YIM: Comment out another unimplemented callback
[centerim.git] / libyahoo2 / libyahoo2.c
blob194a2a9717a700d74eafdd7886f7fec330aad7c7
1 /*
2 * libyahoo2: libyahoo2.c
4 * Some code copyright (C) 2002-2004, Philip S Tellis <philip.tellis AT gmx.net>
6 * Yahoo Search copyright (C) 2003, Konstantin Klyagin <konst AT konst.org.ua>
8 * Much of this code was taken and adapted from the yahoo module for
9 * gaim released under the GNU GPL. This code is also released under the
10 * GNU GPL.
12 * This code is derivitive of Gaim <http://gaim.sourceforge.net>
13 * copyright (C) 1998-1999, Mark Spencer <markster@marko.net>
14 * 1998-1999, Adam Fritzler <afritz@marko.net>
15 * 1998-2002, Rob Flynn <rob@marko.net>
16 * 2000-2002, Eric Warmenhoven <eric@warmenhoven.org>
17 * 2001-2002, Brian Macke <macke@strangelove.net>
18 * 2001, Anand Biligiri S <abiligiri@users.sf.net>
19 * 2001, Valdis Kletnieks
20 * 2002, Sean Egan <bj91704@binghamton.edu>
21 * 2002, Toby Gray <toby.gray@ntlworld.com>
23 * This library also uses code from other libraries, namely:
24 * Portions from libfaim copyright 1998, 1999 Adam Fritzler
25 * <afritz@auk.cx>
26 * Portions of Sylpheed copyright 2000-2002 Hiroyuki Yamamoto
27 * <hiro-y@kcn.ne.jp>
30 * This program is free software; you can redistribute it and/or modify
31 * it under the terms of the GNU General Public License as published by
32 * the Free Software Foundation; either version 2 of the License, or
33 * (at your option) any later version.
35 * This program is distributed in the hope that it will be useful,
36 * but WITHOUT ANY WARRANTY; without even the implied warranty of
37 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38 * GNU General Public License for more details.
40 * You should have received a copy of the GNU General Public License
41 * along with this program; if not, write to the Free Software
42 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
46 #if HAVE_CONFIG_H
47 # include <config.h>
48 #endif
50 #include <unistd.h>
51 #include <errno.h>
52 #include <stdio.h>
53 #include <stdarg.h>
55 #if STDC_HEADERS
56 # include <string.h>
57 #else
58 # if !HAVE_STRCHR
59 # define strchr index
60 # define strrchr rindex
61 # endif
62 char *strchr (), *strrchr ();
63 # if !HAVE_MEMCPY
64 # define memcpy(d, s, n) bcopy ((s), (d), (n))
65 # define memmove(d, s, n) bcopy ((s), (d), (n))
66 # endif
67 #endif
69 #include <sys/types.h>
71 #ifdef __MINGW32__
72 # include <winsock2.h>
73 # define write(a,b,c) send(a,b,c,0)
74 # define read(a,b,c) recv(a,b,c,0)
75 #endif
77 #include <stdlib.h>
78 #include <ctype.h>
80 #include "sha.h"
81 #include "md5.h"
82 #include "yahoo2.h"
83 #include "yahoo_httplib.h"
84 #include "yahoo_util.h"
85 #include "yahoo_auth.h"
87 #include "yahoo2_callbacks.h"
88 #include "yahoo_debug.h"
89 #ifdef __MINGW32__
90 #define snprintf _snprintf
91 #define vsnprintf _vsnprintf
92 #endif
94 #ifdef USE_STRUCT_CALLBACKS
95 struct yahoo_callbacks *yc=NULL;
97 static int yahoo_send_data(int fd, void *data, int len);
99 void yahoo_register_callbacks(struct yahoo_callbacks * tyc)
101 yc = tyc;
104 #define YAHOO_CALLBACK(x) yc->x
105 #else
106 #define YAHOO_CALLBACK(x) x
107 #endif
109 int yahoo_log_message(char * fmt, ...)
111 char out[1024];
112 va_list ap;
113 va_start(ap, fmt);
114 vsnprintf(out, sizeof(out), fmt, ap);
115 va_end(ap);
116 return YAHOO_CALLBACK(ext_yahoo_log)("%s", out);
119 int yahoo_connect(char * host, int port)
121 return YAHOO_CALLBACK(ext_yahoo_connect)(host, port);
124 static enum yahoo_log_level log_level = YAHOO_LOG_NONE;
126 enum yahoo_log_level yahoo_get_log_level()
128 return log_level;
131 int yahoo_set_log_level(enum yahoo_log_level level)
133 enum yahoo_log_level l = log_level;
134 log_level = level;
135 return l;
138 /* default values for servers */
139 static char pager_host[] = "scs.msg.yahoo.com";
140 static int pager_port = 5050;
141 static int fallback_ports[]={23, 25, 80, 20, 119, 8001, 8002, 5050, 0};
142 static char filetransfer_host[]="filetransfer.msg.yahoo.com";
143 static int filetransfer_port=80;
144 static char webcam_host[]="webcam.yahoo.com";
145 static int webcam_port=5100;
146 static char webcam_description[]="";
147 static char local_host[]="";
148 static int conn_type=Y_WCM_DSL;
150 static char profile_url[] = "http://profiles.yahoo.com/";
152 enum yahoo_service { /* these are easier to see in hex */
153 YAHOO_SERVICE_LOGON = 1,
154 YAHOO_SERVICE_LOGOFF,
155 YAHOO_SERVICE_ISAWAY,
156 YAHOO_SERVICE_ISBACK,
157 YAHOO_SERVICE_IDLE, /* 5 (placemarker) */
158 YAHOO_SERVICE_MESSAGE,
159 YAHOO_SERVICE_IDACT,
160 YAHOO_SERVICE_IDDEACT,
161 YAHOO_SERVICE_MAILSTAT,
162 YAHOO_SERVICE_USERSTAT, /* 0xa */
163 YAHOO_SERVICE_NEWMAIL,
164 YAHOO_SERVICE_CHATINVITE,
165 YAHOO_SERVICE_CALENDAR,
166 YAHOO_SERVICE_NEWPERSONALMAIL,
167 YAHOO_SERVICE_NEWCONTACT,
168 YAHOO_SERVICE_ADDIDENT, /* 0x10 */
169 YAHOO_SERVICE_ADDIGNORE,
170 YAHOO_SERVICE_PING,
171 YAHOO_SERVICE_GOTGROUPRENAME, /* < 1, 36(old), 37(new) */
172 YAHOO_SERVICE_SYSMESSAGE = 0x14,
173 YAHOO_SERVICE_PASSTHROUGH2 = 0x16,
174 YAHOO_SERVICE_CONFINVITE = 0x18,
175 YAHOO_SERVICE_CONFLOGON,
176 YAHOO_SERVICE_CONFDECLINE,
177 YAHOO_SERVICE_CONFLOGOFF,
178 YAHOO_SERVICE_CONFADDINVITE,
179 YAHOO_SERVICE_CONFMSG,
180 YAHOO_SERVICE_CHATLOGON,
181 YAHOO_SERVICE_CHATLOGOFF,
182 YAHOO_SERVICE_CHATMSG = 0x20,
183 YAHOO_SERVICE_GAMELOGON = 0x28,
184 YAHOO_SERVICE_GAMELOGOFF,
185 YAHOO_SERVICE_GAMEMSG = 0x2a,
186 YAHOO_SERVICE_FILETRANSFER = 0x46,
187 YAHOO_SERVICE_VOICECHAT = 0x4A,
188 YAHOO_SERVICE_NOTIFY,
189 YAHOO_SERVICE_VERIFY,
190 YAHOO_SERVICE_P2PFILEXFER,
191 YAHOO_SERVICE_PEERTOPEER = 0x4F, /* Checks if P2P possible */
192 YAHOO_SERVICE_WEBCAM,
193 YAHOO_SERVICE_AUTHRESP = 0x54,
194 YAHOO_SERVICE_LIST,
195 YAHOO_SERVICE_AUTH = 0x57,
196 YAHOO_SERVICE_ADDBUDDY = 0x83,
197 YAHOO_SERVICE_REMBUDDY,
198 YAHOO_SERVICE_IGNORECONTACT, /* > 1, 7, 13 < 1, 66, 13, 0*/
199 YAHOO_SERVICE_REJECTCONTACT,
200 YAHOO_SERVICE_GROUPRENAME = 0x89, /* > 1, 65(new), 66(0), 67(old) */
201 YAHOO_SERVICE_CHATONLINE = 0x96, /* > 109(id), 1, 6(abcde) < 0,1*/
202 YAHOO_SERVICE_CHATGOTO,
203 YAHOO_SERVICE_CHATJOIN, /* > 1 104-room 129-1600326591 62-2 */
204 YAHOO_SERVICE_CHATLEAVE,
205 YAHOO_SERVICE_CHATEXIT = 0x9b,
206 YAHOO_SERVICE_CHATLOGOUT = 0xa0,
207 YAHOO_SERVICE_CHATPING,
208 YAHOO_SERVICE_COMMENT = 0xa8,
209 YAHOO_SERVICE_STEALTH = 0xb9,
210 YAHOO_SERVICE_PICTURE_CHECKSUM = 0xbd,
211 YAHOO_SERVICE_PICTURE = 0xbe,
212 YAHOO_SERVICE_PICTURE_UPDATE = 0xc1,
213 YAHOO_SERVICE_PICTURE_UPLOAD = 0xc2,
214 YAHOO_SERVICE_Y6_STATUS_UPDATE = 0xc6,
215 YAHOO_SERVICE_STATUS_15 = 0xf0
218 struct yahoo_pair {
219 int key;
220 char *value;
223 struct yahoo_packet {
224 unsigned short int service;
225 unsigned int status;
226 unsigned int id;
227 YList *hash;
230 struct yahoo_search_state {
231 int lsearch_type;
232 char *lsearch_text;
233 int lsearch_gender;
234 int lsearch_agerange;
235 int lsearch_photo;
236 int lsearch_yahoo_only;
237 int lsearch_nstart;
238 int lsearch_nfound;
239 int lsearch_ntotal;
242 struct data_queue {
243 unsigned char *queue;
244 int len;
247 struct yahoo_input_data {
248 struct yahoo_data *yd;
249 struct yahoo_webcam *wcm;
250 struct yahoo_webcam_data *wcd;
251 struct yahoo_search_state *ys;
253 int fd;
254 enum yahoo_connection_type type;
256 unsigned char *rxqueue;
257 int rxlen;
258 int read_tag;
260 YList *txqueues;
261 int write_tag;
264 struct yahoo_server_settings {
265 char *pager_host;
266 int pager_port;
267 char *filetransfer_host;
268 int filetransfer_port;
269 char *webcam_host;
270 int webcam_port;
271 char *webcam_description;
272 char *local_host;
273 int conn_type;
276 static void * _yahoo_default_server_settings()
278 struct yahoo_server_settings *yss = y_new0(struct yahoo_server_settings, 1);
280 yss->pager_host = strdup(pager_host);
281 yss->pager_port = pager_port;
282 yss->filetransfer_host = strdup(filetransfer_host);
283 yss->filetransfer_port = filetransfer_port;
284 yss->webcam_host = strdup(webcam_host);
285 yss->webcam_port = webcam_port;
286 yss->webcam_description = strdup(webcam_description);
287 yss->local_host = strdup(local_host);
288 yss->conn_type = conn_type;
290 return yss;
293 static void * _yahoo_assign_server_settings(va_list ap)
295 struct yahoo_server_settings *yss = _yahoo_default_server_settings();
296 char *key;
297 char *svalue;
298 int nvalue;
300 while(1) {
301 key = va_arg(ap, char *);
302 if(key == NULL)
303 break;
305 if(!strcmp(key, "pager_host")) {
306 svalue = va_arg(ap, char *);
307 free(yss->pager_host);
308 yss->pager_host = strdup(svalue);
309 } else if(!strcmp(key, "pager_port")) {
310 nvalue = va_arg(ap, int);
311 yss->pager_port = nvalue;
312 } else if(!strcmp(key, "filetransfer_host")) {
313 svalue = va_arg(ap, char *);
314 free(yss->filetransfer_host);
315 yss->filetransfer_host = strdup(svalue);
316 } else if(!strcmp(key, "filetransfer_port")) {
317 nvalue = va_arg(ap, int);
318 yss->filetransfer_port = nvalue;
319 } else if(!strcmp(key, "webcam_host")) {
320 svalue = va_arg(ap, char *);
321 free(yss->webcam_host);
322 yss->webcam_host = strdup(svalue);
323 } else if(!strcmp(key, "webcam_port")) {
324 nvalue = va_arg(ap, int);
325 yss->webcam_port = nvalue;
326 } else if(!strcmp(key, "webcam_description")) {
327 svalue = va_arg(ap, char *);
328 free(yss->webcam_description);
329 yss->webcam_description = strdup(svalue);
330 } else if(!strcmp(key, "local_host")) {
331 svalue = va_arg(ap, char *);
332 free(yss->local_host);
333 yss->local_host = strdup(svalue);
334 } else if(!strcmp(key, "conn_type")) {
335 nvalue = va_arg(ap, int);
336 yss->conn_type = nvalue;
337 } else {
338 WARNING(("Unknown key passed to yahoo_init, "
339 "perhaps you didn't terminate the list "
340 "with NULL"));
344 return yss;
347 static void yahoo_free_server_settings(struct yahoo_server_settings *yss)
349 if(!yss)
350 return;
352 free(yss->pager_host);
353 free(yss->filetransfer_host);
354 free(yss->webcam_host);
355 free(yss->webcam_description);
356 free(yss->local_host);
358 free(yss);
361 static YList *conns=NULL;
362 static YList *inputs=NULL;
363 static int last_id=0;
365 static void add_to_list(struct yahoo_data *yd)
367 conns = y_list_prepend(conns, yd);
369 static struct yahoo_data * find_conn_by_id(int id)
371 YList *l;
372 for(l = conns; l; l = y_list_next(l)) {
373 struct yahoo_data *yd = l->data;
374 if(yd->client_id == id)
375 return yd;
377 return NULL;
379 static void del_from_list(struct yahoo_data *yd)
381 conns = y_list_remove(conns, yd);
384 /* call repeatedly to get the next one */
386 static struct yahoo_input_data * find_input_by_id(int id)
388 YList *l;
389 for(l = inputs; l; l = y_list_next(l)) {
390 struct yahoo_input_data *yid = l->data;
391 if(yid->yd->client_id == id)
392 return yid;
394 return NULL;
398 static struct yahoo_input_data * find_input_by_id_and_webcam_user(int id, const char * who)
400 YList *l;
401 LOG(("find_input_by_id_and_webcam_user"));
402 for(l = inputs; l; l = y_list_next(l)) {
403 struct yahoo_input_data *yid = l->data;
404 if(yid->type == YAHOO_CONNECTION_WEBCAM && yid->yd->client_id == id
405 && yid->wcm &&
406 ((who && yid->wcm->user && !strcmp(who, yid->wcm->user)) ||
407 !(yid->wcm->user && !who)))
408 return yid;
410 return NULL;
413 static struct yahoo_input_data * find_input_by_id_and_type(int id, enum yahoo_connection_type type)
415 YList *l;
416 LOG(("find_input_by_id_and_type"));
417 for(l = inputs; l; l = y_list_next(l)) {
418 struct yahoo_input_data *yid = l->data;
419 if(yid->type == type && yid->yd->client_id == id)
420 return yid;
422 return NULL;
425 static struct yahoo_input_data * find_input_by_id_and_fd(int id, int fd)
427 YList *l;
428 LOG(("find_input_by_id_and_fd"));
429 for(l = inputs; l; l = y_list_next(l)) {
430 struct yahoo_input_data *yid = l->data;
431 if(yid->fd == fd && yid->yd->client_id == id)
432 return yid;
434 return NULL;
437 static int count_inputs_with_id(int id)
439 int c=0;
440 YList *l;
441 LOG(("counting %d", id));
442 for(l = inputs; l; l = y_list_next(l)) {
443 struct yahoo_input_data *yid = l->data;
444 if(yid->yd->client_id == id)
445 c++;
447 LOG(("%d", c));
448 return c;
452 extern char *yahoo_crypt(char *, char *);
454 /* Free a buddy list */
455 static void yahoo_free_buddies(YList * list)
457 YList *l;
459 for(l = list; l; l = l->next)
461 struct yahoo_buddy *bud = l->data;
462 if(!bud)
463 continue;
465 FREE(bud->group);
466 FREE(bud->id);
467 FREE(bud->real_name);
468 if(bud->yab_entry) {
469 FREE(bud->yab_entry->fname);
470 FREE(bud->yab_entry->lname);
471 FREE(bud->yab_entry->nname);
472 FREE(bud->yab_entry->id);
473 FREE(bud->yab_entry->email);
474 FREE(bud->yab_entry->hphone);
475 FREE(bud->yab_entry->wphone);
476 FREE(bud->yab_entry->mphone);
477 FREE(bud->yab_entry);
479 FREE(bud);
480 l->data = bud = NULL;
483 y_list_free(list);
486 /* Free an identities list */
487 static void yahoo_free_identities(YList * list)
489 while (list) {
490 YList *n = list;
491 FREE(list->data);
492 list = y_list_remove_link(list, list);
493 y_list_free_1(n);
497 /* Free webcam data */
498 static void yahoo_free_webcam(struct yahoo_webcam *wcm)
500 if (wcm) {
501 FREE(wcm->user);
502 FREE(wcm->server);
503 FREE(wcm->key);
504 FREE(wcm->description);
505 FREE(wcm->my_ip);
507 FREE(wcm);
510 static void yahoo_free_data(struct yahoo_data *yd)
512 FREE(yd->user);
513 FREE(yd->password);
514 FREE(yd->cookie_y);
515 FREE(yd->cookie_t);
516 FREE(yd->cookie_c);
517 FREE(yd->login_cookie);
518 FREE(yd->login_id);
520 yahoo_free_buddies(yd->buddies);
521 yahoo_free_buddies(yd->ignore);
522 yahoo_free_identities(yd->identities);
524 yahoo_free_server_settings(yd->server_settings);
526 FREE(yd);
529 #define YAHOO_PACKET_HDRLEN (4 + 2 + 2 + 2 + 2 + 4 + 4)
531 static struct yahoo_packet *yahoo_packet_new(enum yahoo_service service,
532 enum yahoo_status status, int id)
534 struct yahoo_packet *pkt = y_new0(struct yahoo_packet, 1);
536 pkt->service = service;
537 pkt->status = status;
538 pkt->id = id;
540 return pkt;
543 static void yahoo_packet_hash(struct yahoo_packet *pkt, int key, const char *value)
545 struct yahoo_pair *pair = y_new0(struct yahoo_pair, 1);
546 pair->key = key;
547 pair->value = strdup(value);
548 pkt->hash = y_list_append(pkt->hash, pair);
551 static int yahoo_packet_length(struct yahoo_packet *pkt)
553 YList *l;
555 int len = 0;
557 for (l = pkt->hash; l; l = l->next) {
558 struct yahoo_pair *pair = l->data;
559 int tmp = pair->key;
560 do {
561 tmp /= 10;
562 len++;
563 } while (tmp);
564 len += 2;
565 len += strlen(pair->value);
566 len += 2;
569 return len;
572 #define yahoo_put16(buf, data) ( \
573 (*(buf) = (unsigned char)((data)>>8)&0xff), \
574 (*((buf)+1) = (unsigned char)(data)&0xff), \
576 #define yahoo_get16(buf) ((((*(buf))&0xff)<<8) + ((*((buf)+1)) & 0xff))
577 #define yahoo_put32(buf, data) ( \
578 (*((buf)) = (unsigned char)((data)>>24)&0xff), \
579 (*((buf)+1) = (unsigned char)((data)>>16)&0xff), \
580 (*((buf)+2) = (unsigned char)((data)>>8)&0xff), \
581 (*((buf)+3) = (unsigned char)(data)&0xff), \
583 #define yahoo_get32(buf) ((((*(buf) )&0xff)<<24) + \
584 (((*((buf)+1))&0xff)<<16) + \
585 (((*((buf)+2))&0xff)<< 8) + \
586 (((*((buf)+3))&0xff)))
588 static void yahoo_packet_read(struct yahoo_packet *pkt, unsigned char *data, int len)
590 int pos = 0;
592 while (pos + 1 < len) {
593 char *key, *value = NULL;
594 int accept;
595 int x;
597 struct yahoo_pair *pair = y_new0(struct yahoo_pair, 1);
599 key = malloc(len + 1);
600 x = 0;
601 while (pos + 1 < len) {
602 if (data[pos] == 0xc0 && data[pos + 1] == 0x80)
603 break;
604 key[x++] = data[pos++];
606 key[x] = 0;
607 pos += 2;
608 pair->key = strtol(key, NULL, 10);
609 free(key);
611 accept = x;
612 /* if x is 0 there was no key, so don't accept it */
613 if (accept)
614 value = malloc(len - pos + 1);
615 x = 0;
616 while (pos + 1 < len) {
617 if (data[pos] == 0xc0 && data[pos + 1] == 0x80)
618 break;
619 if (accept)
620 value[x++] = data[pos++];
622 if (accept)
623 value[x] = 0;
624 pos += 2;
625 if (accept) {
626 pair->value = strdup(value);
627 FREE(value);
628 pkt->hash = y_list_append(pkt->hash, pair);
629 DEBUG_MSG(("Key: %d \tValue: %s", pair->key, pair->value));
630 } else {
631 FREE(pair);
636 static void yahoo_packet_write(struct yahoo_packet *pkt, unsigned char *data)
638 YList *l;
639 int pos = 0;
641 for (l = pkt->hash; l; l = l->next) {
642 struct yahoo_pair *pair = l->data;
643 unsigned char buf[100];
645 snprintf((char *)buf, sizeof(buf), "%d", pair->key);
646 strcpy((char *)data + pos, (char *)buf);
647 pos += strlen((char *)buf);
648 data[pos++] = 0xc0;
649 data[pos++] = 0x80;
651 strcpy((char *)data + pos, pair->value);
652 pos += strlen(pair->value);
653 data[pos++] = 0xc0;
654 data[pos++] = 0x80;
658 static void yahoo_dump_unhandled(struct yahoo_packet *pkt)
660 YList *l;
662 NOTICE(("Service: 0x%02x\tStatus: %d", pkt->service, pkt->status));
663 for (l = pkt->hash; l; l = l->next) {
664 struct yahoo_pair *pair = l->data;
665 NOTICE(("\t%d => %s", pair->key, pair->value));
670 static void yahoo_packet_dump(unsigned char *data, int len)
672 if(yahoo_get_log_level() >= YAHOO_LOG_DEBUG) {
673 int i;
674 for (i = 0; i < len; i++) {
675 if ((i % 8 == 0) && i)
676 YAHOO_CALLBACK(ext_yahoo_log)(" ");
677 if ((i % 16 == 0) && i)
678 YAHOO_CALLBACK(ext_yahoo_log)("\n");
679 YAHOO_CALLBACK(ext_yahoo_log)("%02x ", data[i]);
681 YAHOO_CALLBACK(ext_yahoo_log)("\n");
682 for (i = 0; i < len; i++) {
683 if ((i % 8 == 0) && i)
684 YAHOO_CALLBACK(ext_yahoo_log)(" ");
685 if ((i % 16 == 0) && i)
686 YAHOO_CALLBACK(ext_yahoo_log)("\n");
687 if (isprint(data[i]))
688 YAHOO_CALLBACK(ext_yahoo_log)(" %c ", data[i]);
689 else
690 YAHOO_CALLBACK(ext_yahoo_log)(" . ");
692 YAHOO_CALLBACK(ext_yahoo_log)("\n");
696 static char base64digits[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
697 "abcdefghijklmnopqrstuvwxyz"
698 "0123456789._";
699 static void to_y64(unsigned char *out, const unsigned char *in, int inlen)
700 /* raw bytes in quasi-big-endian order to base 64 string (NUL-terminated) */
702 for (; inlen >= 3; inlen -= 3)
704 *out++ = base64digits[in[0] >> 2];
705 *out++ = base64digits[((in[0]<<4) & 0x30) | (in[1]>>4)];
706 *out++ = base64digits[((in[1]<<2) & 0x3c) | (in[2]>>6)];
707 *out++ = base64digits[in[2] & 0x3f];
708 in += 3;
710 if (inlen > 0)
712 unsigned char fragment;
714 *out++ = base64digits[in[0] >> 2];
715 fragment = (in[0] << 4) & 0x30;
716 if (inlen > 1)
717 fragment |= in[1] >> 4;
718 *out++ = base64digits[fragment];
719 *out++ = (inlen < 2) ? '-'
720 : base64digits[(in[1] << 2) & 0x3c];
721 *out++ = '-';
723 *out = '\0';
726 static void yahoo_add_to_send_queue(struct yahoo_input_data *yid, void *data, int length)
728 struct data_queue *tx = y_new0(struct data_queue, 1);
729 tx->queue = y_new0(unsigned char, length);
730 tx->len = length;
731 memcpy(tx->queue, data, length);
733 yid->txqueues = y_list_append(yid->txqueues, tx);
735 if(!yid->write_tag)
736 yid->write_tag=YAHOO_CALLBACK(ext_yahoo_add_handler)(yid->yd->client_id, yid->fd, YAHOO_INPUT_WRITE, yid);
739 static void yahoo_send_packet(struct yahoo_input_data *yid, struct yahoo_packet *pkt, int extra_pad)
741 int pktlen = yahoo_packet_length(pkt);
742 int len = YAHOO_PACKET_HDRLEN + pktlen;
744 unsigned char *data;
745 int pos = 0;
747 if (yid->fd < 0)
748 return;
750 data = y_new0(unsigned char, len + 1);
752 memcpy(data + pos, "YMSG", 4); pos += 4;
753 pos += yahoo_put16(data + pos, 0x000f);
754 pos += yahoo_put16(data + pos, 0x0000);
755 pos += yahoo_put16(data + pos, pktlen + extra_pad);
756 pos += yahoo_put16(data + pos, pkt->service);
757 pos += yahoo_put32(data + pos, pkt->status);
758 pos += yahoo_put32(data + pos, pkt->id);
760 yahoo_packet_write(pkt, data + pos);
762 yahoo_packet_dump(data, len);
764 if( yid->type == YAHOO_CONNECTION_FT )
765 yahoo_send_data(yid->fd, data, len);
766 else
767 yahoo_add_to_send_queue(yid, data, len);
768 FREE(data);
771 static void yahoo_packet_free(struct yahoo_packet *pkt)
773 while (pkt->hash) {
774 struct yahoo_pair *pair = pkt->hash->data;
775 YList *tmp;
776 FREE(pair->value);
777 FREE(pair);
778 tmp = pkt->hash;
779 pkt->hash = y_list_remove_link(pkt->hash, pkt->hash);
780 y_list_free_1(tmp);
782 FREE(pkt);
785 static int yahoo_send_data(int fd, void *data, int len)
787 int ret;
788 int e;
790 if (fd < 0)
791 return -1;
793 yahoo_packet_dump(data, len);
795 do {
796 ret = write(fd, data, len);
797 } while(ret == -1 && errno==EINTR);
798 e=errno;
800 if (ret == -1) {
801 LOG(("wrote data: ERR %s", strerror(errno)));
802 } else {
803 LOG(("wrote data: OK"));
806 errno=e;
807 return ret;
810 void yahoo_close(int id)
812 struct yahoo_data *yd = find_conn_by_id(id);
813 if(!yd)
814 return;
816 del_from_list(yd);
818 yahoo_free_data(yd);
819 if(id == last_id)
820 last_id--;
823 static void yahoo_input_close(struct yahoo_input_data *yid)
825 inputs = y_list_remove(inputs, yid);
827 LOG(("yahoo_input_close(read)"));
828 YAHOO_CALLBACK(ext_yahoo_remove_handler)(yid->yd->client_id, yid->read_tag);
829 LOG(("yahoo_input_close(write)"));
830 YAHOO_CALLBACK(ext_yahoo_remove_handler)(yid->yd->client_id, yid->write_tag);
831 yid->read_tag = yid->write_tag = 0;
832 if(yid->fd)
833 close(yid->fd);
834 yid->fd = 0;
835 FREE(yid->rxqueue);
836 if(count_inputs_with_id(yid->yd->client_id) == 0) {
837 LOG(("closing %d", yid->yd->client_id));
838 yahoo_close(yid->yd->client_id);
840 yahoo_free_webcam(yid->wcm);
841 if(yid->wcd)
842 FREE(yid->wcd);
843 if(yid->ys) {
844 FREE(yid->ys->lsearch_text);
845 FREE(yid->ys);
847 FREE(yid);
850 static int is_same_bud(const void * a, const void * b) {
851 const struct yahoo_buddy *subject = a;
852 const struct yahoo_buddy *object = b;
854 return strcmp(subject->id, object->id);
857 static YList * bud_str2list(char *rawlist)
859 YList * l = NULL;
861 char **lines;
862 char **split;
863 char **buddies;
864 char **tmp, **bud;
866 lines = y_strsplit(rawlist, "\n", -1);
867 for (tmp = lines; *tmp; tmp++) {
868 struct yahoo_buddy *newbud;
870 split = y_strsplit(*tmp, ":", 2);
871 if (!split)
872 continue;
873 if (!split[0] || !split[1]) {
874 y_strfreev(split);
875 continue;
877 buddies = y_strsplit(split[1], ",", -1);
879 for (bud = buddies; bud && *bud; bud++) {
880 newbud = y_new0(struct yahoo_buddy, 1);
881 newbud->id = strdup(*bud);
882 newbud->group = strdup(split[0]);
884 if(y_list_find_custom(l, newbud, is_same_bud)) {
885 FREE(newbud->id);
886 FREE(newbud->group);
887 FREE(newbud);
888 continue;
891 newbud->real_name = NULL;
893 l = y_list_append(l, newbud);
895 NOTICE(("Added buddy %s to group %s", newbud->id, newbud->group));
898 y_strfreev(buddies);
899 y_strfreev(split);
901 y_strfreev(lines);
903 return l;
906 static char * getcookie(char *rawcookie)
908 char * cookie=NULL;
909 char * tmpcookie;
910 char * cookieend;
912 if (strlen(rawcookie) < 2)
913 return NULL;
915 tmpcookie = strdup(rawcookie+2);
916 cookieend = strchr(tmpcookie, ';');
918 if(cookieend)
919 *cookieend = '\0';
921 cookie = strdup(tmpcookie);
922 FREE(tmpcookie);
923 /* cookieend=NULL; not sure why this was there since the value is not preserved in the stack -dd */
925 return cookie;
928 static char * getlcookie(char *cookie)
930 char *tmp;
931 char *tmpend;
932 char *login_cookie = NULL;
934 tmpend = strstr(cookie, "n=");
935 if(tmpend) {
936 tmp = strdup(tmpend+2);
937 tmpend = strchr(tmp, '&');
938 if(tmpend)
939 *tmpend='\0';
940 login_cookie = strdup(tmp);
941 FREE(tmp);
944 return login_cookie;
947 static void yahoo_process_notify(struct yahoo_input_data *yid, struct yahoo_packet *pkt)
949 struct yahoo_data *yd = yid->yd;
950 char *msg = NULL;
951 char *from = NULL;
952 char *to = NULL;
953 int stat = 0;
954 int accept = 0;
955 char *ind = NULL;
956 YList *l;
957 for (l = pkt->hash; l; l = l->next) {
958 struct yahoo_pair *pair = l->data;
959 if (pair->key == 4)
960 from = pair->value;
961 if (pair->key == 5)
962 to = pair->value;
963 if (pair->key == 49)
964 msg = pair->value;
965 if (pair->key == 13)
966 stat = atoi(pair->value);
967 if (pair->key == 14)
968 ind = pair->value;
969 if (pair->key == 16) { /* status == -1 */
970 NOTICE((pair->value));
971 return;
976 if (!msg)
977 return;
979 if (!strncasecmp(msg, "TYPING", strlen("TYPING")))
980 YAHOO_CALLBACK(ext_yahoo_typing_notify)(yd->client_id, to, from, stat);
981 else if (!strncasecmp(msg, "GAME", strlen("GAME")))
982 YAHOO_CALLBACK(ext_yahoo_game_notify)(yd->client_id, to, from, stat);
983 else if (!strncasecmp(msg, "WEBCAMINVITE", strlen("WEBCAMINVITE")))
985 if (!strcmp(ind, " ")) {
986 YAHOO_CALLBACK(ext_yahoo_webcam_invite)(yd->client_id, to, from);
987 } else {
988 accept = atoi(ind);
989 /* accept the invitation (-1 = deny 1 = accept) */
990 if (accept < 0)
991 accept = 0;
992 YAHOO_CALLBACK(ext_yahoo_webcam_invite_reply)(yd->client_id, to, from, accept);
995 else
996 LOG(("Got unknown notification: %s", msg));
999 static void yahoo_process_filetransfer(struct yahoo_input_data *yid, struct yahoo_packet *pkt)
1001 struct yahoo_data *yd = yid->yd;
1002 char *from=NULL;
1003 char *to=NULL;
1004 char *msg=NULL;
1005 char *url=NULL;
1006 long expires=0;
1008 char *service=NULL;
1010 char *filename=NULL;
1011 unsigned long filesize=0L;
1013 YList *l;
1014 for (l = pkt->hash; l; l = l->next) {
1015 struct yahoo_pair *pair = l->data;
1016 if (pair->key == 4)
1017 from = pair->value;
1018 if (pair->key == 5)
1019 to = pair->value;
1020 if (pair->key == 14)
1021 msg = pair->value;
1022 if (pair->key == 20)
1023 url = pair->value;
1024 if (pair->key == 38)
1025 expires = atol(pair->value);
1027 if (pair->key == 27)
1028 filename = pair->value;
1029 if (pair->key == 28)
1030 filesize = atol(pair->value);
1032 if (pair->key == 49)
1033 service = pair->value;
1036 if(pkt->service == YAHOO_SERVICE_P2PFILEXFER) {
1037 if(strcmp("FILEXFER", service) != 0) {
1038 WARNING(("unhandled service 0x%02x", pkt->service));
1039 yahoo_dump_unhandled(pkt);
1040 return;
1044 if(msg) {
1045 char *tmp;
1046 tmp = strchr(msg, '\006');
1047 if(tmp)
1048 *tmp = '\0';
1050 if(url && from)
1051 YAHOO_CALLBACK(ext_yahoo_got_file)(yd->client_id, to, from, url, expires, msg, filename, filesize);
1055 static void yahoo_process_conference(struct yahoo_input_data *yid, struct yahoo_packet *pkt)
1057 struct yahoo_data *yd = yid->yd;
1058 char *msg = NULL;
1059 char *host = NULL;
1060 char *who = NULL;
1061 char *room = NULL;
1062 char *id = NULL;
1063 int utf8 = 0;
1064 YList *members = NULL;
1065 YList *l;
1067 for (l = pkt->hash; l; l = l->next) {
1068 struct yahoo_pair *pair = l->data;
1069 if (pair->key == 50)
1070 host = pair->value;
1072 if (pair->key == 52) { /* invite */
1073 members = y_list_append(members, strdup(pair->value));
1075 if (pair->key == 53) /* logon */
1076 who = pair->value;
1077 if (pair->key == 54) /* decline */
1078 who = pair->value;
1079 if (pair->key == 55) /* unavailable (status == 2) */
1080 who = pair->value;
1081 if (pair->key == 56) /* logoff */
1082 who = pair->value;
1084 if (pair->key == 57)
1085 room = pair->value;
1087 if (pair->key == 58) /* join message */
1088 msg = pair->value;
1089 if (pair->key == 14) /* decline/conf message */
1090 msg = pair->value;
1092 if (pair->key == 13)
1094 if (pair->key == 16) /* error */
1095 msg = pair->value;
1097 if (pair->key == 1) /* my id */
1098 id = pair->value;
1099 if (pair->key == 3) /* message sender */
1100 who = pair->value;
1102 if (pair->key == 97)
1103 utf8 = atoi(pair->value);
1106 if(!room)
1107 return;
1109 if(host) {
1110 for(l = members; l; l = l->next) {
1111 char * w = l->data;
1112 if(!strcmp(w, host))
1113 break;
1115 if(!l)
1116 members = y_list_append(members, strdup(host));
1118 /* invite, decline, join, left, message -> status == 1 */
1120 switch(pkt->service) {
1121 case YAHOO_SERVICE_CONFINVITE:
1122 if(pkt->status == 2)
1124 else if(members)
1125 YAHOO_CALLBACK(ext_yahoo_got_conf_invite)(yd->client_id, host, room, msg, members);
1126 else if(msg)
1127 YAHOO_CALLBACK(ext_yahoo_error)(yd->client_id, msg, 0, E_CONFNOTAVAIL);
1128 break;
1129 case YAHOO_SERVICE_CONFADDINVITE:
1130 if(pkt->status == 2)
1132 else
1133 YAHOO_CALLBACK(ext_yahoo_got_conf_invite)(yd->client_id, host, room, msg, members);
1134 break;
1135 case YAHOO_SERVICE_CONFDECLINE:
1136 if(who)
1137 YAHOO_CALLBACK(ext_yahoo_conf_userdecline)(yd->client_id, who, room, msg);
1138 break;
1139 case YAHOO_SERVICE_CONFLOGON:
1140 if(who)
1141 YAHOO_CALLBACK(ext_yahoo_conf_userjoin)(yd->client_id, who, room);
1142 break;
1143 case YAHOO_SERVICE_CONFLOGOFF:
1144 if(who)
1145 YAHOO_CALLBACK(ext_yahoo_conf_userleave)(yd->client_id, who, room);
1146 break;
1147 case YAHOO_SERVICE_CONFMSG:
1148 if(who)
1149 YAHOO_CALLBACK(ext_yahoo_conf_message)(yd->client_id, who, room, msg, utf8);
1150 break;
1154 static void yahoo_process_chat(struct yahoo_input_data *yid, struct yahoo_packet *pkt)
1156 char *msg = NULL;
1157 char *who = NULL;
1158 char *room = NULL;
1159 char *topic = NULL;
1160 YList *members = NULL;
1161 struct yahoo_chat_member *currentmember = NULL;
1162 int msgtype = 1;
1163 int utf8 = 0;
1164 int firstjoin = 0;
1165 int membercount = 0;
1166 int chaterr=0;
1167 YList *l;
1169 yahoo_dump_unhandled(pkt);
1170 for (l = pkt->hash; l; l = l->next) {
1171 struct yahoo_pair *pair = l->data;
1173 if (pair->key == 104) {
1174 /* Room name */
1175 room = pair->value;
1178 if (pair->key == 105) {
1179 /* Room topic */
1180 topic = pair->value;
1183 if (pair->key == 108) {
1184 /* Number of members in this packet */
1185 membercount = atoi(pair->value);
1188 if (pair->key == 109) {
1189 /* message sender */
1190 who = pair->value;
1192 if (pkt->service == YAHOO_SERVICE_CHATJOIN) {
1193 currentmember = y_new0(struct yahoo_chat_member, 1);
1194 currentmember->id = strdup(pair->value);
1195 members = y_list_append(members, currentmember);
1199 if (pair->key == 110) {
1200 /* age */
1201 if (pkt->service == YAHOO_SERVICE_CHATJOIN)
1202 currentmember->age = atoi(pair->value);
1205 if (pair->key == 113) {
1206 /* attribs */
1207 if (pkt->service == YAHOO_SERVICE_CHATJOIN)
1208 currentmember->attribs = atoi(pair->value);
1211 if (pair->key == 141) {
1212 /* alias */
1213 if (pkt->service == YAHOO_SERVICE_CHATJOIN)
1214 currentmember->alias = strdup(pair->value);
1217 if (pair->key == 142) {
1218 /* location */
1219 if (pkt->service == YAHOO_SERVICE_CHATJOIN)
1220 currentmember->location = strdup(pair->value);
1224 if (pair->key == 130) {
1225 /* first join */
1226 firstjoin = 1;
1229 if (pair->key == 117) {
1230 /* message */
1231 msg = pair->value;
1234 if (pair->key == 124) {
1235 /* Message type */
1236 msgtype = atoi(pair->value);
1238 if (pair->key == 114) {
1239 /* message error not sure what all the pair values mean */
1240 /* but -1 means no session in room */
1241 chaterr= atoi(pair->value);
1245 if(!room) {
1246 if (pkt->service == YAHOO_SERVICE_CHATLOGOUT) { /* yahoo originated chat logout */
1247 YAHOO_CALLBACK(ext_yahoo_chat_yahoologout)(yid->yd->client_id);
1248 return ;
1250 if (pkt->service == YAHOO_SERVICE_COMMENT && chaterr) {
1251 YAHOO_CALLBACK(ext_yahoo_chat_yahooerror)(yid->yd->client_id);
1252 return;
1255 WARNING(("We didn't get a room name, ignoring packet"));
1256 return;
1259 switch(pkt->service) {
1260 case YAHOO_SERVICE_CHATJOIN:
1261 if(y_list_length(members) != membercount) {
1262 WARNING(("Count of members doesn't match No. of members we got"));
1264 if(firstjoin && members) {
1265 YAHOO_CALLBACK(ext_yahoo_chat_join)(yid->yd->client_id, room, topic, members, yid->fd);
1266 } else if(who) {
1267 if(y_list_length(members) != 1) {
1268 WARNING(("Got more than 1 member on a normal join"));
1270 /* this should only ever have one, but just in case */
1271 while(members) {
1272 YList *n = members->next;
1273 currentmember = members->data;
1274 YAHOO_CALLBACK(ext_yahoo_chat_userjoin)(yid->yd->client_id, room, currentmember);
1275 y_list_free_1(members);
1276 members=n;
1279 break;
1280 case YAHOO_SERVICE_CHATEXIT:
1281 if(who) {
1282 YAHOO_CALLBACK(ext_yahoo_chat_userleave)(yid->yd->client_id, room, who);
1284 break;
1285 case YAHOO_SERVICE_COMMENT:
1286 if(who) {
1287 YAHOO_CALLBACK(ext_yahoo_chat_message)(yid->yd->client_id, who, room, msg, msgtype, utf8);
1289 break;
1293 static void yahoo_process_message(struct yahoo_input_data *yid, struct yahoo_packet *pkt)
1295 struct yahoo_data *yd = yid->yd;
1296 YList *l;
1297 YList * messages = NULL;
1299 struct m {
1300 int i_31;
1301 int i_32;
1302 char *to;
1303 char *from;
1304 long tm;
1305 char *msg;
1306 int utf8;
1307 } *message = y_new0(struct m, 1);
1309 for (l = pkt->hash; l; l = l->next) {
1310 struct yahoo_pair *pair = l->data;
1311 if (pair->key == 1 || pair->key == 4)
1313 if(!message->from)
1314 message->from = pair->value;
1316 else if (pair->key == 5)
1317 message->to = pair->value;
1318 else if (pair->key == 15)
1319 message->tm = strtol(pair->value, NULL, 10);
1320 else if (pair->key == 97)
1321 message->utf8 = atoi(pair->value);
1322 /* user message */ /* sys message */
1323 else if (pair->key == 14 || pair->key == 16)
1324 message->msg = pair->value;
1325 else if (pair->key == 31) {
1326 if(message->i_31) {
1327 messages = y_list_append(messages, message);
1328 message = y_new0(struct m, 1);
1330 message->i_31 = atoi(pair->value);
1332 else if (pair->key == 32)
1333 message->i_32 = atoi(pair->value);
1334 else
1335 LOG(("yahoo_process_message: status: %d, key: %d, value: %s",
1336 pkt->status, pair->key, pair->value));
1339 messages = y_list_append(messages, message);
1341 for (l = messages; l; l=l->next) {
1342 message = l->data;
1343 if (pkt->service == YAHOO_SERVICE_SYSMESSAGE) {
1344 YAHOO_CALLBACK(ext_yahoo_system_message)(yd->client_id, message->msg);
1345 } else if (pkt->status <= 2 || pkt->status == 5) {
1346 YAHOO_CALLBACK(ext_yahoo_got_im)(yd->client_id, message->to, message->from, message->msg, message->tm, pkt->status, message->utf8);
1347 } else if (pkt->status == 0xffffffff) {
1348 YAHOO_CALLBACK(ext_yahoo_error)(yd->client_id, message->msg, 0, E_SYSTEM);
1350 free(message);
1353 y_list_free(messages);
1357 static void yahoo_process_status(struct yahoo_input_data *yid, struct yahoo_packet *pkt)
1359 YList *l;
1360 struct yahoo_data *yd = yid->yd;
1362 struct user
1364 char *name; /* 7 name */
1365 int state; /* 10 state */
1366 int flags; /* 13 flags, bit 0 = pager, bit 1 = chat, bit 2 = game */
1367 int mobile; /* 60 mobile */
1368 char *msg; /* 19 custom status message */
1369 int away; /* 47 away (or invisible)*/
1370 int buddy_session; /* 11 state */
1371 int f17; /* 17 in chat? then what about flags? */
1372 int idle; /* 137 seconds idle */
1373 int f138; /* 138 state */
1374 char *f184; /* 184 state */
1375 int f192; /* 192 state */
1376 int f10001; /* 10001 state */
1377 int f10002; /* 10002 state */
1378 int f198; /* 198 state */
1379 char *f197; /* 197 state */
1380 char *f205; /* 205 state */
1381 int f213; /* 213 state */
1382 } *u;
1384 YList *users = 0;
1386 if (pkt->service == YAHOO_SERVICE_LOGOFF && pkt->status == -1) {
1387 YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, YAHOO_LOGIN_DUPL, NULL);
1388 return;
1391 for (l = pkt->hash; l; l = l->next) {
1392 struct yahoo_pair *pair = l->data;
1394 switch (pair->key) {
1395 case 0: /* we won't actually do anything with this */
1396 NOTICE(("key %d:%s", pair->key, pair->value));
1397 break;
1398 case 1: /* we don't get the full buddy list here. */
1399 if (!yd->logged_in) {
1400 yd->logged_in = TRUE;
1401 if(yd->current_status < 0)
1402 yd->current_status = yd->initial_status;
1403 YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, YAHOO_LOGIN_OK, NULL);
1405 break;
1406 case 8: /* how many online buddies we have */
1407 NOTICE(("key %d:%s", pair->key, pair->value));
1408 break;
1409 case 7: /* the current buddy */
1410 u = y_new0(struct user, 1);
1411 u->name = pair->value;
1412 users = y_list_prepend(users, u);
1413 break;
1414 case 10: /* state */
1415 ((struct user*)users->data)->state = strtol(pair->value, NULL, 10);
1416 break;
1417 case 19: /* custom status message */
1418 ((struct user*)users->data)->msg = pair->value;
1419 break;
1420 case 47: /* is it an away message or not */
1421 ((struct user*)users->data)->away = atoi(pair->value);
1422 break;
1423 case 137: /* seconds idle */
1424 ((struct user*)users->data)->idle = atoi(pair->value);
1425 break;
1426 case 11: /* this is the buddy's session id */
1427 ((struct user*)users->data)->buddy_session = atoi(pair->value);
1428 break;
1429 case 17: /* in chat? */
1430 ((struct user*)users->data)->f17 = atoi(pair->value);
1431 break;
1432 case 13: /* bitmask, bit 0 = pager, bit 1 = chat, bit 2 = game */
1433 ((struct user*)users->data)->flags = atoi(pair->value);
1434 break;
1435 case 60: /* SMS -> 1 MOBILE USER */
1436 /* sometimes going offline makes this 2, but invisible never sends it */
1437 ((struct user*)users->data)->mobile = atoi(pair->value);
1438 break;
1439 case 138:
1440 ((struct user*)users->data)->f138 = atoi(pair->value);
1441 break;
1442 case 184:
1443 ((struct user*)users->data)->f184 = pair->value;
1444 break;
1445 case 192:
1446 ((struct user*)users->data)->f192 = atoi(pair->value);
1447 break;
1448 case 10001:
1449 ((struct user*)users->data)->f10001 = atoi(pair->value);
1450 break;
1451 case 10002:
1452 ((struct user*)users->data)->f10002 = atoi(pair->value);
1453 break;
1454 case 198:
1455 ((struct user*)users->data)->f198 = atoi(pair->value);
1456 break;
1457 case 197:
1458 ((struct user*)users->data)->f197 = pair->value;
1459 break;
1460 case 205:
1461 ((struct user*)users->data)->f205 = pair->value;
1462 break;
1463 case 213:
1464 ((struct user*)users->data)->f213 = atoi(pair->value);
1465 break;
1466 case 16: /* Custom error message */
1467 YAHOO_CALLBACK(ext_yahoo_error)(yd->client_id, pair->value, 0, E_CUSTOM);
1468 break;
1469 default:
1470 WARNING(("unknown status key %d:%s", pair->key, pair->value));
1471 break;
1475 while (users) {
1476 YList *t = users;
1477 struct user *u = users->data;
1479 if (u->name != NULL) {
1480 if (pkt->service == YAHOO_SERVICE_LOGOFF || u->flags == 0) {
1481 YAHOO_CALLBACK(ext_yahoo_status_changed)(yd->client_id, u->name, YAHOO_STATUS_OFFLINE, NULL, 1, 0, 0);
1482 } else {
1483 YAHOO_CALLBACK(ext_yahoo_status_changed)(yd->client_id, u->name, u->state, u->msg, u->away, u->idle, u->mobile);
1487 users = y_list_remove_link(users, users);
1488 y_list_free_1(t);
1489 FREE(u);
1493 static void yahoo_process_list(struct yahoo_input_data *yid, struct yahoo_packet *pkt)
1495 struct yahoo_data *yd = yid->yd;
1496 YList *l;
1498 if (!yd->logged_in) {
1499 yd->logged_in = TRUE;
1500 if(yd->current_status < 0)
1501 yd->current_status = yd->initial_status;
1502 YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, YAHOO_LOGIN_OK, NULL);
1504 pkt = yahoo_packet_new(YAHOO_SERVICE_Y6_STATUS_UPDATE, YAHOO_STATUS_AVAILABLE, 0);
1506 char buff[20];
1508 snprintf(buff, sizeof(buff)-1, "%d", yd->current_status);
1509 yahoo_packet_hash(pkt, 10, buff);
1510 yahoo_packet_hash(pkt, 19, "");
1511 yahoo_send_packet(yid, pkt, 0);
1513 yahoo_packet_free(pkt);
1516 for (l = pkt->hash; l; l = l->next) {
1517 struct yahoo_pair *pair = l->data;
1519 switch(pair->key) {
1520 case 87: /* buddies */
1521 if(!yd->rawbuddylist)
1522 yd->rawbuddylist = strdup(pair->value);
1523 else {
1524 yd->rawbuddylist = y_string_append(yd->rawbuddylist, pair->value);
1526 break;
1528 case 88: /* ignore list */
1529 if(!yd->ignorelist)
1530 yd->ignorelist = strdup("Ignore:");
1531 yd->ignorelist = y_string_append(yd->ignorelist, pair->value);
1532 break;
1534 case 89: /* identities */
1536 char **identities = y_strsplit(pair->value, ",", -1);
1537 int i;
1538 for(i=0; identities[i]; i++)
1539 yd->identities = y_list_append(yd->identities,
1540 strdup(identities[i]));
1541 y_strfreev(identities);
1543 YAHOO_CALLBACK(ext_yahoo_got_identities)(yd->client_id, yd->identities);
1544 break;
1545 case 59: /* cookies */
1546 if(yd->ignorelist) {
1547 yd->ignore = bud_str2list(yd->ignorelist);
1548 FREE(yd->ignorelist);
1549 YAHOO_CALLBACK(ext_yahoo_got_ignore)(yd->client_id, yd->ignore);
1551 if(yd->rawbuddylist) {
1552 yd->buddies = bud_str2list(yd->rawbuddylist);
1553 FREE(yd->rawbuddylist);
1554 YAHOO_CALLBACK(ext_yahoo_got_buddies)(yd->client_id, yd->buddies);
1557 if(pair->value[0]=='Y') {
1558 FREE(yd->cookie_y);
1559 FREE(yd->login_cookie);
1561 yd->cookie_y = getcookie(pair->value);
1562 yd->login_cookie = getlcookie(yd->cookie_y);
1564 } else if(pair->value[0]=='T') {
1565 FREE(yd->cookie_t);
1566 yd->cookie_t = getcookie(pair->value);
1568 } else if(pair->value[0]=='C') {
1569 FREE(yd->cookie_c);
1570 yd->cookie_c = getcookie(pair->value);
1573 if(yd->cookie_y && yd->cookie_t && yd->cookie_c)
1574 YAHOO_CALLBACK(ext_yahoo_got_cookies)(yd->client_id);
1576 break;
1577 case 3: /* my id */
1578 case 90: /* 1 */
1579 case 100: /* 0 */
1580 case 101: /* NULL */
1581 case 102: /* NULL */
1582 case 93: /* 86400/1440 */
1583 break;
1588 static void yahoo_process_verify(struct yahoo_input_data *yid, struct yahoo_packet *pkt)
1590 struct yahoo_data *yd = yid->yd;
1592 if(pkt->status != 0x01) {
1593 DEBUG_MSG(("expected status: 0x01, got: %d", pkt->status));
1594 YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, YAHOO_LOGIN_LOCK, "");
1595 return;
1598 pkt = yahoo_packet_new(YAHOO_SERVICE_AUTH, YAHOO_STATUS_AVAILABLE, yd->session_id);
1600 yahoo_packet_hash(pkt, 1, yd->user);
1601 yahoo_send_packet(yid, pkt, 0);
1603 yahoo_packet_free(pkt);
1607 static void yahoo_process_picture_checksum( struct yahoo_input_data *yid, struct yahoo_packet *pkt)
1609 struct yahoo_data *yd = yid->yd;
1610 char *from;
1611 char *to;
1612 int checksum = 0;
1613 YList *l;
1615 for(l = pkt->hash; l; l = l->next)
1617 struct yahoo_pair *pair = l->data;
1619 switch(pair->key)
1621 case 1:
1622 case 4:
1623 from = pair->value;
1624 case 5:
1625 to = pair->value;
1626 break;
1627 case 212:
1628 break;
1629 case 192:
1630 checksum = atoi( pair->value );
1631 break;
1635 //YAHOO_CALLBACK(ext_yahoo_got_buddyicon_checksum)(yd->client_id,to,from,checksum);
1638 static void yahoo_process_picture(struct yahoo_input_data *yid, struct yahoo_packet *pkt)
1640 struct yahoo_data *yd = yid->yd;
1641 char *url;
1642 char *from;
1643 char *to;
1644 int status = 0;
1645 int checksum = 0;
1646 YList *l;
1648 for(l = pkt->hash; l; l = l->next)
1650 struct yahoo_pair *pair = l->data;
1652 switch(pair->key)
1654 case 1:
1655 case 4: /* sender */
1656 from = pair->value;
1657 break;
1658 case 5: /* we */
1659 to = pair->value;
1660 break;
1661 case 13: /* request / sending */
1662 status = atoi( pair->value );
1663 break;
1664 case 20: /* url */
1665 url = pair->value;
1666 break;
1667 case 192: /*checksum */
1668 checksum = atoi( pair->value );
1669 break;
1673 switch( status )
1675 case 1: /* this is a request, ignore for now */
1676 YAHOO_CALLBACK(ext_yahoo_got_buddyicon_request)(yd->client_id, to, from);
1677 break;
1678 case 2: /* this is cool - we get a picture :) */
1679 YAHOO_CALLBACK(ext_yahoo_got_buddyicon)(yd->client_id,to, from, url, checksum);
1680 break;
1684 static void yahoo_process_picture_upload(struct yahoo_input_data *yid, struct yahoo_packet *pkt)
1686 struct yahoo_data *yd = yid->yd;
1687 YList *l;
1688 char *url;
1690 if ( pkt->status != 1 )
1691 return; /* something went wrong */
1693 for(l = pkt->hash; l; l = l->next)
1695 struct yahoo_pair *pair = l->data;
1697 switch(pair->key)
1699 case 5: /* we */
1700 break;
1701 case 20: /* url */
1702 url = pair->value;
1703 break;
1704 case 27: /* local filename */
1705 break;
1706 case 38: /* time */
1707 break;
1711 YAHOO_CALLBACK(ext_yahoo_buddyicon_uploaded)(yd->client_id, url);
1714 static void yahoo_process_auth_pre_0x0b(struct yahoo_input_data *yid,
1715 const char *seed, const char *sn)
1717 struct yahoo_data *yd = yid->yd;
1719 /* So, Yahoo has stopped supporting its older clients in India, and
1720 * undoubtedly will soon do so in the rest of the world.
1722 * The new clients use this authentication method. I warn you in
1723 * advance, it's bizzare, convoluted, inordinately complicated.
1724 * It's also no more secure than crypt() was. The only purpose this
1725 * scheme could serve is to prevent third part clients from connecting
1726 * to their servers.
1728 * Sorry, Yahoo.
1731 struct yahoo_packet *pack;
1733 md5_byte_t result[16];
1734 md5_state_t ctx;
1735 char *crypt_result;
1736 unsigned char *password_hash = malloc(25);
1737 unsigned char *crypt_hash = malloc(25);
1738 unsigned char *hash_string_p = malloc(50 + strlen(sn));
1739 unsigned char *hash_string_c = malloc(50 + strlen(sn));
1741 char checksum;
1743 int sv;
1745 unsigned char *result6 = malloc(25);
1746 unsigned char *result96 = malloc(25);
1748 sv = seed[15];
1749 sv = (sv % 8) % 5;
1751 md5_init(&ctx);
1752 md5_append(&ctx, (md5_byte_t *)yd->password, strlen(yd->password));
1753 md5_finish(&ctx, result);
1754 to_y64(password_hash, result, 16);
1756 md5_init(&ctx);
1757 crypt_result = yahoo_crypt(yd->password, "$1$_2S43d5f$");
1758 md5_append(&ctx, (md5_byte_t *)crypt_result, strlen(crypt_result));
1759 md5_finish(&ctx, result);
1760 to_y64(crypt_hash, result, 16);
1761 free(crypt_result);
1763 switch (sv) {
1764 case 0:
1765 checksum = seed[seed[7] % 16];
1766 snprintf((char *)hash_string_p, strlen(sn) + 50,
1767 "%c%s%s%s", checksum, password_hash, yd->user, seed);
1768 snprintf((char *)hash_string_c, strlen(sn) + 50,
1769 "%c%s%s%s", checksum, crypt_hash, yd->user, seed);
1770 break;
1771 case 1:
1772 checksum = seed[seed[9] % 16];
1773 snprintf((char *)hash_string_p, strlen(sn) + 50,
1774 "%c%s%s%s", checksum, yd->user, seed, password_hash);
1775 snprintf((char *)hash_string_c, strlen(sn) + 50,
1776 "%c%s%s%s", checksum, yd->user, seed, crypt_hash);
1777 break;
1778 case 2:
1779 checksum = seed[seed[15] % 16];
1780 snprintf((char *)hash_string_p, strlen(sn) + 50,
1781 "%c%s%s%s", checksum, seed, password_hash, yd->user);
1782 snprintf((char *)hash_string_c, strlen(sn) + 50,
1783 "%c%s%s%s", checksum, seed, crypt_hash, yd->user);
1784 break;
1785 case 3:
1786 checksum = seed[seed[1] % 16];
1787 snprintf((char *)hash_string_p, strlen(sn) + 50,
1788 "%c%s%s%s", checksum, yd->user, password_hash, seed);
1789 snprintf((char *)hash_string_c, strlen(sn) + 50,
1790 "%c%s%s%s", checksum, yd->user, crypt_hash, seed);
1791 break;
1792 case 4:
1793 checksum = seed[seed[3] % 16];
1794 snprintf((char *)hash_string_p, strlen(sn) + 50,
1795 "%c%s%s%s", checksum, password_hash, seed, yd->user);
1796 snprintf((char *)hash_string_c, strlen(sn) + 50,
1797 "%c%s%s%s", checksum, crypt_hash, seed, yd->user);
1798 break;
1801 md5_init(&ctx);
1802 md5_append(&ctx, (md5_byte_t *)hash_string_p, strlen((char *)hash_string_p));
1803 md5_finish(&ctx, result);
1804 to_y64(result6, result, 16);
1806 md5_init(&ctx);
1807 md5_append(&ctx, (md5_byte_t *)hash_string_c, strlen((char *)hash_string_c));
1808 md5_finish(&ctx, result);
1809 to_y64(result96, result, 16);
1811 pack = yahoo_packet_new(YAHOO_SERVICE_AUTHRESP, yd->initial_status, yd->session_id);
1812 yahoo_packet_hash(pack, 0, yd->user);
1813 yahoo_packet_hash(pack, 6, (char *)result6);
1814 yahoo_packet_hash(pack, 96, (char *)result96);
1815 yahoo_packet_hash(pack, 1, yd->user);
1817 yahoo_send_packet(yid, pack, 0);
1819 FREE(result6);
1820 FREE(result96);
1821 FREE(password_hash);
1822 FREE(crypt_hash);
1823 FREE(hash_string_p);
1824 FREE(hash_string_c);
1826 yahoo_packet_free(pack);
1831 * New auth protocol cracked by Cerulean Studios and sent in to Gaim
1833 static void yahoo_process_auth_0x0b(struct yahoo_input_data *yid, const char *seed, const char *sn)
1835 struct yahoo_packet *pack = NULL;
1836 struct yahoo_data *yd = yid->yd;
1838 md5_byte_t result[16];
1839 md5_state_t ctx;
1841 SHA1Context ctx1;
1842 SHA1Context ctx2;
1844 char *alphabet1 = "FBZDWAGHrJTLMNOPpRSKUVEXYChImkwQ";
1845 char *alphabet2 = "F0E1D2C3B4A59687abcdefghijklmnop";
1847 char *challenge_lookup = "qzec2tb3um1olpar8whx4dfgijknsvy5";
1848 char *operand_lookup = "+|&%/*^-";
1849 char *delimit_lookup = ",;";
1851 unsigned char *password_hash = malloc(25);
1852 unsigned char *crypt_hash = malloc(25);
1853 char *crypt_result = NULL;
1855 unsigned char pass_hash_xor1[64];
1856 unsigned char pass_hash_xor2[64];
1857 unsigned char crypt_hash_xor1[64];
1858 unsigned char crypt_hash_xor2[64];
1859 char resp_6[100];
1860 char resp_96[100];
1862 unsigned char digest1[20];
1863 unsigned char digest2[20];
1864 unsigned char comparison_src[20];
1865 unsigned char magic_key_char[4];
1866 const char *magic_ptr;
1868 unsigned int magic[64];
1869 unsigned int magic_work=0;
1870 unsigned int magic_4 = 0;
1873 int x, y;
1874 int cnt = 0;
1875 int magic_cnt = 0;
1876 int magic_len;
1878 memset(password_hash, 0, 25);
1879 memset(crypt_hash, 0, 25);
1880 memset(&pass_hash_xor1, 0, 64);
1881 memset(&pass_hash_xor2, 0, 64);
1882 memset(&crypt_hash_xor1, 0, 64);
1883 memset(&crypt_hash_xor2, 0, 64);
1884 memset(&digest1, 0, 20);
1885 memset(&digest2, 0, 20);
1886 memset(&magic, 0, 64);
1887 memset(&resp_6, 0, 100);
1888 memset(&resp_96, 0, 100);
1889 memset(&magic_key_char, 0, 4);
1890 memset(&comparison_src, 0, 20);
1893 * Magic: Phase 1. Generate what seems to be a 30
1894 * byte value (could change if base64
1895 * ends up differently? I don't remember and I'm
1896 * tired, so use a 64 byte buffer.
1899 magic_ptr = seed;
1901 while (*magic_ptr != (int)NULL) {
1902 char *loc;
1904 /* Ignore parentheses. */
1906 if (*magic_ptr == '(' || *magic_ptr == ')') {
1907 magic_ptr++;
1908 continue;
1911 /* Characters and digits verify against
1912 the challenge lookup.
1915 if (isalpha(*magic_ptr) || isdigit(*magic_ptr)) {
1916 loc = strchr(challenge_lookup, *magic_ptr);
1917 if (!loc) {
1918 /* This isn't good */
1919 //continue;
1922 /* Get offset into lookup table and lsh 3. */
1924 magic_work = loc - challenge_lookup;
1925 magic_work <<= 3;
1927 magic_ptr++;
1928 continue;
1929 } else {
1930 unsigned int local_store;
1932 loc = strchr(operand_lookup, *magic_ptr);
1933 if (!loc) {
1934 /* Also not good. */
1935 //continue;
1938 local_store = loc - operand_lookup;
1940 /* Oops; how did this happen? */
1941 if (magic_cnt >= 64)
1942 break;
1944 magic[magic_cnt++] = magic_work | local_store;
1945 magic_ptr++;
1946 continue;
1950 magic_len = magic_cnt;
1951 magic_cnt = 0;
1953 /* Magic: Phase 2. Take generated magic value and
1954 * sprinkle fairy dust on the values. */
1956 for (magic_cnt = magic_len-2; magic_cnt >= 0; magic_cnt--) {
1957 unsigned char byte1;
1958 unsigned char byte2;
1960 /* Bad. Abort. */
1961 if ((magic_cnt >= magic_len)) {
1962 WARNING(("magic_cnt(%d) magic_len(%d)", magic_cnt, magic_len))
1963 break;
1966 byte1 = magic[magic_cnt];
1967 byte2 = magic[magic_cnt+1];
1969 byte1 *= 0xcd;
1970 byte1 ^= byte2;
1972 magic[magic_cnt+1] = byte1;
1976 * Magic: Phase 3. This computes 20 bytes. The first 4 bytes are used as our magic
1977 * key (and may be changed later); the next 16 bytes are an MD5 sum of the magic key
1978 * plus 3 bytes. The 3 bytes are found by looping, and they represent the offsets
1979 * into particular functions we'll later call to potentially alter the magic key.
1981 * %-)
1984 magic_cnt = 1;
1985 x = 0;
1987 do {
1988 unsigned int bl = 0;
1989 unsigned int cl = magic[magic_cnt++];
1991 if (magic_cnt >= magic_len)
1992 break;
1994 if (cl > 0x7F) {
1995 if (cl < 0xe0)
1996 bl = cl = (cl & 0x1f) << 6;
1997 else {
1998 bl = magic[magic_cnt++];
1999 cl = (cl & 0x0f) << 6;
2000 bl = ((bl & 0x3f) + cl) << 6;
2003 cl = magic[magic_cnt++];
2004 bl = (cl & 0x3f) + bl;
2005 } else
2006 bl = cl;
2008 comparison_src[x++] = (bl & 0xff00) >> 8;
2009 comparison_src[x++] = bl & 0xff;
2010 } while (x < 20);
2012 /* First four bytes are magic key. */
2013 memcpy(&magic_key_char[0], comparison_src, 4);
2014 magic_4 = magic_key_char[0] | (magic_key_char[1] << 8) |
2015 (magic_key_char[2] << 16) | (magic_key_char[3] << 24);
2018 * Magic: Phase 4. Determine what function to use later by getting outside/inside
2019 * loop values until we match our previous buffer.
2021 for (x = 0; x < 65535; x++) {
2022 int leave = 0;
2024 for (y = 0; y < 5; y++) {
2025 unsigned char test[3];
2027 /* Calculate buffer. */
2028 test[0] = x;
2029 test[1] = x >> 8;
2030 test[2] = y;
2032 md5_init( &ctx );
2033 md5_append( &ctx, magic_key_char, 4 );
2034 md5_append( &ctx, test, 3 );
2035 md5_finish( &ctx, result );
2038 if( memcmp( comparison_src + 4, result, 16 ) == 0 ) {
2039 leave = 1;
2040 break;
2044 if (leave == 1)
2045 break;
2048 /* If y != 0, we need some help. */
2049 if (y != 0) {
2050 unsigned int updated_key;
2052 /* Update magic stuff.
2053 * Call it twice because Yahoo's encryption is super bad ass.
2055 updated_key = yahoo_auth_finalCountdown(magic_4, 0x60, y, x);
2056 updated_key = yahoo_auth_finalCountdown(updated_key, 0x60, y, x);
2058 magic_key_char[0] = updated_key & 0xff;
2059 magic_key_char[1] = (updated_key >> 8) & 0xff;
2060 magic_key_char[2] = (updated_key >> 16) & 0xff;
2061 magic_key_char[3] = (updated_key >> 24) & 0xff;
2064 /* Get password and crypt hashes as per usual. */
2065 md5_init(&ctx);
2066 md5_append(&ctx, (md5_byte_t *)yd->password, strlen(yd->password));
2067 md5_finish(&ctx, result);
2069 to_y64(password_hash, result, 16);
2071 crypt_result = yahoo_crypt(yd->password, "$1$_2S43d5f$");
2073 md5_init(&ctx);
2074 md5_append(&ctx, (md5_byte_t *)crypt_result, strlen(crypt_result));
2075 md5_finish(&ctx, result);
2076 to_y64(crypt_hash, result, 16);
2077 free(crypt_result);
2079 /* Our first authentication response is based off
2080 * of the password hash. */
2082 for (x = 0; x < (int)strlen((char *)password_hash); x++)
2083 pass_hash_xor1[cnt++] = password_hash[x] ^ 0x36;
2085 if (cnt < 64)
2086 memset(&(pass_hash_xor1[cnt]), 0x36, 64-cnt);
2088 cnt = 0;
2090 for (x = 0; x < (int)strlen((char *)password_hash); x++)
2091 pass_hash_xor2[cnt++] = password_hash[x] ^ 0x5c;
2093 if (cnt < 64)
2094 memset(&(pass_hash_xor2[cnt]), 0x5c, 64-cnt);
2096 SHA1Init(&ctx1);
2097 SHA1Init(&ctx2);
2099 /* The first context gets the password hash XORed
2100 * with 0x36 plus a magic value
2101 * which we previously extrapolated from our
2102 * challenge. */
2104 SHA1Update(&ctx1, pass_hash_xor1, 64);
2105 if (y >= 3)
2106 ctx1.totalLength = 0x1ff;
2107 SHA1Update(&ctx1, magic_key_char, 4);
2108 SHA1Final(&ctx1, digest1);
2110 /* The second context gets the password hash XORed
2111 * with 0x5c plus the SHA-1 digest
2112 * of the first context. */
2114 SHA1Update(&ctx2, pass_hash_xor2, 64);
2115 SHA1Update(&ctx2, digest1, 20);
2116 SHA1Final(&ctx2, digest2);
2118 /* Now that we have digest2, use it to fetch
2119 * characters from an alphabet to construct
2120 * our first authentication response. */
2122 for (x = 0; x < 20; x += 2) {
2123 unsigned int val = 0;
2124 unsigned int lookup = 0;
2126 char byte[6];
2128 memset(&byte, 0, 6);
2130 /* First two bytes of digest stuffed
2131 * together.
2134 val = digest2[x];
2135 val <<= 8;
2136 val += digest2[x+1];
2138 lookup = (val >> 0x0b);
2139 lookup &= 0x1f;
2140 if (lookup >= strlen(alphabet1))
2141 break;
2142 sprintf(byte, "%c", alphabet1[lookup]);
2143 strcat(resp_6, byte);
2144 strcat(resp_6, "=");
2146 lookup = (val >> 0x06);
2147 lookup &= 0x1f;
2148 if (lookup >= strlen(alphabet2))
2149 break;
2150 sprintf(byte, "%c", alphabet2[lookup]);
2151 strcat(resp_6, byte);
2153 lookup = (val >> 0x01);
2154 lookup &= 0x1f;
2155 if (lookup >= strlen(alphabet2))
2156 break;
2157 sprintf(byte, "%c", alphabet2[lookup]);
2158 strcat(resp_6, byte);
2160 lookup = (val & 0x01);
2161 if (lookup >= strlen(delimit_lookup))
2162 break;
2163 sprintf(byte, "%c", delimit_lookup[lookup]);
2164 strcat(resp_6, byte);
2167 /* Our second authentication response is based off
2168 * of the crypto hash. */
2170 cnt = 0;
2171 memset(&digest1, 0, 20);
2172 memset(&digest2, 0, 20);
2174 for (x = 0; x < (int)strlen((char *)crypt_hash); x++)
2175 crypt_hash_xor1[cnt++] = crypt_hash[x] ^ 0x36;
2177 if (cnt < 64)
2178 memset(&(crypt_hash_xor1[cnt]), 0x36, 64-cnt);
2180 cnt = 0;
2182 for (x = 0; x < (int)strlen((char *)crypt_hash); x++)
2183 crypt_hash_xor2[cnt++] = crypt_hash[x] ^ 0x5c;
2185 if (cnt < 64)
2186 memset(&(crypt_hash_xor2[cnt]), 0x5c, 64-cnt);
2188 SHA1Init(&ctx1);
2189 SHA1Init(&ctx2);
2191 /* The first context gets the password hash XORed
2192 * with 0x36 plus a magic value
2193 * which we previously extrapolated from our
2194 * challenge. */
2196 SHA1Update(&ctx1, crypt_hash_xor1, 64);
2197 if (y >= 3)
2198 ctx1.totalLength = 0x1ff;
2199 SHA1Update(&ctx1, magic_key_char, 4);
2200 SHA1Final(&ctx1, digest1);
2202 /* The second context gets the password hash XORed
2203 * with 0x5c plus the SHA-1 digest
2204 * of the first context. */
2206 SHA1Update(&ctx2, crypt_hash_xor2, 64);
2207 SHA1Update(&ctx2, digest1, 20);
2208 SHA1Final(&ctx2, digest2);
2210 /* Now that we have digest2, use it to fetch
2211 * characters from an alphabet to construct
2212 * our first authentication response. */
2214 for (x = 0; x < 20; x += 2) {
2215 unsigned int val = 0;
2216 unsigned int lookup = 0;
2218 char byte[6];
2220 memset(&byte, 0, 6);
2222 /* First two bytes of digest stuffed
2223 * together. */
2225 val = digest2[x];
2226 val <<= 8;
2227 val += digest2[x+1];
2229 lookup = (val >> 0x0b);
2230 lookup &= 0x1f;
2231 if (lookup >= strlen(alphabet1))
2232 break;
2233 sprintf(byte, "%c", alphabet1[lookup]);
2234 strcat(resp_96, byte);
2235 strcat(resp_96, "=");
2237 lookup = (val >> 0x06);
2238 lookup &= 0x1f;
2239 if (lookup >= strlen(alphabet2))
2240 break;
2241 sprintf(byte, "%c", alphabet2[lookup]);
2242 strcat(resp_96, byte);
2244 lookup = (val >> 0x01);
2245 lookup &= 0x1f;
2246 if (lookup >= strlen(alphabet2))
2247 break;
2248 sprintf(byte, "%c", alphabet2[lookup]);
2249 strcat(resp_96, byte);
2251 lookup = (val & 0x01);
2252 if (lookup >= strlen(delimit_lookup))
2253 break;
2254 sprintf(byte, "%c", delimit_lookup[lookup]);
2255 strcat(resp_96, byte);
2258 pack = yahoo_packet_new(YAHOO_SERVICE_AUTHRESP, yd->initial_status, yd->session_id);
2259 yahoo_packet_hash(pack, 0, sn);
2260 yahoo_packet_hash(pack, 6, resp_6);
2261 yahoo_packet_hash(pack, 96, resp_96);
2262 yahoo_packet_hash(pack, 1, sn);
2263 yahoo_packet_hash(pack, 244, YAHOO_CLIENT_VERSION_ID);
2264 yahoo_packet_hash(pack, 135, YAHOO_CLIENT_VERSION);
2266 yahoo_send_packet(yid, pack, 0);
2267 yahoo_packet_free(pack);
2269 free(password_hash);
2270 free(crypt_hash);
2273 static void yahoo_process_auth(struct yahoo_input_data *yid, struct yahoo_packet *pkt)
2275 char *seed = NULL;
2276 char *sn = NULL;
2277 YList *l = pkt->hash;
2278 int m = 0;
2280 while (l) {
2281 struct yahoo_pair *pair = l->data;
2282 if (pair->key == 94)
2283 seed = pair->value;
2284 if (pair->key == 1)
2285 sn = pair->value;
2286 if (pair->key == 13)
2287 m = atoi(pair->value);
2288 l = l->next;
2291 if (!seed)
2292 return;
2294 switch (m) {
2295 case 0:
2296 yahoo_process_auth_pre_0x0b(yid, seed, sn);
2297 break;
2298 case 1:
2299 case 2:
2300 yahoo_process_auth_0x0b(yid, seed, sn);
2301 break;
2302 default:
2303 /* call error */
2304 WARNING(("unknown auth type %d", m));
2305 yahoo_process_auth_0x0b(yid, seed, sn);
2306 break;
2310 static void yahoo_process_auth_resp(struct yahoo_input_data *yid, struct yahoo_packet *pkt)
2312 struct yahoo_data *yd = yid->yd;
2313 char *login_id;
2314 char *handle;
2315 char *url=NULL;
2316 int login_status=0;
2318 YList *l;
2320 for (l = pkt->hash; l; l = l->next) {
2321 struct yahoo_pair *pair = l->data;
2322 if (pair->key == 0)
2323 login_id = pair->value;
2324 else if (pair->key == 1)
2325 handle = pair->value;
2326 else if (pair->key == 20)
2327 url = pair->value;
2328 else if (pair->key == 66)
2329 login_status = atoi(pair->value);
2332 if(pkt->status == 0xffffffff) {
2333 YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, login_status, url);
2334 /* yahoo_logoff(yd->client_id);*/
2338 static void yahoo_process_mail(struct yahoo_input_data *yid, struct yahoo_packet *pkt)
2340 struct yahoo_data *yd = yid->yd;
2341 char *who = NULL;
2342 char *email = NULL;
2343 char *subj = NULL;
2344 int count = 0;
2345 YList *l;
2347 for (l = pkt->hash; l; l = l->next) {
2348 struct yahoo_pair *pair = l->data;
2349 if (pair->key == 9)
2350 count = strtol(pair->value, NULL, 10);
2351 else if (pair->key == 43)
2352 who = pair->value;
2353 else if (pair->key == 42)
2354 email = pair->value;
2355 else if (pair->key == 18)
2356 subj = pair->value;
2357 else
2358 LOG(("key: %d => value: %s", pair->key, pair->value));
2361 if (who && email && subj) {
2362 char from[1024];
2363 snprintf(from, sizeof(from), "%s (%s)", who, email);
2364 YAHOO_CALLBACK(ext_yahoo_mail_notify)(yd->client_id, from, subj, count);
2365 } else if(count > 0)
2366 YAHOO_CALLBACK(ext_yahoo_mail_notify)(yd->client_id, NULL, NULL, count);
2369 static void yahoo_process_contact(struct yahoo_input_data *yid, struct yahoo_packet *pkt)
2371 struct yahoo_data *yd = yid->yd;
2372 char *id = NULL;
2373 char *who = NULL;
2374 char *msg = NULL;
2375 char *name = NULL;
2376 long tm = 0L;
2377 int state = YAHOO_STATUS_AVAILABLE;
2378 int online = FALSE;
2379 int away = 0;
2380 int idle = 0;
2381 int mobile = 0;
2383 YList *l;
2385 for (l = pkt->hash; l; l = l->next) {
2386 struct yahoo_pair *pair = l->data;
2387 if (pair->key == 1)
2388 id = pair->value;
2389 else if (pair->key == 3)
2390 who = pair->value;
2391 else if (pair->key == 14)
2392 msg = pair->value;
2393 else if (pair->key == 7)
2394 name = pair->value;
2395 else if (pair->key == 10)
2396 state = strtol(pair->value, NULL, 10);
2397 else if (pair->key == 15)
2398 tm = strtol(pair->value, NULL, 10);
2399 else if (pair->key == 13)
2400 online = strtol(pair->value, NULL, 10);
2401 else if (pair->key == 47)
2402 away = strtol(pair->value, NULL, 10);
2403 else if (pair->key == 137)
2404 idle = strtol(pair->value, NULL, 10);
2405 else if (pair->key == 60)
2406 mobile = strtol(pair->value, NULL, 10);
2410 if (id)
2411 YAHOO_CALLBACK(ext_yahoo_contact_added)(yd->client_id, id, who, msg);
2412 else if (name)
2413 YAHOO_CALLBACK(ext_yahoo_status_changed)(yd->client_id, name, state, msg, away, idle, mobile);
2414 else if(pkt->status == 0x07)
2415 YAHOO_CALLBACK(ext_yahoo_rejected)(yd->client_id, who, msg);
2418 static void yahoo_process_buddyadd(struct yahoo_input_data *yid, struct yahoo_packet *pkt)
2420 struct yahoo_data *yd = yid->yd;
2421 char *who = NULL;
2422 char *where = NULL;
2423 int status = 0;
2424 char *me = NULL;
2426 struct yahoo_buddy *bud=NULL;
2428 YList *l;
2429 for (l = pkt->hash; l; l = l->next) {
2430 struct yahoo_pair *pair = l->data;
2431 if (pair->key == 1)
2432 me = pair->value;
2433 if (pair->key == 7)
2434 who = pair->value;
2435 if (pair->key == 65)
2436 where = pair->value;
2437 if (pair->key == 66)
2438 status = strtol(pair->value, NULL, 10);
2441 yahoo_dump_unhandled(pkt);
2443 if(!who)
2444 return;
2445 if(!where)
2446 where = "Unknown";
2448 bud = y_new0(struct yahoo_buddy, 1);
2449 bud->id = strdup(who);
2450 bud->group = strdup(where);
2451 bud->real_name = NULL;
2453 yd->buddies = y_list_append(yd->buddies, bud);
2455 /* YAHOO_CALLBACK(ext_yahoo_status_changed)(yd->client_id, who, status, NULL, (status==YAHOO_STATUS_AVAILABLE?0:1)); */
2458 static void yahoo_process_buddydel(struct yahoo_input_data *yid, struct yahoo_packet *pkt)
2460 struct yahoo_data *yd = yid->yd;
2461 char *who = NULL;
2462 char *where = NULL;
2463 int unk_66 = 0;
2464 char *me = NULL;
2465 struct yahoo_buddy *bud;
2467 YList *buddy;
2469 YList *l;
2470 for (l = pkt->hash; l; l = l->next) {
2471 struct yahoo_pair *pair = l->data;
2472 if (pair->key == 1)
2473 me = pair->value;
2474 else if (pair->key == 7)
2475 who = pair->value;
2476 else if (pair->key == 65)
2477 where = pair->value;
2478 else if (pair->key == 66)
2479 unk_66 = strtol(pair->value, NULL, 10);
2480 else
2481 DEBUG_MSG(("unknown key: %d = %s", pair->key, pair->value));
2484 if(!who || !where)
2485 return;
2487 bud = y_new0(struct yahoo_buddy, 1);
2488 bud->id = strdup(who);
2489 bud->group = strdup(where);
2491 buddy = y_list_find_custom(yd->buddies, bud, is_same_bud);
2493 FREE(bud->id);
2494 FREE(bud->group);
2495 FREE(bud);
2497 if(buddy) {
2498 bud = buddy->data;
2499 yd->buddies = y_list_remove_link(yd->buddies, buddy);
2500 y_list_free_1(buddy);
2502 FREE(bud->id);
2503 FREE(bud->group);
2504 FREE(bud->real_name);
2505 FREE(bud);
2507 bud=NULL;
2511 static void yahoo_process_ignore(struct yahoo_input_data *yid, struct yahoo_packet *pkt)
2513 char *who = NULL;
2514 int status = 0;
2515 char *me = NULL;
2516 int un_ignore = 0;
2518 YList *l;
2519 for (l = pkt->hash; l; l = l->next) {
2520 struct yahoo_pair *pair = l->data;
2521 if (pair->key == 0)
2522 who = pair->value;
2523 if (pair->key == 1)
2524 me = pair->value;
2525 if (pair->key == 13) /* 1 == ignore, 2 == unignore */
2526 un_ignore = strtol(pair->value, NULL, 10);
2527 if (pair->key == 66)
2528 status = strtol(pair->value, NULL, 10);
2533 * status
2534 * 0 - ok
2535 * 2 - already in ignore list, could not add
2536 * 3 - not in ignore list, could not delete
2537 * 12 - is a buddy, could not add
2540 /* if(status)
2541 YAHOO_CALLBACK(ext_yahoo_error)(yd->client_id, who, 0, status);
2545 static void yahoo_process_voicechat(struct yahoo_input_data *yid, struct yahoo_packet *pkt)
2547 char *who = NULL;
2548 char *me = NULL;
2549 char *room = NULL;
2550 char *voice_room = NULL;
2552 YList *l;
2553 for (l = pkt->hash; l; l = l->next) {
2554 struct yahoo_pair *pair = l->data;
2555 if (pair->key == 4)
2556 who = pair->value;
2557 if (pair->key == 5)
2558 me = pair->value;
2559 if (pair->key == 13)
2560 voice_room=pair->value;
2561 if (pair->key == 57)
2562 room=pair->value;
2565 NOTICE(("got voice chat invite from %s in %s to identity %s", who, room, me));
2567 * send: s:0 1:me 5:who 57:room 13:1
2568 * ???? s:4 5:who 10:99 19:-1615114531
2569 * gotr: s:4 5:who 10:99 19:-1615114615
2570 * ???? s:1 5:me 4:who 57:room 13:3room
2571 * got: s:1 5:me 4:who 57:room 13:1room
2572 * rej: s:0 1:me 5:who 57:room 13:3
2573 * rejr: s:4 5:who 10:99 19:-1617114599
2577 static void yahoo_process_ping(struct yahoo_input_data *yid, struct yahoo_packet *pkt)
2579 char *errormsg = NULL;
2581 YList *l;
2582 for (l = pkt->hash; l; l = l->next) {
2583 struct yahoo_pair *pair = l->data;
2584 if (pair->key == 16)
2585 errormsg = pair->value;
2588 NOTICE(("got ping packet"));
2589 //YAHOO_CALLBACK(ext_yahoo_got_ping)(yid->yd->client_id, errormsg);
2592 static void _yahoo_webcam_get_server_connected(int fd, int error, void *d)
2594 struct yahoo_input_data *yid = d;
2595 char *who = yid->wcm->user;
2596 char *data = NULL;
2597 char *packet = NULL;
2598 unsigned char magic_nr[] = {0, 1, 0};
2599 unsigned char header_len = 8;
2600 unsigned int len = 0;
2601 unsigned int pos = 0;
2603 if(error || fd <= 0) {
2604 FREE(who);
2605 FREE(yid);
2606 return;
2609 yid->fd = fd;
2610 inputs = y_list_prepend(inputs, yid);
2612 /* send initial packet */
2613 if (who)
2614 data = strdup("<RVWCFG>");
2615 else
2616 data = strdup("<RUPCFG>");
2617 yahoo_add_to_send_queue(yid, data, strlen(data));
2618 FREE(data);
2620 /* send data */
2621 if (who)
2623 data = strdup("g=");
2624 data = y_string_append(data, who);
2625 data = y_string_append(data, "\r\n");
2626 } else {
2627 data = strdup("f=1\r\n");
2629 len = strlen(data);
2630 packet = y_new0(char, header_len + len);
2631 packet[pos++] = header_len;
2632 memcpy(packet + pos, magic_nr, sizeof(magic_nr));
2633 pos += sizeof(magic_nr);
2634 pos += yahoo_put32(packet + pos, len);
2635 memcpy(packet + pos, data, len);
2636 pos += len;
2637 yahoo_add_to_send_queue(yid, packet, pos);
2638 FREE(packet);
2639 FREE(data);
2641 yid->read_tag=YAHOO_CALLBACK(ext_yahoo_add_handler)(yid->yd->client_id, fd, YAHOO_INPUT_READ, yid);
2644 static void yahoo_webcam_get_server(struct yahoo_input_data *y, char *who, char *key)
2646 struct yahoo_input_data *yid = y_new0(struct yahoo_input_data, 1);
2647 struct yahoo_server_settings *yss = y->yd->server_settings;
2649 yid->type = YAHOO_CONNECTION_WEBCAM_MASTER;
2650 yid->yd = y->yd;
2651 yid->wcm = y_new0(struct yahoo_webcam, 1);
2652 yid->wcm->user = who?strdup(who):NULL;
2653 yid->wcm->direction = who?YAHOO_WEBCAM_DOWNLOAD:YAHOO_WEBCAM_UPLOAD;
2654 yid->wcm->key = strdup(key);
2656 YAHOO_CALLBACK(ext_yahoo_connect_async)(yid->yd->client_id, yss->webcam_host, yss->webcam_port,
2657 _yahoo_webcam_get_server_connected, yid);
2661 static YList *webcam_queue=NULL;
2662 static void yahoo_process_webcam_key(struct yahoo_input_data *yid, struct yahoo_packet *pkt)
2664 char *me = NULL;
2665 char *key = NULL;
2666 char *who = NULL;
2668 YList *l;
2669 yahoo_dump_unhandled(pkt);
2670 for (l = pkt->hash; l; l = l->next) {
2671 struct yahoo_pair *pair = l->data;
2672 if (pair->key == 5)
2673 me = pair->value;
2674 if (pair->key == 61)
2675 key=pair->value;
2678 l = webcam_queue;
2679 if(!l)
2680 return;
2681 who = l->data;
2682 webcam_queue = y_list_remove_link(webcam_queue, webcam_queue);
2683 y_list_free_1(l);
2684 yahoo_webcam_get_server(yid, who, key);
2685 FREE(who);
2688 static void yahoo_packet_process(struct yahoo_input_data *yid, struct yahoo_packet *pkt)
2690 DEBUG_MSG(("yahoo_packet_process: 0x%02x", pkt->service));
2691 switch (pkt->service)
2693 case YAHOO_SERVICE_USERSTAT:
2694 case YAHOO_SERVICE_LOGON:
2695 case YAHOO_SERVICE_LOGOFF:
2696 case YAHOO_SERVICE_ISAWAY:
2697 case YAHOO_SERVICE_ISBACK:
2698 case YAHOO_SERVICE_GAMELOGON:
2699 case YAHOO_SERVICE_GAMELOGOFF:
2700 case YAHOO_SERVICE_IDACT:
2701 case YAHOO_SERVICE_IDDEACT:
2702 case YAHOO_SERVICE_STATUS_15:
2703 yahoo_process_status(yid, pkt);
2704 break;
2705 case YAHOO_SERVICE_NOTIFY:
2706 yahoo_process_notify(yid, pkt);
2707 break;
2708 case YAHOO_SERVICE_MESSAGE:
2709 case YAHOO_SERVICE_GAMEMSG:
2710 case YAHOO_SERVICE_SYSMESSAGE:
2711 yahoo_process_message(yid, pkt);
2712 break;
2713 case YAHOO_SERVICE_NEWMAIL:
2714 yahoo_process_mail(yid, pkt);
2715 break;
2716 case YAHOO_SERVICE_NEWCONTACT:
2717 yahoo_process_contact(yid, pkt);
2718 break;
2719 case YAHOO_SERVICE_LIST:
2720 yahoo_process_list(yid, pkt);
2721 break;
2722 case YAHOO_SERVICE_VERIFY:
2723 yahoo_process_verify(yid, pkt);
2724 break;
2725 case YAHOO_SERVICE_AUTH:
2726 yahoo_process_auth(yid, pkt);
2727 break;
2728 case YAHOO_SERVICE_AUTHRESP:
2729 yahoo_process_auth_resp(yid, pkt);
2730 break;
2731 case YAHOO_SERVICE_CONFINVITE:
2732 case YAHOO_SERVICE_CONFADDINVITE:
2733 case YAHOO_SERVICE_CONFDECLINE:
2734 case YAHOO_SERVICE_CONFLOGON:
2735 case YAHOO_SERVICE_CONFLOGOFF:
2736 case YAHOO_SERVICE_CONFMSG:
2737 yahoo_process_conference(yid, pkt);
2738 break;
2739 case YAHOO_SERVICE_CHATONLINE:
2740 case YAHOO_SERVICE_CHATGOTO:
2741 case YAHOO_SERVICE_CHATJOIN:
2742 case YAHOO_SERVICE_CHATLEAVE:
2743 case YAHOO_SERVICE_CHATEXIT:
2744 case YAHOO_SERVICE_CHATLOGOUT:
2745 case YAHOO_SERVICE_CHATPING:
2746 case YAHOO_SERVICE_COMMENT:
2747 yahoo_process_chat(yid, pkt);
2748 break;
2749 case YAHOO_SERVICE_P2PFILEXFER:
2750 case YAHOO_SERVICE_FILETRANSFER:
2751 yahoo_process_filetransfer(yid, pkt);
2752 break;
2753 case YAHOO_SERVICE_ADDBUDDY:
2754 yahoo_process_buddyadd(yid, pkt);
2755 break;
2756 case YAHOO_SERVICE_REMBUDDY:
2757 yahoo_process_buddydel(yid, pkt);
2758 break;
2759 case YAHOO_SERVICE_IGNORECONTACT:
2760 yahoo_process_ignore(yid, pkt);
2761 break;
2762 case YAHOO_SERVICE_VOICECHAT:
2763 yahoo_process_voicechat(yid, pkt);
2764 break;
2765 case YAHOO_SERVICE_WEBCAM:
2766 yahoo_process_webcam_key(yid, pkt);
2767 break;
2768 case YAHOO_SERVICE_PING:
2769 yahoo_process_ping(yid, pkt);
2770 break;
2771 case YAHOO_SERVICE_IDLE:
2772 case YAHOO_SERVICE_MAILSTAT:
2773 case YAHOO_SERVICE_CHATINVITE:
2774 case YAHOO_SERVICE_CALENDAR:
2775 case YAHOO_SERVICE_NEWPERSONALMAIL:
2776 case YAHOO_SERVICE_ADDIDENT:
2777 case YAHOO_SERVICE_ADDIGNORE:
2778 case YAHOO_SERVICE_GOTGROUPRENAME:
2779 case YAHOO_SERVICE_GROUPRENAME:
2780 case YAHOO_SERVICE_PASSTHROUGH2:
2781 case YAHOO_SERVICE_CHATLOGON:
2782 case YAHOO_SERVICE_CHATLOGOFF:
2783 case YAHOO_SERVICE_CHATMSG:
2784 case YAHOO_SERVICE_REJECTCONTACT:
2785 case YAHOO_SERVICE_PEERTOPEER:
2786 WARNING(("unhandled service 0x%02x", pkt->service));
2787 yahoo_dump_unhandled(pkt);
2788 break;
2789 case YAHOO_SERVICE_PICTURE:
2790 yahoo_process_picture(yid, pkt);
2791 break;
2792 case YAHOO_SERVICE_PICTURE_CHECKSUM:
2793 yahoo_process_picture_checksum(yid, pkt);
2794 break;
2795 case YAHOO_SERVICE_PICTURE_UPLOAD:
2796 yahoo_process_picture_upload(yid, pkt);
2797 break;
2798 default:
2799 WARNING(("unknown service 0x%02x", pkt->service));
2800 yahoo_dump_unhandled(pkt);
2801 break;
2805 static struct yahoo_packet * yahoo_getdata(struct yahoo_input_data * yid)
2807 struct yahoo_packet *pkt;
2808 struct yahoo_data *yd = yid->yd;
2809 int pos = 0;
2810 int pktlen;
2812 if(!yd)
2813 return NULL;
2815 DEBUG_MSG(("rxlen is %d", yid->rxlen));
2816 if (yid->rxlen < YAHOO_PACKET_HDRLEN) {
2817 DEBUG_MSG(("len < YAHOO_PACKET_HDRLEN"));
2818 return NULL;
2821 pos += 4; /* YMSG */
2822 pos += 2;
2823 pos += 2;
2825 pktlen = yahoo_get16(yid->rxqueue + pos); pos += 2;
2826 DEBUG_MSG(("%d bytes to read, rxlen is %d",
2827 pktlen, yid->rxlen));
2829 if (yid->rxlen < (YAHOO_PACKET_HDRLEN + pktlen)) {
2830 DEBUG_MSG(("len < YAHOO_PACKET_HDRLEN + pktlen"));
2831 return NULL;
2834 LOG(("reading packet"));
2835 yahoo_packet_dump(yid->rxqueue, YAHOO_PACKET_HDRLEN + pktlen);
2837 pkt = yahoo_packet_new(0, 0, 0);
2839 pkt->service = yahoo_get16(yid->rxqueue + pos); pos += 2;
2840 pkt->status = yahoo_get32(yid->rxqueue + pos); pos += 4;
2841 DEBUG_MSG(("Yahoo Service: 0x%02x Status: %d", pkt->service,
2842 pkt->status));
2843 pkt->id = yahoo_get32(yid->rxqueue + pos); pos += 4;
2845 yd->session_id = pkt->id;
2847 yahoo_packet_read(pkt, yid->rxqueue + pos, pktlen);
2849 yid->rxlen -= YAHOO_PACKET_HDRLEN + pktlen;
2850 DEBUG_MSG(("rxlen == %d, rxqueue == %p", yid->rxlen, yid->rxqueue));
2851 if (yid->rxlen>0) {
2852 unsigned char *tmp = y_memdup(yid->rxqueue + YAHOO_PACKET_HDRLEN
2853 + pktlen, yid->rxlen);
2854 FREE(yid->rxqueue);
2855 yid->rxqueue = tmp;
2856 DEBUG_MSG(("new rxlen == %d, rxqueue == %p", yid->rxlen, yid->rxqueue));
2857 } else {
2858 DEBUG_MSG(("freed rxqueue == %p", yid->rxqueue));
2859 FREE(yid->rxqueue);
2862 return pkt;
2865 static void yahoo_yab_read(struct yab *yab, unsigned char *d, int len)
2867 char *st, *en;
2868 char *data = (char *)d;
2869 data[len]='\0';
2871 DEBUG_MSG(("Got yab: %s", data));
2872 st = en = strstr(data, "userid=\"");
2873 if(st) {
2874 st += strlen("userid=\"");
2875 en = strchr(st, '"'); *en++ = '\0';
2876 yab->id = yahoo_xmldecode(st);
2879 st = strstr(en, "fname=\"");
2880 if(st) {
2881 st += strlen("fname=\"");
2882 en = strchr(st, '"'); *en++ = '\0';
2883 yab->fname = yahoo_xmldecode(st);
2886 st = strstr(en, "lname=\"");
2887 if(st) {
2888 st += strlen("lname=\"");
2889 en = strchr(st, '"'); *en++ = '\0';
2890 yab->lname = yahoo_xmldecode(st);
2893 st = strstr(en, "nname=\"");
2894 if(st) {
2895 st += strlen("nname=\"");
2896 en = strchr(st, '"'); *en++ = '\0';
2897 yab->nname = yahoo_xmldecode(st);
2900 st = strstr(en, "email=\"");
2901 if(st) {
2902 st += strlen("email=\"");
2903 en = strchr(st, '"'); *en++ = '\0';
2904 yab->email = yahoo_xmldecode(st);
2907 st = strstr(en, "hphone=\"");
2908 if(st) {
2909 st += strlen("hphone=\"");
2910 en = strchr(st, '"'); *en++ = '\0';
2911 yab->hphone = yahoo_xmldecode(st);
2914 st = strstr(en, "wphone=\"");
2915 if(st) {
2916 st += strlen("wphone=\"");
2917 en = strchr(st, '"'); *en++ = '\0';
2918 yab->wphone = yahoo_xmldecode(st);
2921 st = strstr(en, "mphone=\"");
2922 if(st) {
2923 st += strlen("mphone=\"");
2924 en = strchr(st, '"'); *en++ = '\0';
2925 yab->mphone = yahoo_xmldecode(st);
2928 st = strstr(en, "dbid=\"");
2929 if(st) {
2930 st += strlen("dbid=\"");
2931 en = strchr(st, '"'); *en++ = '\0';
2932 yab->dbid = atoi(st);
2936 static struct yab * yahoo_getyab(struct yahoo_input_data *yid)
2938 struct yab *yab = NULL;
2939 int pos = 0, end=0;
2940 struct yahoo_data *yd = yid->yd;
2942 if(!yd)
2943 return NULL;
2945 DEBUG_MSG(("rxlen is %d", yid->rxlen));
2947 if(yid->rxlen <= strlen("<record"))
2948 return NULL;
2950 /* start with <record */
2951 while(pos < yid->rxlen-strlen("<record")+1
2952 && memcmp(yid->rxqueue + pos, "<record", strlen("<record")))
2953 pos++;
2955 if(pos >= yid->rxlen-1)
2956 return NULL;
2958 end = pos+2;
2959 /* end with /> */
2960 while(end < yid->rxlen-strlen("/>")+1 && memcmp(yid->rxqueue + end, "/>", strlen("/>")))
2961 end++;
2963 if(end >= yid->rxlen-1)
2964 return NULL;
2966 yab = y_new0(struct yab, 1);
2967 yahoo_yab_read(yab, yid->rxqueue + pos, end+2-pos);
2970 yid->rxlen -= end+1;
2971 DEBUG_MSG(("rxlen == %d, rxqueue == %p", yid->rxlen, yid->rxqueue));
2972 if (yid->rxlen>0) {
2973 unsigned char *tmp = y_memdup(yid->rxqueue + end + 1, yid->rxlen);
2974 FREE(yid->rxqueue);
2975 yid->rxqueue = tmp;
2976 DEBUG_MSG(("new rxlen == %d, rxqueue == %p", yid->rxlen, yid->rxqueue));
2977 } else {
2978 DEBUG_MSG(("freed rxqueue == %p", yid->rxqueue));
2979 FREE(yid->rxqueue);
2983 return yab;
2986 static char * yahoo_getwebcam_master(struct yahoo_input_data *yid)
2988 unsigned int pos=0;
2989 unsigned int len=0;
2990 unsigned int status=0;
2991 char *server=NULL;
2992 struct yahoo_data *yd = yid->yd;
2994 if(!yid || !yd)
2995 return NULL;
2997 DEBUG_MSG(("rxlen is %d", yid->rxlen));
2999 len = yid->rxqueue[pos++];
3000 if (yid->rxlen < len)
3001 return NULL;
3003 /* extract status (0 = ok, 6 = webcam not online) */
3004 status = yid->rxqueue[pos++];
3006 if (status == 0)
3008 pos += 2; /* skip next 2 bytes */
3009 server = y_memdup(yid->rxqueue+pos, 16);
3010 pos += 16;
3012 else if (status == 6)
3014 YAHOO_CALLBACK(ext_yahoo_webcam_closed)
3015 (yd->client_id, yid->wcm->user, 4);
3018 /* skip rest of the data */
3020 yid->rxlen -= len;
3021 DEBUG_MSG(("rxlen == %d, rxqueue == %p", yid->rxlen, yid->rxqueue));
3022 if (yid->rxlen>0) {
3023 unsigned char *tmp = y_memdup(yid->rxqueue + pos, yid->rxlen);
3024 FREE(yid->rxqueue);
3025 yid->rxqueue = tmp;
3026 DEBUG_MSG(("new rxlen == %d, rxqueue == %p", yid->rxlen, yid->rxqueue));
3027 } else {
3028 DEBUG_MSG(("freed rxqueue == %p", yid->rxqueue));
3029 FREE(yid->rxqueue);
3032 return server;
3035 static int yahoo_get_webcam_data(struct yahoo_input_data *yid)
3037 unsigned char reason=0;
3038 unsigned int pos=0;
3039 unsigned int begin=0;
3040 unsigned int end=0;
3041 unsigned int closed=0;
3042 unsigned char header_len=0;
3043 char *who;
3044 int connect=0;
3045 struct yahoo_data *yd = yid->yd;
3047 if(!yd)
3048 return -1;
3050 if(!yid->wcm || !yid->wcd || !yid->rxlen)
3051 return -1;
3053 DEBUG_MSG(("rxlen is %d", yid->rxlen));
3055 /* if we are not reading part of image then read header */
3056 if (!yid->wcd->to_read)
3058 header_len=yid->rxqueue[pos++];
3059 yid->wcd->packet_type=0;
3061 if (yid->rxlen < header_len)
3062 return 0;
3064 if (header_len >= 8)
3066 reason = yid->rxqueue[pos++];
3067 /* next 2 bytes should always be 05 00 */
3068 pos += 2;
3069 yid->wcd->data_size = yahoo_get32(yid->rxqueue + pos);
3070 pos += 4;
3071 yid->wcd->to_read = yid->wcd->data_size;
3073 if (header_len >= 13)
3075 yid->wcd->packet_type = yid->rxqueue[pos++];
3076 yid->wcd->timestamp = yahoo_get32(yid->rxqueue + pos);
3077 pos += 4;
3080 /* skip rest of header */
3081 pos = header_len;
3084 begin = pos;
3085 pos += yid->wcd->to_read;
3086 if (pos > yid->rxlen) pos = yid->rxlen;
3088 /* if it is not an image then make sure we have the whole packet */
3089 if (yid->wcd->packet_type != 0x02) {
3090 if ((pos - begin) != yid->wcd->data_size) {
3091 yid->wcd->to_read = 0;
3092 return 0;
3093 } else {
3094 yahoo_packet_dump(yid->rxqueue + begin, pos - begin);
3098 DEBUG_MSG(("packet type %.2X, data length %d", yid->wcd->packet_type,
3099 yid->wcd->data_size));
3101 /* find out what kind of packet we got */
3102 switch (yid->wcd->packet_type)
3104 case 0x00:
3105 /* user requests to view webcam (uploading) */
3106 if (yid->wcd->data_size &&
3107 yid->wcm->direction == YAHOO_WEBCAM_UPLOAD) {
3108 end = begin;
3109 while (end <= yid->rxlen &&
3110 yid->rxqueue[end++] != 13);
3111 if (end > begin)
3113 who = y_memdup(yid->rxqueue + begin, end - begin);
3114 who[end - begin - 1] = 0;
3115 YAHOO_CALLBACK(ext_yahoo_webcam_viewer)(yd->client_id, who + 2, 2);
3116 FREE(who);
3120 if (yid->wcm->direction == YAHOO_WEBCAM_DOWNLOAD) {
3121 /* timestamp/status field */
3122 /* 0 = declined viewing permission */
3123 /* 1 = accepted viewing permission */
3124 if (yid->wcd->timestamp == 0) {
3125 YAHOO_CALLBACK(ext_yahoo_webcam_closed)(yd->client_id, yid->wcm->user, 3);
3128 break;
3129 case 0x01: /* status packets?? */
3130 /* timestamp contains status info */
3131 /* 00 00 00 01 = we have data?? */
3132 break;
3133 case 0x02: /* image data */
3134 YAHOO_CALLBACK(ext_yahoo_got_webcam_image)(yd->client_id,
3135 yid->wcm->user, yid->rxqueue + begin,
3136 yid->wcd->data_size, pos - begin,
3137 yid->wcd->timestamp);
3138 break;
3139 case 0x05: /* response packets when uploading */
3140 if (!yid->wcd->data_size) {
3141 YAHOO_CALLBACK(ext_yahoo_webcam_data_request)(yd->client_id, yid->wcd->timestamp);
3143 break;
3144 case 0x07: /* connection is closing */
3145 switch(reason)
3147 case 0x01: /* user closed connection */
3148 closed = 1;
3149 break;
3150 case 0x0F: /* user cancelled permission */
3151 closed = 2;
3152 break;
3154 YAHOO_CALLBACK(ext_yahoo_webcam_closed)(yd->client_id, yid->wcm->user, closed);
3155 break;
3156 case 0x0C: /* user connected */
3157 case 0x0D: /* user disconnected */
3158 if (yid->wcd->data_size) {
3159 who = y_memdup(yid->rxqueue + begin, pos - begin + 1);
3160 who[pos - begin] = 0;
3161 if (yid->wcd->packet_type == 0x0C)
3162 connect=1;
3163 else
3164 connect=0;
3165 YAHOO_CALLBACK(ext_yahoo_webcam_viewer)(yd->client_id, who, connect);
3166 FREE(who);
3168 break;
3169 case 0x13: /* user data */
3170 /* i=user_ip (ip of the user we are viewing) */
3171 /* j=user_ext_ip (external ip of the user we */
3172 /* are viewing) */
3173 break;
3174 case 0x17: /* ?? */
3175 break;
3177 yid->wcd->to_read -= pos - begin;
3179 yid->rxlen -= pos;
3180 DEBUG_MSG(("rxlen == %d, rxqueue == %p", yid->rxlen, yid->rxqueue));
3181 if (yid->rxlen>0) {
3182 unsigned char *tmp = y_memdup(yid->rxqueue + pos, yid->rxlen);
3183 FREE(yid->rxqueue);
3184 yid->rxqueue = tmp;
3185 DEBUG_MSG(("new rxlen == %d, rxqueue == %p", yid->rxlen, yid->rxqueue));
3186 } else {
3187 DEBUG_MSG(("freed rxqueue == %p", yid->rxqueue));
3188 FREE(yid->rxqueue);
3191 /* If we read a complete packet return success */
3192 if (!yid->wcd->to_read)
3193 return 1;
3195 return 0;
3198 int yahoo_write_ready(int id, int fd, void *data)
3200 struct yahoo_input_data *yid = data;
3201 int len;
3202 struct data_queue *tx;
3204 LOG(("write callback: id=%d fd=%d data=%p", id, fd, data));
3205 if(!yid || !yid->txqueues)
3206 return -2;
3208 tx = yid->txqueues->data;
3209 LOG(("writing %d bytes", tx->len));
3210 len = yahoo_send_data(fd, tx->queue, MIN(1024, tx->len));
3212 if(len == -1 && errno == EAGAIN)
3213 return 1;
3215 if(len <= 0) {
3216 int e = errno;
3217 DEBUG_MSG(("len == %d (<= 0)", len));
3218 while(yid->txqueues) {
3219 YList *l=yid->txqueues;
3220 tx = l->data;
3221 free(tx->queue);
3222 free(tx);
3223 yid->txqueues = y_list_remove_link(yid->txqueues, yid->txqueues);
3224 y_list_free_1(l);
3226 LOG(("yahoo_write_ready(%d, %d) len < 0", id, fd));
3227 YAHOO_CALLBACK(ext_yahoo_remove_handler)(id, yid->write_tag);
3228 yid->write_tag = 0;
3229 errno=e;
3230 return 0;
3234 tx->len -= len;
3235 if(tx->len > 0) {
3236 unsigned char *tmp = y_memdup(tx->queue + len, tx->len);
3237 FREE(tx->queue);
3238 tx->queue = tmp;
3239 } else {
3240 YList *l=yid->txqueues;
3241 free(tx->queue);
3242 free(tx);
3243 yid->txqueues = y_list_remove_link(yid->txqueues, yid->txqueues);
3244 y_list_free_1(l);
3246 if(!yid->txqueues)
3247 LOG(("yahoo_write_ready(%d, %d) !yxqueues", id, fd));
3249 if(!yid->txqueues) {
3250 LOG(("yahoo_write_ready(%d, %d) !yxqueues", id, fd));
3251 YAHOO_CALLBACK(ext_yahoo_remove_handler)(id, yid->write_tag);
3252 yid->write_tag = 0;
3256 return 1;
3259 static void yahoo_process_pager_connection(struct yahoo_input_data *yid, int over)
3261 struct yahoo_packet *pkt;
3262 struct yahoo_data *yd = yid->yd;
3263 int id = yd->client_id;
3265 if(over)
3266 return;
3268 while (find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER)
3269 && (pkt = yahoo_getdata(yid)) != NULL) {
3271 yahoo_packet_process(yid, pkt);
3273 yahoo_packet_free(pkt);
3277 static void yahoo_process_ft_connection(struct yahoo_input_data *yid, int over)
3281 static void yahoo_process_chatcat_connection(struct yahoo_input_data *yid, int over)
3283 if(over)
3284 return;
3286 if (strstr((char*)yid->rxqueue+(yid->rxlen-20), "</content>")) {
3287 YAHOO_CALLBACK(ext_yahoo_chat_cat_xml)(yid->yd->client_id, (char*)yid->rxqueue);
3291 static void yahoo_process_yab_connection(struct yahoo_input_data *yid, int over)
3293 struct yahoo_data *yd = yid->yd;
3294 struct yab *yab;
3295 YList *buds;
3296 int changed=0;
3297 int id = yd->client_id;
3299 if(over)
3300 return;
3302 while(find_input_by_id_and_type(id, YAHOO_CONNECTION_YAB)
3303 && (yab = yahoo_getyab(yid)) != NULL) {
3304 if(!yab->id)
3305 continue;
3306 changed=1;
3307 for(buds = yd->buddies; buds; buds=buds->next) {
3308 struct yahoo_buddy * bud = buds->data;
3309 if(!strcmp(bud->id, yab->id)) {
3310 bud->yab_entry = yab;
3311 if(yab->nname) {
3312 bud->real_name = strdup(yab->nname);
3313 } else if(yab->fname && yab->lname) {
3314 bud->real_name = y_new0(char,
3315 strlen(yab->fname)+
3316 strlen(yab->lname)+2
3318 sprintf(bud->real_name, "%s %s",
3319 yab->fname, yab->lname);
3320 } else if(yab->fname) {
3321 bud->real_name = strdup(yab->fname);
3323 break; /* for */
3328 if(changed)
3329 YAHOO_CALLBACK(ext_yahoo_got_buddies)(yd->client_id, yd->buddies);
3332 static void yahoo_process_search_connection(struct yahoo_input_data *yid, int over)
3334 struct yahoo_found_contact *yct=NULL;
3335 char *p = (char *)yid->rxqueue, *np, *cp;
3336 int k, n;
3337 int start=0, found=0, total=0;
3338 YList *contacts=NULL;
3339 struct yahoo_input_data *pyid = find_input_by_id_and_type(yid->yd->client_id, YAHOO_CONNECTION_PAGER);
3341 if(!over || !pyid)
3342 return;
3344 if(p && (p=strstr(p, "\r\n\r\n"))) {
3345 p += 4;
3347 for(k = 0; (p = strchr(p, 4)) && (k < 4); k++) {
3348 p++;
3349 n = atoi(p);
3350 switch(k) {
3351 case 0: found = pyid->ys->lsearch_nfound = n; break;
3352 case 2: start = pyid->ys->lsearch_nstart = n; break;
3353 case 3: total = pyid->ys->lsearch_ntotal = n; break;
3357 if(p)
3358 p++;
3360 k=0;
3361 while(p && *p) {
3362 cp = p;
3363 np = strchr(p, 4);
3365 if(!np)
3366 break;
3367 *np = 0;
3368 p = np+1;
3370 switch(k++) {
3371 case 1:
3372 if(strlen(cp) > 2 && y_list_length(contacts) < total) {
3373 yct = y_new0(struct yahoo_found_contact, 1);
3374 contacts = y_list_append(contacts, yct);
3375 yct->id = cp+2;
3376 } else {
3377 *p = 0;
3379 break;
3380 case 2:
3381 yct->online = !strcmp(cp, "2") ? 1 : 0;
3382 break;
3383 case 3:
3384 yct->gender = cp;
3385 break;
3386 case 4:
3387 yct->age = atoi(cp);
3388 break;
3389 case 5:
3390 if( strcmp(cp,"\005") != 0)
3391 yct->location = cp;
3392 k = 0;
3393 break;
3398 YAHOO_CALLBACK(ext_yahoo_got_search_result)(yid->yd->client_id, found, start, total, contacts);
3400 while(contacts) {
3401 YList *node = contacts;
3402 contacts = y_list_remove_link(contacts, node);
3403 free(node->data);
3404 y_list_free_1(node);
3408 static void _yahoo_webcam_connected(int fd, int error, void *d)
3410 struct yahoo_input_data *yid = d;
3411 struct yahoo_webcam *wcm = yid->wcm;
3412 struct yahoo_data *yd = yid->yd;
3413 char conn_type[100];
3414 char *data=NULL;
3415 char *packet=NULL;
3416 unsigned char magic_nr[] = {1, 0, 0, 0, 1};
3417 unsigned header_len=0;
3418 unsigned int len=0;
3419 unsigned int pos=0;
3421 if(error || fd <= 0) {
3422 FREE(yid);
3423 return;
3426 yid->fd = fd;
3427 inputs = y_list_prepend(inputs, yid);
3429 LOG(("Connected"));
3430 /* send initial packet */
3431 switch (wcm->direction)
3433 case YAHOO_WEBCAM_DOWNLOAD:
3434 data = strdup("<REQIMG>");
3435 break;
3436 case YAHOO_WEBCAM_UPLOAD:
3437 data = strdup("<SNDIMG>");
3438 break;
3439 default:
3440 return;
3442 yahoo_add_to_send_queue(yid, data, strlen(data));
3443 FREE(data);
3445 /* send data */
3446 switch (wcm->direction)
3448 case YAHOO_WEBCAM_DOWNLOAD:
3449 header_len = 8;
3450 data = strdup("a=2\r\nc=us\r\ne=21\r\nu=");
3451 data = y_string_append(data, yd->user);
3452 data = y_string_append(data, "\r\nt=");
3453 data = y_string_append(data, wcm->key);
3454 data = y_string_append(data, "\r\ni=");
3455 data = y_string_append(data, wcm->my_ip);
3456 data = y_string_append(data, "\r\ng=");
3457 data = y_string_append(data, wcm->user);
3458 data = y_string_append(data, "\r\no=w-2-5-1\r\np=");
3459 snprintf(conn_type, sizeof(conn_type), "%d", wcm->conn_type);
3460 data = y_string_append(data, conn_type);
3461 data = y_string_append(data, "\r\n");
3462 break;
3463 case YAHOO_WEBCAM_UPLOAD:
3464 header_len = 13;
3465 data = strdup("a=2\r\nc=us\r\nu=");
3466 data = y_string_append(data, yd->user);
3467 data = y_string_append(data, "\r\nt=");
3468 data = y_string_append(data, wcm->key);
3469 data = y_string_append(data, "\r\ni=");
3470 data = y_string_append(data, wcm->my_ip);
3471 data = y_string_append(data, "\r\no=w-2-5-1\r\np=");
3472 snprintf(conn_type, sizeof(conn_type), "%d", wcm->conn_type);
3473 data = y_string_append(data, conn_type);
3474 data = y_string_append(data, "\r\nb=");
3475 data = y_string_append(data, wcm->description);
3476 data = y_string_append(data, "\r\n");
3477 break;
3480 len = strlen(data);
3481 packet = y_new0(char, header_len + len);
3482 packet[pos++] = header_len;
3483 packet[pos++] = 0;
3484 switch (wcm->direction)
3486 case YAHOO_WEBCAM_DOWNLOAD:
3487 packet[pos++] = 1;
3488 packet[pos++] = 0;
3489 break;
3490 case YAHOO_WEBCAM_UPLOAD:
3491 packet[pos++] = 5;
3492 packet[pos++] = 0;
3493 break;
3496 pos += yahoo_put32(packet + pos, len);
3497 if (wcm->direction == YAHOO_WEBCAM_UPLOAD)
3499 memcpy(packet + pos, magic_nr, sizeof(magic_nr));
3500 pos += sizeof(magic_nr);
3502 memcpy(packet + pos, data, len);
3503 yahoo_add_to_send_queue(yid, packet, header_len + len);
3504 FREE(packet);
3505 FREE(data);
3507 yid->read_tag=YAHOO_CALLBACK(ext_yahoo_add_handler)(yid->yd->client_id, yid->fd, YAHOO_INPUT_READ, yid);
3510 static void yahoo_webcam_connect(struct yahoo_input_data *y)
3512 struct yahoo_webcam *wcm = y->wcm;
3513 struct yahoo_input_data *yid;
3514 struct yahoo_server_settings *yss;
3516 if (!wcm || !wcm->server || !wcm->key)
3517 return;
3519 yid = y_new0(struct yahoo_input_data, 1);
3520 yid->type = YAHOO_CONNECTION_WEBCAM;
3521 yid->yd = y->yd;
3523 /* copy webcam data to new connection */
3524 yid->wcm = y->wcm;
3525 y->wcm = NULL;
3527 yss = y->yd->server_settings;
3529 yid->wcd = y_new0(struct yahoo_webcam_data, 1);
3531 LOG(("Connecting to: %s:%d", wcm->server, wcm->port));
3532 YAHOO_CALLBACK(ext_yahoo_connect_async)(y->yd->client_id, wcm->server, wcm->port,
3533 _yahoo_webcam_connected, yid);
3537 static void yahoo_process_webcam_master_connection(struct yahoo_input_data *yid, int over)
3539 char* server;
3540 struct yahoo_server_settings *yss;
3542 if(over)
3543 return;
3545 server = yahoo_getwebcam_master(yid);
3547 if (server)
3549 yss = yid->yd->server_settings;
3550 yid->wcm->server = strdup(server);
3551 yid->wcm->port = yss->webcam_port;
3552 yid->wcm->conn_type = yss->conn_type;
3553 yid->wcm->my_ip = strdup(yss->local_host);
3554 if (yid->wcm->direction == YAHOO_WEBCAM_UPLOAD)
3555 yid->wcm->description = strdup(yss->webcam_description);
3556 yahoo_webcam_connect(yid);
3557 FREE(server);
3561 static void yahoo_process_webcam_connection(struct yahoo_input_data *yid, int over)
3563 int id = yid->yd->client_id;
3564 int fd = yid->fd;
3566 if(over)
3567 return;
3569 /* as long as we still have packets available keep processing them */
3570 while (find_input_by_id_and_fd(id, fd)
3571 && yahoo_get_webcam_data(yid) == 1);
3574 static void (*yahoo_process_connection[])(struct yahoo_input_data *, int over) = {
3575 yahoo_process_pager_connection,
3576 yahoo_process_ft_connection,
3577 yahoo_process_yab_connection,
3578 yahoo_process_webcam_master_connection,
3579 yahoo_process_webcam_connection,
3580 yahoo_process_chatcat_connection,
3581 yahoo_process_search_connection
3584 int yahoo_read_ready(int id, int fd, void *data)
3586 struct yahoo_input_data *yid = data;
3587 char buf[1024];
3588 int len;
3590 LOG(("read callback: id=%d fd=%d data=%p", id, fd, data));
3591 if(!yid)
3592 return -2;
3595 do {
3596 len = read(fd, buf, sizeof(buf));
3597 } while(len == -1 && errno == EINTR);
3599 if(len == -1 && errno == EAGAIN) /* we'll try again later */
3600 return 1;
3602 if (len <= 0) {
3603 int e = errno;
3604 DEBUG_MSG(("len == %d (<= 0)", len));
3606 if(yid->type == YAHOO_CONNECTION_PAGER) {
3607 YAHOO_CALLBACK(ext_yahoo_error)(yid->yd->client_id, "Connection closed by server", 1, E_CONNECTION);
3610 yahoo_process_connection[yid->type](yid, 1);
3611 yahoo_input_close(yid);
3613 /* no need to return an error, because we've already fixed it */
3614 if(len == 0)
3615 return 1;
3617 errno=e;
3618 LOG(("read error: %s", strerror(errno)));
3619 return -1;
3622 yid->rxqueue = y_renew(unsigned char, yid->rxqueue, len + yid->rxlen);
3623 memcpy(yid->rxqueue + yid->rxlen, buf, len);
3624 yid->rxlen += len;
3626 yahoo_process_connection[yid->type](yid, 0);
3628 return len;
3631 int yahoo_init_with_attributes(const char *username, const char *password, ...)
3633 va_list ap;
3634 struct yahoo_data *yd;
3636 yd = y_new0(struct yahoo_data, 1);
3638 if(!yd)
3639 return 0;
3641 yd->user = strdup(username);
3642 yd->password = strdup(password);
3644 yd->initial_status = -1;
3645 yd->current_status = -1;
3647 yd->client_id = ++last_id;
3649 add_to_list(yd);
3651 va_start(ap, password);
3652 yd->server_settings = _yahoo_assign_server_settings(ap);
3653 va_end(ap);
3655 return yd->client_id;
3658 int yahoo_init(const char *username, const char *password)
3660 return yahoo_init_with_attributes(username, password, (char *)NULL);
3663 struct connect_callback_data {
3664 struct yahoo_data *yd;
3665 int tag;
3666 int i;
3669 static void yahoo_connected(int fd, int error, void *data)
3671 struct connect_callback_data *ccd = data;
3672 struct yahoo_data *yd = ccd->yd;
3673 struct yahoo_packet *pkt;
3674 struct yahoo_input_data *yid;
3675 struct yahoo_server_settings *yss = yd->server_settings;
3677 if(error) {
3678 if(fallback_ports[ccd->i]) {
3679 int tag;
3680 yss->pager_port = fallback_ports[ccd->i++];
3681 tag = YAHOO_CALLBACK(ext_yahoo_connect_async)(yd->client_id, yss->pager_host,
3682 yss->pager_port, yahoo_connected, ccd);
3684 if(tag > 0)
3685 ccd->tag=tag;
3686 } else {
3687 FREE(ccd);
3688 YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, YAHOO_LOGIN_SOCK, NULL);
3690 return;
3693 FREE(ccd);
3695 /* fd < 0 && error == 0 means connect was cancelled */
3696 if(fd < 0)
3697 return;
3699 pkt = yahoo_packet_new(YAHOO_SERVICE_AUTH, YAHOO_STATUS_AVAILABLE, yd->session_id);
3700 NOTICE(("Sending initial packet"));
3702 yahoo_packet_hash(pkt, 1, yd->user);
3704 yid = y_new0(struct yahoo_input_data, 1);
3705 yid->yd = yd;
3706 yid->fd = fd;
3707 inputs = y_list_prepend(inputs, yid);
3709 yahoo_send_packet(yid, pkt, 0);
3711 yahoo_packet_free(pkt);
3713 yid->read_tag=YAHOO_CALLBACK(ext_yahoo_add_handler)(yid->yd->client_id, yid->fd, YAHOO_INPUT_READ, yid);
3716 void yahoo_login(int id, int initial)
3718 struct yahoo_data *yd = find_conn_by_id(id);
3719 struct connect_callback_data *ccd;
3720 struct yahoo_server_settings *yss;
3721 int tag;
3723 if(!yd)
3724 return;
3726 yss = yd->server_settings;
3728 yd->initial_status = initial;
3730 ccd = y_new0(struct connect_callback_data, 1);
3731 ccd->yd = yd;
3732 tag = YAHOO_CALLBACK(ext_yahoo_connect_async)(yd->client_id, yss->pager_host, yss->pager_port,
3733 yahoo_connected, ccd);
3736 * if tag <= 0, then callback has already been called
3737 * so ccd will have been freed
3739 if(tag > 0)
3740 ccd->tag = tag;
3741 else if(tag < 0)
3742 YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, YAHOO_LOGIN_SOCK, NULL);
3746 int yahoo_get_fd(int id)
3748 struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
3749 if(!yid)
3750 return 0;
3751 else
3752 return yid->fd;
3755 void yahoo_send_im(int id, const char *from, const char *who, const char *what, int utf8, int picture)
3757 struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
3758 struct yahoo_packet *pkt = NULL;
3759 struct yahoo_data *yd;
3760 char pic_str[10];
3762 if(!yid)
3763 return;
3765 yd = yid->yd;
3767 pkt = yahoo_packet_new(YAHOO_SERVICE_MESSAGE, YAHOO_STATUS_OFFLINE, yd->session_id);
3769 snprintf(pic_str, sizeof(pic_str), "%d", picture);
3771 if(from && strcmp(from, yd->user))
3772 yahoo_packet_hash(pkt, 0, yd->user);
3773 yahoo_packet_hash(pkt, 1, from?from:yd->user);
3774 yahoo_packet_hash(pkt, 5, who);
3775 yahoo_packet_hash(pkt, 14, what);
3777 if(utf8)
3778 yahoo_packet_hash(pkt, 97, "1");
3780 yahoo_packet_hash(pkt, 63, ";0"); /* imvironment name; or ;0 */
3781 yahoo_packet_hash(pkt, 64, "0");
3782 yahoo_packet_hash(pkt, 206, pic_str);
3785 yahoo_send_packet(yid, pkt, 0);
3787 yahoo_packet_free(pkt);
3790 void yahoo_send_typing(int id, const char *from, const char *who, int typ)
3792 struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
3793 struct yahoo_data *yd;
3794 struct yahoo_packet *pkt = NULL;
3795 if(!yid)
3796 return;
3798 yd = yid->yd;
3799 pkt = yahoo_packet_new(YAHOO_SERVICE_NOTIFY, YAHOO_STATUS_NOTIFY, yd->session_id);
3801 yahoo_packet_hash(pkt, 5, who);
3802 yahoo_packet_hash(pkt, 4, from?from:yd->user);
3803 yahoo_packet_hash(pkt, 14, " ");
3804 yahoo_packet_hash(pkt, 13, typ ? "1" : "0");
3805 yahoo_packet_hash(pkt, 49, "TYPING");
3807 yahoo_send_packet(yid, pkt, 0);
3809 yahoo_packet_free(pkt);
3812 void yahoo_set_away(int id, enum yahoo_status state, const char *msg, int away)
3814 struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
3815 struct yahoo_data *yd;
3816 struct yahoo_packet *pkt = NULL;
3817 int service;
3818 char s[4];
3820 if(!yid)
3821 return;
3823 yd = yid->yd;
3825 if (msg) {
3826 yd->current_status = YAHOO_STATUS_CUSTOM;
3827 } else {
3828 yd->current_status = state;
3831 if (yd->current_status == YAHOO_STATUS_AVAILABLE)
3832 service = YAHOO_SERVICE_ISBACK;
3833 else
3834 service = YAHOO_SERVICE_ISAWAY;
3836 if ((away == 2) && (yd->current_status == YAHOO_STATUS_AVAILABLE)) {
3837 pkt = yahoo_packet_new(YAHOO_SERVICE_ISAWAY, YAHOO_STATUS_BRB, yd->session_id);
3838 yahoo_packet_hash(pkt, 10, "999");
3839 yahoo_packet_hash(pkt, 47, "2");
3840 }else {
3841 pkt = yahoo_packet_new(service, YAHOO_STATUS_AVAILABLE, yd->session_id);
3842 snprintf(s, sizeof(s), "%d", yd->current_status);
3843 yahoo_packet_hash(pkt, 10, s);
3844 if (yd->current_status == YAHOO_STATUS_CUSTOM) {
3845 yahoo_packet_hash(pkt, 19, msg);
3846 yahoo_packet_hash(pkt, 47, (away == 2)? "2": (away) ?"1":"0");
3847 } else {
3848 yahoo_packet_hash(pkt, 47, (away == 2)? "2": (away) ?"1":"0");
3855 yahoo_send_packet(yid, pkt, 0);
3856 yahoo_packet_free(pkt);
3859 void yahoo_logoff(int id)
3861 struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
3862 struct yahoo_data *yd;
3863 struct yahoo_packet *pkt = NULL;
3865 if(!yid)
3866 return;
3867 yd = yid->yd;
3869 LOG(("yahoo_logoff: current status: %d", yd->current_status));
3871 if(yd->current_status != -1) {
3872 pkt = yahoo_packet_new(YAHOO_SERVICE_LOGOFF, YAHOO_STATUS_AVAILABLE, yd->session_id);
3873 yd->current_status = -1;
3875 if (pkt) {
3876 yahoo_send_packet(yid, pkt, 0);
3877 yahoo_packet_free(pkt);
3882 /* do {
3883 yahoo_input_close(yid);
3884 } while((yid = find_input_by_id(id)));*/
3888 void yahoo_get_list(int id)
3890 struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
3891 struct yahoo_data *yd;
3892 struct yahoo_packet *pkt = NULL;
3894 if(!yid)
3895 return;
3896 yd = yid->yd;
3898 pkt = yahoo_packet_new(YAHOO_SERVICE_LIST, YAHOO_STATUS_AVAILABLE, yd->session_id);
3899 yahoo_packet_hash(pkt, 1, yd->user);
3900 if (pkt) {
3901 yahoo_send_packet(yid, pkt, 0);
3902 yahoo_packet_free(pkt);
3906 static void _yahoo_http_connected(int id, int fd, int error, void *data)
3908 struct yahoo_input_data *yid = data;
3909 if(fd <= 0) {
3910 inputs = y_list_remove(inputs, yid);
3911 FREE(yid);
3912 return;
3915 yid->fd = fd;
3916 yid->read_tag=YAHOO_CALLBACK(ext_yahoo_add_handler)(yid->yd->client_id, fd, YAHOO_INPUT_READ, yid);
3919 void yahoo_get_yab(int id)
3921 struct yahoo_data *yd = find_conn_by_id(id);
3922 struct yahoo_input_data *yid;
3923 char url[1024];
3924 char buff[1024];
3926 if(!yd)
3927 return;
3929 yid = y_new0(struct yahoo_input_data, 1);
3930 yid->yd = yd;
3931 yid->type = YAHOO_CONNECTION_YAB;
3933 snprintf(url, 1024, "http://insider.msg.yahoo.com/ycontent/?ab2=0");
3935 snprintf(buff, sizeof(buff), "Y=%s; T=%s",
3936 yd->cookie_y, yd->cookie_t);
3938 inputs = y_list_prepend(inputs, yid);
3940 yahoo_http_get(yid->yd->client_id, url, buff,
3941 _yahoo_http_connected, yid);
3944 void yahoo_set_yab(int id, struct yab * yab)
3946 struct yahoo_data *yd = find_conn_by_id(id);
3947 struct yahoo_input_data *yid;
3948 char url[1024];
3949 char buff[1024];
3950 char *temp;
3951 int size = sizeof(url)-1;
3953 if(!yd)
3954 return;
3956 yid = y_new0(struct yahoo_input_data, 1);
3957 yid->type = YAHOO_CONNECTION_YAB;
3958 yid->yd = yd;
3960 strncpy(url, "http://insider.msg.yahoo.com/ycontent/?addab2=0", size);
3962 if(yab->dbid) {
3963 /* change existing yab */
3964 char tmp[32];
3965 strncat(url, "&ee=1&ow=1&id=", size - strlen(url));
3966 snprintf(tmp, sizeof(tmp), "%d", yab->dbid);
3967 strncat(url, tmp, size - strlen(url));
3970 if(yab->fname) {
3971 strncat(url, "&fn=", size - strlen(url));
3972 temp = yahoo_urlencode(yab->fname);
3973 strncat(url, temp, size - strlen(url));
3974 free(temp);
3976 if(yab->lname) {
3977 strncat(url, "&ln=", size - strlen(url));
3978 temp = yahoo_urlencode(yab->lname);
3979 strncat(url, temp, size - strlen(url));
3980 free(temp);
3982 strncat(url, "&yid=", size - strlen(url));
3983 temp = yahoo_urlencode(yab->id);
3984 strncat(url, temp, size - strlen(url));
3985 free(temp);
3986 if(yab->nname) {
3987 strncat(url, "&nn=", size - strlen(url));
3988 temp = yahoo_urlencode(yab->nname);
3989 strncat(url, temp, size - strlen(url));
3990 free(temp);
3992 if(yab->email) {
3993 strncat(url, "&e=", size - strlen(url));
3994 temp = yahoo_urlencode(yab->email);
3995 strncat(url, temp, size - strlen(url));
3996 free(temp);
3998 if(yab->hphone) {
3999 strncat(url, "&hp=", size - strlen(url));
4000 temp = yahoo_urlencode(yab->hphone);
4001 strncat(url, temp, size - strlen(url));
4002 free(temp);
4004 if(yab->wphone) {
4005 strncat(url, "&wp=", size - strlen(url));
4006 temp = yahoo_urlencode(yab->wphone);
4007 strncat(url, temp, size - strlen(url));
4008 free(temp);
4010 if(yab->mphone) {
4011 strncat(url, "&mp=", size - strlen(url));
4012 temp = yahoo_urlencode(yab->mphone);
4013 strncat(url, temp, size - strlen(url));
4014 free(temp);
4016 strncat(url, "&pp=0", size - strlen(url));
4018 snprintf(buff, sizeof(buff), "Y=%s; T=%s",
4019 yd->cookie_y, yd->cookie_t);
4021 inputs = y_list_prepend(inputs, yid);
4023 yahoo_http_get(yid->yd->client_id, url, buff,
4024 _yahoo_http_connected, yid);
4027 void yahoo_set_identity_status(int id, const char * identity, int active)
4029 struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
4030 struct yahoo_data *yd;
4031 struct yahoo_packet *pkt = NULL;
4033 if(!yid)
4034 return;
4035 yd = yid->yd;
4037 pkt = yahoo_packet_new(active?YAHOO_SERVICE_IDACT:YAHOO_SERVICE_IDDEACT,
4038 YAHOO_STATUS_AVAILABLE, yd->session_id);
4039 yahoo_packet_hash(pkt, 3, identity);
4040 if (pkt) {
4041 yahoo_send_packet(yid, pkt, 0);
4042 yahoo_packet_free(pkt);
4046 void yahoo_refresh(int id)
4048 struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
4049 struct yahoo_data *yd;
4050 struct yahoo_packet *pkt = NULL;
4052 if(!yid)
4053 return;
4054 yd = yid->yd;
4056 pkt = yahoo_packet_new(YAHOO_SERVICE_USERSTAT, YAHOO_STATUS_AVAILABLE, yd->session_id);
4057 if (pkt) {
4058 yahoo_send_packet(yid, pkt, 0);
4059 yahoo_packet_free(pkt);
4063 void yahoo_keepalive(int id)
4065 struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
4066 struct yahoo_data *yd;
4067 struct yahoo_packet *pkt=NULL;
4068 if(!yid)
4069 return;
4070 yd = yid->yd;
4072 pkt = yahoo_packet_new(YAHOO_SERVICE_PING, YAHOO_STATUS_AVAILABLE, yd->session_id);
4073 yahoo_send_packet(yid, pkt, 0);
4074 yahoo_packet_free(pkt);
4077 void yahoo_chat_keepalive (int id)
4079 struct yahoo_input_data *yid = find_input_by_id_and_type (id, YAHOO_CONNECTION_PAGER);
4080 struct yahoo_data *yd;
4081 struct yahoo_packet *pkt = NULL;
4083 if (!yid)
4084 return;
4086 yd = yid->yd;
4088 pkt = yahoo_packet_new (YAHOO_SERVICE_CHATPING, YAHOO_STATUS_AVAILABLE, yd->session_id);
4089 yahoo_send_packet (yid, pkt, 0);
4090 yahoo_packet_free (pkt);
4093 void yahoo_add_buddy(int id, const char *who, const char *group, const char *msg)
4095 struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
4096 struct yahoo_data *yd;
4097 struct yahoo_packet *pkt;
4099 if(!yid)
4100 return;
4101 yd = yid->yd;
4103 if (!yd->logged_in)
4104 return;
4106 pkt = yahoo_packet_new(YAHOO_SERVICE_ADDBUDDY, YAHOO_STATUS_AVAILABLE, yd->session_id);
4107 yahoo_packet_hash(pkt, 1, yd->user);
4108 yahoo_packet_hash(pkt, 7, who);
4109 yahoo_packet_hash(pkt, 65, group);
4110 if(msg)
4111 yahoo_packet_hash(pkt, 14, msg);
4113 yahoo_send_packet(yid, pkt, 0);
4114 yahoo_packet_free(pkt);
4117 void yahoo_remove_buddy(int id, const char *who, const char *group)
4119 struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
4120 struct yahoo_data *yd;
4121 struct yahoo_packet *pkt = NULL;
4123 if(!yid)
4124 return;
4125 yd = yid->yd;
4127 pkt = yahoo_packet_new(YAHOO_SERVICE_REMBUDDY, YAHOO_STATUS_AVAILABLE, yd->session_id);
4129 yahoo_packet_hash(pkt, 1, yd->user);
4130 yahoo_packet_hash(pkt, 7, who);
4131 yahoo_packet_hash(pkt, 65, group);
4132 yahoo_send_packet(yid, pkt, 0);
4133 yahoo_packet_free(pkt);
4136 void yahoo_reject_buddy(int id, const char *who, const char *msg)
4138 struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
4139 struct yahoo_data *yd;
4140 struct yahoo_packet *pkt;
4142 if(!yid)
4143 return;
4144 yd = yid->yd;
4146 if (!yd->logged_in)
4147 return;
4149 pkt = yahoo_packet_new(YAHOO_SERVICE_REJECTCONTACT, YAHOO_STATUS_AVAILABLE, yd->session_id);
4150 yahoo_packet_hash(pkt, 1, yd->user);
4151 yahoo_packet_hash(pkt, 7, who);
4152 yahoo_packet_hash(pkt, 14, msg);
4153 yahoo_send_packet(yid, pkt, 0);
4154 yahoo_packet_free(pkt);
4157 void yahoo_ignore_buddy(int id, const char *who, int unignore)
4159 struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
4160 struct yahoo_data *yd;
4161 struct yahoo_packet *pkt;
4163 if(!yid)
4164 return;
4165 yd = yid->yd;
4167 if (!yd->logged_in)
4168 return;
4170 pkt = yahoo_packet_new(YAHOO_SERVICE_IGNORECONTACT, YAHOO_STATUS_AVAILABLE, yd->session_id);
4171 yahoo_packet_hash(pkt, 1, yd->user);
4172 yahoo_packet_hash(pkt, 7, who);
4173 yahoo_packet_hash(pkt, 13, unignore?"2":"1");
4174 yahoo_send_packet(yid, pkt, 0);
4175 yahoo_packet_free(pkt);
4178 void yahoo_stealth_buddy(int id, const char *who, int unstealth)
4180 struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
4181 struct yahoo_data *yd;
4182 struct yahoo_packet *pkt;
4184 if(!yid)
4185 return;
4186 yd = yid->yd;
4188 if (!yd->logged_in)
4189 return;
4191 pkt = yahoo_packet_new(YAHOO_SERVICE_STEALTH, YAHOO_STATUS_AVAILABLE, yd->session_id);
4192 yahoo_packet_hash(pkt, 1, yd->user);
4193 yahoo_packet_hash(pkt, 7, who);
4194 yahoo_packet_hash(pkt, 31, unstealth?"2":"1");
4195 yahoo_packet_hash(pkt, 13, "2");
4196 yahoo_send_packet(yid, pkt, 0);
4197 yahoo_packet_free(pkt);
4200 void yahoo_change_buddy_group(int id, const char *who, const char *old_group, const char *new_group)
4202 struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
4203 struct yahoo_data *yd;
4204 struct yahoo_packet *pkt = NULL;
4206 if(!yid)
4207 return;
4208 yd = yid->yd;
4210 pkt = yahoo_packet_new(YAHOO_SERVICE_ADDBUDDY, YAHOO_STATUS_AVAILABLE, yd->session_id);
4211 yahoo_packet_hash(pkt, 1, yd->user);
4212 yahoo_packet_hash(pkt, 7, who);
4213 yahoo_packet_hash(pkt, 65, new_group);
4214 yahoo_packet_hash(pkt, 14, " ");
4216 yahoo_send_packet(yid, pkt, 0);
4217 yahoo_packet_free(pkt);
4219 pkt = yahoo_packet_new(YAHOO_SERVICE_REMBUDDY, YAHOO_STATUS_AVAILABLE, yd->session_id);
4220 yahoo_packet_hash(pkt, 1, yd->user);
4221 yahoo_packet_hash(pkt, 7, who);
4222 yahoo_packet_hash(pkt, 65, old_group);
4223 yahoo_send_packet(yid, pkt, 0);
4224 yahoo_packet_free(pkt);
4227 void yahoo_group_rename(int id, const char *old_group, const char *new_group)
4229 struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
4230 struct yahoo_data *yd;
4231 struct yahoo_packet *pkt = NULL;
4233 if(!yid)
4234 return;
4235 yd = yid->yd;
4237 pkt = yahoo_packet_new(YAHOO_SERVICE_GROUPRENAME, YAHOO_STATUS_AVAILABLE, yd->session_id);
4238 yahoo_packet_hash(pkt, 1, yd->user);
4239 yahoo_packet_hash(pkt, 65, old_group);
4240 yahoo_packet_hash(pkt, 67, new_group);
4242 yahoo_send_packet(yid, pkt, 0);
4243 yahoo_packet_free(pkt);
4246 void yahoo_conference_addinvite(int id, const char * from, const char *who, const char *room, const YList * members, const char *msg)
4248 struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
4249 struct yahoo_data *yd;
4250 struct yahoo_packet *pkt;
4252 if(!yid)
4253 return;
4254 yd = yid->yd;
4256 pkt = yahoo_packet_new(YAHOO_SERVICE_CONFADDINVITE, YAHOO_STATUS_AVAILABLE, yd->session_id);
4258 yahoo_packet_hash(pkt, 1, (from?from:yd->user));
4259 yahoo_packet_hash(pkt, 51, who);
4260 yahoo_packet_hash(pkt, 57, room);
4261 yahoo_packet_hash(pkt, 58, msg);
4262 yahoo_packet_hash(pkt, 13, "0");
4263 for(; members; members = members->next) {
4264 yahoo_packet_hash(pkt, 52, (char *)members->data);
4265 yahoo_packet_hash(pkt, 53, (char *)members->data);
4267 /* 52, 53 -> other members? */
4269 yahoo_send_packet(yid, pkt, 0);
4271 yahoo_packet_free(pkt);
4274 void yahoo_conference_invite(int id, const char * from, YList *who, const char *room, const char *msg)
4276 struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
4277 struct yahoo_data *yd;
4278 struct yahoo_packet *pkt;
4280 if(!yid)
4281 return;
4282 yd = yid->yd;
4284 pkt = yahoo_packet_new(YAHOO_SERVICE_CONFINVITE, YAHOO_STATUS_AVAILABLE, yd->session_id);
4286 yahoo_packet_hash(pkt, 1, (from?from:yd->user));
4287 yahoo_packet_hash(pkt, 50, yd->user);
4288 for(; who; who = who->next) {
4289 yahoo_packet_hash(pkt, 52, (char *)who->data);
4291 yahoo_packet_hash(pkt, 57, room);
4292 yahoo_packet_hash(pkt, 58, msg);
4293 yahoo_packet_hash(pkt, 13, "0");
4295 yahoo_send_packet(yid, pkt, 0);
4297 yahoo_packet_free(pkt);
4300 void yahoo_conference_logon(int id, const char *from, YList *who, const char *room)
4302 struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
4303 struct yahoo_data *yd;
4304 struct yahoo_packet *pkt;
4306 if(!yid)
4307 return;
4308 yd = yid->yd;
4310 pkt = yahoo_packet_new(YAHOO_SERVICE_CONFLOGON, YAHOO_STATUS_AVAILABLE, yd->session_id);
4312 yahoo_packet_hash(pkt, 1, (from?from:yd->user));
4313 for(; who; who = who->next) {
4314 yahoo_packet_hash(pkt, 3, (char *)who->data);
4316 yahoo_packet_hash(pkt, 57, room);
4318 yahoo_send_packet(yid, pkt, 0);
4320 yahoo_packet_free(pkt);
4323 void yahoo_conference_decline(int id, const char * from, YList *who, const char *room, const char *msg)
4325 struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
4326 struct yahoo_data *yd;
4327 struct yahoo_packet *pkt;
4329 if(!yid)
4330 return;
4331 yd = yid->yd;
4333 pkt = yahoo_packet_new(YAHOO_SERVICE_CONFDECLINE, YAHOO_STATUS_AVAILABLE, yd->session_id);
4335 yahoo_packet_hash(pkt, 1, (from?from:yd->user));
4336 for(; who; who = who->next) {
4337 yahoo_packet_hash(pkt, 3, (char *)who->data);
4339 yahoo_packet_hash(pkt, 57, room);
4340 yahoo_packet_hash(pkt, 14, msg);
4342 yahoo_send_packet(yid, pkt, 0);
4344 yahoo_packet_free(pkt);
4347 void yahoo_conference_logoff(int id, const char * from, YList *who, const char *room)
4349 struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
4350 struct yahoo_data *yd;
4351 struct yahoo_packet *pkt;
4353 if(!yid)
4354 return;
4355 yd = yid->yd;
4357 pkt = yahoo_packet_new(YAHOO_SERVICE_CONFLOGOFF, YAHOO_STATUS_AVAILABLE, yd->session_id);
4359 yahoo_packet_hash(pkt, 1, (from?from:yd->user));
4360 for(; who; who = who->next) {
4361 yahoo_packet_hash(pkt, 3, (char *)who->data);
4363 yahoo_packet_hash(pkt, 57, room);
4365 yahoo_send_packet(yid, pkt, 0);
4367 yahoo_packet_free(pkt);
4370 void yahoo_conference_message(int id, const char * from, YList *who, const char *room, const char *msg, int utf8)
4372 struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
4373 struct yahoo_data *yd;
4374 struct yahoo_packet *pkt;
4376 if(!yid)
4377 return;
4378 yd = yid->yd;
4380 pkt = yahoo_packet_new(YAHOO_SERVICE_CONFMSG, YAHOO_STATUS_AVAILABLE, yd->session_id);
4382 yahoo_packet_hash(pkt, 1, (from?from:yd->user));
4383 for(; who; who = who->next) {
4384 yahoo_packet_hash(pkt, 53, (char *)who->data);
4386 yahoo_packet_hash(pkt, 57, room);
4387 yahoo_packet_hash(pkt, 14, msg);
4389 if(utf8)
4390 yahoo_packet_hash(pkt, 97, "1");
4392 yahoo_send_packet(yid, pkt, 0);
4394 yahoo_packet_free(pkt);
4397 void yahoo_get_chatrooms(int id, int chatroomid)
4399 struct yahoo_data *yd = find_conn_by_id(id);
4400 struct yahoo_input_data *yid;
4401 char url[1024];
4402 char buff[1024];
4404 if(!yd)
4405 return;
4407 yid = y_new0(struct yahoo_input_data, 1);
4408 yid->yd = yd;
4409 yid->type = YAHOO_CONNECTION_CHATCAT;
4411 if (chatroomid == 0) {
4412 snprintf(url, 1024, "http://insider.msg.yahoo.com/ycontent/?chatcat=0");
4413 } else {
4414 snprintf(url, 1024, "http://insider.msg.yahoo.com/ycontent/?chatroom_%d=0",chatroomid);
4417 snprintf(buff, sizeof(buff), "Y=%s; T=%s", yd->cookie_y, yd->cookie_t);
4419 inputs = y_list_prepend(inputs, yid);
4421 yahoo_http_get(yid->yd->client_id, url, buff, _yahoo_http_connected, yid);
4424 void yahoo_chat_logon(int id, const char *from, const char *room, const char *roomid)
4426 struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
4427 struct yahoo_data *yd;
4428 struct yahoo_packet *pkt;
4430 if(!yid)
4431 return;
4433 yd = yid->yd;
4435 pkt = yahoo_packet_new(YAHOO_SERVICE_CHATONLINE, YAHOO_STATUS_AVAILABLE, yd->session_id);
4437 yahoo_packet_hash(pkt, 1, (from?from:yd->user));
4438 yahoo_packet_hash(pkt, 109, yd->user);
4439 yahoo_packet_hash(pkt, 6, "abcde");
4441 yahoo_send_packet(yid, pkt, 0);
4443 yahoo_packet_free(pkt);
4445 pkt = yahoo_packet_new(YAHOO_SERVICE_CHATJOIN, YAHOO_STATUS_AVAILABLE, yd->session_id);
4447 yahoo_packet_hash(pkt, 1, (from?from:yd->user));
4448 yahoo_packet_hash(pkt, 104, room);
4449 yahoo_packet_hash(pkt, 129, roomid);
4450 yahoo_packet_hash(pkt, 62, "2"); /* ??? */
4452 yahoo_send_packet(yid, pkt, 0);
4454 yahoo_packet_free(pkt);
4458 void yahoo_chat_message(int id, const char *from, const char *room, const char *msg, const int msgtype, const int utf8)
4460 struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
4461 struct yahoo_data *yd;
4462 struct yahoo_packet *pkt;
4463 char buf[2];
4465 if(!yid)
4466 return;
4468 yd = yid->yd;
4470 pkt = yahoo_packet_new(YAHOO_SERVICE_COMMENT, YAHOO_STATUS_AVAILABLE, yd->session_id);
4472 yahoo_packet_hash(pkt, 1, (from?from:yd->user));
4473 yahoo_packet_hash(pkt, 104, room);
4474 yahoo_packet_hash(pkt, 117, msg);
4476 snprintf(buf, sizeof(buf), "%d", msgtype);
4477 yahoo_packet_hash(pkt, 124, buf);
4479 if(utf8)
4480 yahoo_packet_hash(pkt, 97, "1");
4482 yahoo_send_packet(yid, pkt, 0);
4484 yahoo_packet_free(pkt);
4488 void yahoo_chat_logoff(int id, const char *from)
4490 struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
4491 struct yahoo_data *yd;
4492 struct yahoo_packet *pkt;
4494 if(!yid)
4495 return;
4497 yd = yid->yd;
4499 pkt = yahoo_packet_new(YAHOO_SERVICE_CHATLOGOUT, YAHOO_STATUS_AVAILABLE, yd->session_id);
4501 yahoo_packet_hash(pkt, 1, (from?from:yd->user));
4503 yahoo_send_packet(yid, pkt, 0);
4505 yahoo_packet_free(pkt);
4508 void yahoo_buddyicon_request(int id, const char *who)
4510 struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
4511 struct yahoo_data *yd;
4512 struct yahoo_packet *pkt;
4514 if( !yid )
4515 return;
4517 yd = yid->yd;
4519 pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE, YAHOO_STATUS_AVAILABLE, 0);
4520 yahoo_packet_hash(pkt, 4, yd->user);
4521 yahoo_packet_hash(pkt, 5, who);
4522 yahoo_packet_hash(pkt, 13, "1");
4523 yahoo_send_packet(yid, pkt, 0);
4525 yahoo_packet_free(pkt);
4528 void yahoo_send_picture_info(int id, const char *who, const char *url, int checksum)
4530 struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
4531 struct yahoo_data *yd;
4532 struct yahoo_packet *pkt;
4533 char checksum_str[10];
4535 if( !yid )
4536 return;
4538 yd = yid->yd;
4540 snprintf(checksum_str, sizeof(checksum_str), "%d", checksum);
4542 pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE, YAHOO_STATUS_AVAILABLE, 0);
4543 yahoo_packet_hash(pkt, 1, yd->user);
4544 yahoo_packet_hash(pkt, 4, yd->user);
4545 yahoo_packet_hash(pkt, 5, who);
4546 yahoo_packet_hash(pkt, 13, "2");
4547 yahoo_packet_hash(pkt, 20, url);
4548 yahoo_packet_hash(pkt, 192, checksum_str);
4549 yahoo_send_packet(yid, pkt, 0);
4551 yahoo_packet_free(pkt);
4554 void yahoo_send_picture_update(int id, const char *who, int type)
4556 struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
4557 struct yahoo_data *yd;
4558 struct yahoo_packet *pkt;
4559 char type_str[10];
4561 if( !yid )
4562 return;
4564 yd = yid->yd;
4566 snprintf(type_str, sizeof(type_str), "%d", type);
4568 pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE_UPDATE, YAHOO_STATUS_AVAILABLE, 0);
4569 yahoo_packet_hash(pkt, 1, yd->user);
4570 yahoo_packet_hash(pkt, 5, who);
4571 yahoo_packet_hash(pkt, 206, type_str);
4572 yahoo_send_packet(yid, pkt, 0);
4574 yahoo_packet_free(pkt);
4577 void yahoo_send_picture_checksum(int id, const char *who, int checksum)
4579 struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
4580 struct yahoo_data *yd;
4581 struct yahoo_packet *pkt;
4582 char checksum_str[10];
4584 if( !yid )
4585 return;
4587 yd = yid->yd;
4589 snprintf(checksum_str, sizeof(checksum_str), "%d", checksum);
4591 pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE_CHECKSUM, YAHOO_STATUS_AVAILABLE, 0);
4592 yahoo_packet_hash(pkt, 1, yd->user);
4593 if( who != 0 )
4594 yahoo_packet_hash(pkt, 5, who);
4595 yahoo_packet_hash(pkt, 192, checksum_str);
4596 yahoo_packet_hash(pkt, 212, "1");
4597 yahoo_send_packet(yid, pkt, 0);
4599 yahoo_packet_free(pkt);
4602 void yahoo_webcam_close_feed(int id, const char *who)
4604 struct yahoo_input_data *yid = find_input_by_id_and_webcam_user(id, who);
4606 if(yid)
4607 yahoo_input_close(yid);
4610 void yahoo_webcam_get_feed(int id, const char *who)
4612 struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
4613 struct yahoo_data *yd;
4614 struct yahoo_packet *pkt;
4616 if(!yid)
4617 return;
4620 * add the user to the queue. this is a dirty hack, since
4621 * the yahoo server doesn't tell us who's key it's returning,
4622 * we have to just hope that it sends back keys in the same
4623 * order that we request them.
4624 * The queue is popped in yahoo_process_webcam_key
4626 webcam_queue = y_list_append(webcam_queue, who?strdup(who):NULL);
4628 yd = yid->yd;
4630 pkt = yahoo_packet_new(YAHOO_SERVICE_WEBCAM, YAHOO_STATUS_AVAILABLE, yd->session_id);
4632 yahoo_packet_hash(pkt, 1, yd->user);
4633 if (who != NULL)
4634 yahoo_packet_hash(pkt, 5, who);
4635 yahoo_send_packet(yid, pkt, 0);
4637 yahoo_packet_free(pkt);
4640 void yahoo_webcam_send_image(int id, unsigned char *image, unsigned int length, unsigned int timestamp)
4642 struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_WEBCAM);
4643 unsigned char *packet;
4644 unsigned char header_len = 13;
4645 unsigned int pos = 0;
4647 if (!yid)
4648 return;
4650 packet = y_new0(unsigned char, header_len);
4652 packet[pos++] = header_len;
4653 packet[pos++] = 0;
4654 packet[pos++] = 5; /* version byte?? */
4655 packet[pos++] = 0;
4656 pos += yahoo_put32(packet + pos, length);
4657 packet[pos++] = 2; /* packet type, image */
4658 pos += yahoo_put32(packet + pos, timestamp);
4659 yahoo_add_to_send_queue(yid, packet, header_len);
4660 FREE(packet);
4662 if (length)
4663 yahoo_add_to_send_queue(yid, image, length);
4666 void yahoo_webcam_accept_viewer(int id, const char* who, int accept)
4668 struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_WEBCAM);
4669 char *packet = NULL;
4670 char *data = NULL;
4671 unsigned char header_len = 13;
4672 unsigned int pos = 0;
4673 unsigned int len = 0;
4675 if (!yid)
4676 return;
4678 data = strdup("u=");
4679 data = y_string_append(data, (char*)who);
4680 data = y_string_append(data, "\r\n");
4681 len = strlen(data);
4683 packet = y_new0(char, header_len + len);
4684 packet[pos++] = header_len;
4685 packet[pos++] = 0;
4686 packet[pos++] = 5; /* version byte?? */
4687 packet[pos++] = 0;
4688 pos += yahoo_put32(packet + pos, len);
4689 packet[pos++] = 0; /* packet type */
4690 pos += yahoo_put32(packet + pos, accept);
4691 memcpy(packet + pos, data, len);
4692 FREE(data);
4693 yahoo_add_to_send_queue(yid, packet, header_len + len);
4694 FREE(packet);
4697 void yahoo_webcam_invite(int id, const char *who)
4699 struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
4700 struct yahoo_packet *pkt;
4702 if(!yid)
4703 return;
4705 pkt = yahoo_packet_new(YAHOO_SERVICE_NOTIFY, YAHOO_STATUS_NOTIFY, yid->yd->session_id);
4707 yahoo_packet_hash(pkt, 49, "WEBCAMINVITE");
4708 yahoo_packet_hash(pkt, 14, " ");
4709 yahoo_packet_hash(pkt, 13, "0");
4710 yahoo_packet_hash(pkt, 1, yid->yd->user);
4711 yahoo_packet_hash(pkt, 5, who);
4712 yahoo_send_packet(yid, pkt, 0);
4714 yahoo_packet_free(pkt);
4717 static void yahoo_search_internal(int id, int t, const char *text, int g, int ar, int photo, int yahoo_only, int startpos, int total)
4719 struct yahoo_data *yd = find_conn_by_id(id);
4720 struct yahoo_input_data *yid;
4721 char url[1024];
4722 char buff[1024];
4723 char *ctext, *p;
4725 if(!yd)
4726 return;
4728 yid = y_new0(struct yahoo_input_data, 1);
4729 yid->yd = yd;
4730 yid->type = YAHOO_CONNECTION_SEARCH;
4733 age range
4734 .ar=1 - 13-18, 2 - 18-25, 3 - 25-35, 4 - 35-50, 5 - 50-70, 6 - 70+
4737 snprintf(buff, sizeof(buff), "&.sq=%%20&.tt=%d&.ss=%d", total, startpos);
4739 ctext = strdup(text);
4740 while((p = strchr(ctext, ' ')))
4741 *p = '+';
4743 snprintf(url, 1024, "http://members.yahoo.com/interests?.oc=m&.kw=%s&.sb=%d&.g=%d&.ar=0%s%s%s",
4744 ctext, t, g, photo ? "&.p=y" : "", yahoo_only ? "&.pg=y" : "",
4745 startpos ? buff : "");
4747 FREE(ctext);
4749 snprintf(buff, sizeof(buff), "Y=%s; T=%s", yd->cookie_y, yd->cookie_t);
4751 inputs = y_list_prepend(inputs, yid);
4752 yahoo_http_get(yid->yd->client_id, url, buff, _yahoo_http_connected, yid);
4755 void yahoo_search(int id, enum yahoo_search_type t, const char *text, enum yahoo_search_gender g, enum yahoo_search_agerange ar,
4756 int photo, int yahoo_only)
4758 struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
4759 struct yahoo_search_state *yss;
4761 if(!yid)
4762 return;
4764 if(!yid->ys)
4765 yid->ys = y_new0(struct yahoo_search_state, 1);
4767 yss = yid->ys;
4769 FREE(yss->lsearch_text);
4770 yss->lsearch_type = t;
4771 yss->lsearch_text = strdup(text);
4772 yss->lsearch_gender = g;
4773 yss->lsearch_agerange = ar;
4774 yss->lsearch_photo = photo;
4775 yss->lsearch_yahoo_only = yahoo_only;
4777 yahoo_search_internal(id, t, text, g, ar, photo, yahoo_only, 0, 0);
4780 void yahoo_search_again(int id, int start)
4782 struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
4783 struct yahoo_search_state *yss;
4785 if(!yid || !yid->ys)
4786 return;
4788 yss = yid->ys;
4790 if(start == -1)
4791 start = yss->lsearch_nstart + yss->lsearch_nfound;
4793 yahoo_search_internal(id, yss->lsearch_type, yss->lsearch_text,
4794 yss->lsearch_gender, yss->lsearch_agerange,
4795 yss->lsearch_photo, yss->lsearch_yahoo_only,
4796 start, yss->lsearch_ntotal);
4799 struct send_file_data {
4800 struct yahoo_packet *pkt;
4801 yahoo_get_fd_callback callback;
4802 void *user_data;
4805 static void _yahoo_send_picture_connected(int id, int fd, int error, void *data)
4807 struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_FT);
4808 struct send_file_data *sfd = data;
4809 struct yahoo_packet *pkt = sfd->pkt;
4810 unsigned char buff[1024];
4812 if(fd <= 0) {
4813 sfd->callback(id, fd, error, sfd->user_data);
4814 FREE(sfd);
4815 yahoo_packet_free(pkt);
4816 inputs = y_list_remove(inputs, yid);
4817 FREE(yid);
4818 return;
4821 yid->fd = fd;
4822 yahoo_send_packet(yid, pkt, 8);
4823 yahoo_packet_free(pkt);
4825 snprintf((char *)buff, sizeof(buff), "29");
4826 buff[2] = 0xc0;
4827 buff[3] = 0x80;
4829 write(yid->fd, buff, 4);
4831 /* YAHOO_CALLBACK(ext_yahoo_add_handler)(nyd->fd, YAHOO_INPUT_READ); */
4833 sfd->callback(id, fd, error, sfd->user_data);
4834 FREE(sfd);
4835 inputs = y_list_remove(inputs, yid);
4837 while(yahoo_tcp_readline(buff, sizeof(buff), nyd->fd) > 0) {
4838 if(!strcmp(buff, ""))
4839 break;
4843 yahoo_input_close(yid);
4846 void yahoo_send_picture(int id, const char *name, unsigned long size,
4847 yahoo_get_fd_callback callback, void *data)
4849 struct yahoo_data *yd = find_conn_by_id(id);
4850 struct yahoo_input_data *yid;
4851 struct yahoo_server_settings *yss;
4852 struct yahoo_packet *pkt = NULL;
4853 char size_str[10];
4854 char expire_str[10];
4855 long content_length=0;
4856 unsigned char buff[1024];
4857 char url[255];
4858 struct send_file_data *sfd;
4860 if(!yd)
4861 return;
4863 yss = yd->server_settings;
4865 yid = y_new0(struct yahoo_input_data, 1);
4866 yid->yd = yd;
4867 yid->type = YAHOO_CONNECTION_FT;
4869 pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE_UPLOAD, YAHOO_STATUS_AVAILABLE, yd->session_id);
4871 snprintf(size_str, sizeof(size_str), "%ld", size);
4872 snprintf(expire_str, sizeof(expire_str), "%ld", (long)604800);
4874 yahoo_packet_hash(pkt, 0, yd->user);
4875 yahoo_packet_hash(pkt, 1, yd->user);
4876 yahoo_packet_hash(pkt, 14, "");
4877 yahoo_packet_hash(pkt, 27, name);
4878 yahoo_packet_hash(pkt, 28, size_str);
4879 yahoo_packet_hash(pkt, 38, expire_str);
4882 content_length = YAHOO_PACKET_HDRLEN + yahoo_packet_length(pkt);
4884 snprintf(url, sizeof(url), "http://%s:%d/notifyft",
4885 yss->filetransfer_host, yss->filetransfer_port);
4886 snprintf((char *)buff, sizeof(buff), "Y=%s; T=%s",
4887 yd->cookie_y, yd->cookie_t);
4888 inputs = y_list_prepend(inputs, yid);
4890 sfd = y_new0(struct send_file_data, 1);
4891 sfd->pkt = pkt;
4892 sfd->callback = callback;
4893 sfd->user_data = data;
4894 yahoo_http_post(yid->yd->client_id, url, (char *)buff, content_length+4+size,
4895 _yahoo_send_picture_connected, sfd);
4898 static void _yahoo_send_file_connected(int id, int fd, int error, void *data)
4900 struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_FT);
4901 struct send_file_data *sfd = data;
4902 struct yahoo_packet *pkt = sfd->pkt;
4903 unsigned char buff[1024];
4905 if(fd <= 0) {
4906 sfd->callback(id, fd, error, sfd->user_data);
4907 FREE(sfd);
4908 yahoo_packet_free(pkt);
4909 inputs = y_list_remove(inputs, yid);
4910 FREE(yid);
4911 return;
4914 yid->fd = fd;
4915 yahoo_send_packet(yid, pkt, 8);
4916 yahoo_packet_free(pkt);
4918 snprintf((char *)buff, sizeof(buff), "29");
4919 buff[2] = 0xc0;
4920 buff[3] = 0x80;
4922 write(yid->fd, buff, 4);
4924 /* YAHOO_CALLBACK(ext_yahoo_add_handler)(nyd->fd, YAHOO_INPUT_READ); */
4926 sfd->callback(id, fd, error, sfd->user_data);
4927 FREE(sfd);
4928 inputs = y_list_remove(inputs, yid);
4930 while(yahoo_tcp_readline(buff, sizeof(buff), nyd->fd) > 0) {
4931 if(!strcmp(buff, ""))
4932 break;
4936 yahoo_input_close(yid);
4939 void yahoo_send_file(int id, const char *who, const char *msg,
4940 const char *name, unsigned long size,
4941 yahoo_get_fd_callback callback, void *data)
4943 struct yahoo_data *yd = find_conn_by_id(id);
4944 struct yahoo_input_data *yid;
4945 struct yahoo_server_settings *yss;
4946 struct yahoo_packet *pkt = NULL;
4947 char size_str[10];
4948 long content_length=0;
4949 unsigned char buff[1024];
4950 char url[255];
4951 struct send_file_data *sfd;
4953 if(!yd)
4954 return;
4956 yss = yd->server_settings;
4958 yid = y_new0(struct yahoo_input_data, 1);
4959 yid->yd = yd;
4960 yid->type = YAHOO_CONNECTION_FT;
4962 pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANSFER, YAHOO_STATUS_AVAILABLE, yd->session_id);
4964 snprintf(size_str, sizeof(size_str), "%ld", size);
4966 yahoo_packet_hash(pkt, 0, yd->user);
4967 yahoo_packet_hash(pkt, 5, who);
4968 yahoo_packet_hash(pkt, 14, msg);
4969 yahoo_packet_hash(pkt, 27, name);
4970 yahoo_packet_hash(pkt, 28, size_str);
4972 content_length = YAHOO_PACKET_HDRLEN + yahoo_packet_length(pkt);
4974 snprintf(url, sizeof(url), "http://%s:%d/notifyft",
4975 yss->filetransfer_host, yss->filetransfer_port);
4976 snprintf((char *)buff, sizeof(buff), "Y=%s; T=%s",
4977 yd->cookie_y, yd->cookie_t);
4978 inputs = y_list_prepend(inputs, yid);
4980 sfd = y_new0(struct send_file_data, 1);
4981 sfd->pkt = pkt;
4982 sfd->callback = callback;
4983 sfd->user_data = data;
4984 yahoo_http_post(yid->yd->client_id, url, (char *)buff, content_length+4+size,
4985 _yahoo_send_file_connected, sfd);
4989 enum yahoo_status yahoo_current_status(int id)
4991 struct yahoo_data *yd = find_conn_by_id(id);
4992 if(!yd)
4993 return YAHOO_STATUS_OFFLINE;
4994 return yd->current_status;
4997 const YList * yahoo_get_buddylist(int id)
4999 struct yahoo_data *yd = find_conn_by_id(id);
5000 if(!yd)
5001 return NULL;
5002 return yd->buddies;
5005 const YList * yahoo_get_ignorelist(int id)
5007 struct yahoo_data *yd = find_conn_by_id(id);
5008 if(!yd)
5009 return NULL;
5010 return yd->ignore;
5013 const YList * yahoo_get_identities(int id)
5015 struct yahoo_data *yd = find_conn_by_id(id);
5016 if(!yd)
5017 return NULL;
5018 return yd->identities;
5021 const char * yahoo_get_cookie(int id, const char *which)
5023 struct yahoo_data *yd = find_conn_by_id(id);
5024 if(!yd)
5025 return NULL;
5026 if(!strncasecmp(which, "y", 1))
5027 return yd->cookie_y;
5028 if(!strncasecmp(which, "t", 1))
5029 return yd->cookie_t;
5030 if(!strncasecmp(which, "c", 1))
5031 return yd->cookie_c;
5032 if(!strncasecmp(which, "login", 5))
5033 return yd->login_cookie;
5034 return NULL;
5037 void yahoo_get_url_handle(int id, const char *url,
5038 yahoo_get_url_handle_callback callback, void *data)
5040 struct yahoo_data *yd = find_conn_by_id(id);
5041 if(!yd)
5042 return;
5044 yahoo_get_url_fd(id, url, yd, callback, data);
5047 const char * yahoo_get_profile_url( void )
5049 return profile_url;