diff options
Diffstat (limited to 'protocols/yahoo/libyahoo2.c')
-rw-r--r-- | protocols/yahoo/libyahoo2.c | 5711 |
1 files changed, 0 insertions, 5711 deletions
diff --git a/protocols/yahoo/libyahoo2.c b/protocols/yahoo/libyahoo2.c deleted file mode 100644 index b6f20e16..00000000 --- a/protocols/yahoo/libyahoo2.c +++ /dev/null @@ -1,5711 +0,0 @@ -/* - * libyahoo2: libyahoo2.c - * - * Some code copyright (C) 2002-2004, Philip S Tellis <philip.tellis AT gmx.net> - * YMSG16 code copyright (C) 2009, - * Siddhesh Poyarekar <siddhesh dot poyarekar at gmail dot com> - * - * Yahoo Search copyright (C) 2003, Konstantin Klyagin <konst AT konst.org.ua> - * - * Much of this code was taken and adapted from the yahoo module for - * gaim released under the GNU GPL. This code is also released under the - * GNU GPL. - * - * This code is derivative of Gaim <http://gaim.sourceforge.net> - * copyright (C) 1998-1999, Mark Spencer <markster@marko.net> - * 1998-1999, Adam Fritzler <afritz@marko.net> - * 1998-2002, Rob Flynn <rob@marko.net> - * 2000-2002, Eric Warmenhoven <eric@warmenhoven.org> - * 2001-2002, Brian Macke <macke@strangelove.net> - * 2001, Anand Biligiri S <abiligiri@users.sf.net> - * 2001, Valdis Kletnieks - * 2002, Sean Egan <bj91704@binghamton.edu> - * 2002, Toby Gray <toby.gray@ntlworld.com> - * - * This library also uses code from other libraries, namely: - * Portions from libfaim copyright 1998, 1999 Adam Fritzler - * <afritz@auk.cx> - * Portions of Sylpheed copyright 2000-2002 Hiroyuki Yamamoto - * <hiro-y@kcn.ne.jp> - * - * YMSG16 authentication code based mostly on write-up at: - * http://www.carbonize.co.uk/ymsg16.html - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include <unistd.h> -#include <errno.h> -#include <stdio.h> -#include <stdarg.h> - -#if STDC_HEADERS -# include <string.h> -#else -# if !HAVE_STRCHR -# define strchr index -# define strrchr rindex -# endif -char *strchr(), *strrchr(); -# if !HAVE_MEMCPY -# define memcpy(d, s, n) bcopy((s), (d), (n)) -# define memmove(d, s, n) bcopy((s), (d), (n)) -# endif -#endif - -#include <sys/types.h> - -#ifdef __MINGW32__ -# include <winsock2.h> -#endif - -#include <stdlib.h> -#include <ctype.h> - -#include "sha1.h" -#include "md5.h" -#include "yahoo2.h" -#include "yahoo_httplib.h" -#include "yahoo_util.h" - -#include "yahoo2_callbacks.h" -#include "yahoo_debug.h" -#if defined(__MINGW32__) && !defined(HAVE_GLIB) -#define snprintf _snprintf -#define vsnprintf _vsnprintf -#endif - -#include "base64.h" -#include "http_client.h" - -#ifdef USE_STRUCT_CALLBACKS -struct yahoo_callbacks *yc = NULL; - -void yahoo_register_callbacks(struct yahoo_callbacks *tyc) -{ - yc = tyc; -} - -#define YAHOO_CALLBACK(x) yc->x -#else -#define YAHOO_CALLBACK(x) x -#endif - -static int yahoo_send_data(void *fd, void *data, int len); -static void _yahoo_http_connected(int id, void *fd, int error, void *data); -static void yahoo_connected(void *fd, int error, void *data); - -int yahoo_log_message(char *fmt, ...) -{ - char out[1024]; - va_list ap; - - va_start(ap, fmt); - vsnprintf(out, sizeof(out), fmt, ap); - va_end(ap); - return YAHOO_CALLBACK (ext_yahoo_log) ("%s", out); -} - -static enum yahoo_log_level log_level = YAHOO_LOG_NONE; - -enum yahoo_log_level yahoo_get_log_level() -{ - return log_level; -} - -int yahoo_set_log_level(enum yahoo_log_level level) -{ - enum yahoo_log_level l = log_level; - - log_level = level; - return l; -} - -/* default values for servers */ -static char *default_pager_hosts[] = { "scs.msg.yahoo.com", - "scsa.msg.yahoo.com", - "scsb.msg.yahoo.com", - "scsc.msg.yahoo.com", - NULL }; - -static int pager_port = 5050; -static int fallback_ports[] = { 23, 25, 80, 20, 119, 8001, 8002, 5050, 0 }; - -static char filetransfer_host[] = "filetransfer.msg.yahoo.com"; -static int filetransfer_port = 80; -static char webcam_host[] = "webcam.yahoo.com"; -static int webcam_port = 5100; -static char webcam_description[] = ""; -static char local_host[] = ""; -static int conn_type = Y_WCM_DSL; - -static char profile_url[] = "http://profiles.yahoo.com/"; - -struct connect_callback_data { - struct yahoo_data *yd; - int tag; - int i; - int server_i; -}; - -struct yahoo_pair { - int key; - char *value; -}; - -struct yahoo_packet { - unsigned short int service; - unsigned int status; - unsigned int id; - YList *hash; -}; - -struct yahoo_search_state { - int lsearch_type; - char *lsearch_text; - int lsearch_gender; - int lsearch_agerange; - int lsearch_photo; - int lsearch_yahoo_only; - int lsearch_nstart; - int lsearch_nfound; - int lsearch_ntotal; -}; - -struct data_queue { - unsigned char *queue; - int len; -}; - -struct yahoo_input_data { - struct yahoo_data *yd; - struct yahoo_webcam *wcm; - struct yahoo_webcam_data *wcd; - struct yahoo_search_state *ys; - - void *fd; - enum yahoo_connection_type type; - - unsigned char *rxqueue; - int rxlen; - int read_tag; - - YList *txqueues; - int write_tag; -}; - -struct yahoo_server_settings { - char *pager_host; - int pager_port; - char *filetransfer_host; - int filetransfer_port; - char *webcam_host; - int webcam_port; - char *webcam_description; - char *local_host; - int conn_type; - char **pager_host_list; -}; - -static void yahoo_process_ft_connection(struct yahoo_input_data *yid, int over); - -static void yahoo_process_filetransfer(struct yahoo_input_data *yid, - struct yahoo_packet *pkt); -static void yahoo_process_filetransferinfo(struct yahoo_input_data *yid, - struct yahoo_packet *pkt); -static void yahoo_process_filetransferaccept(struct yahoo_input_data *yid, - struct yahoo_packet *pkt); - -static void yahoo_https_auth(struct yahoo_input_data *yid, const char *seed, const char *sn); - -static void *_yahoo_default_server_settings() -{ - struct yahoo_server_settings *yss = - y_new0(struct yahoo_server_settings, 1); - - /* Give preference to the default host list - * Make sure that only one of the two is set at any time - */ - yss->pager_host = NULL; - yss->pager_host_list = default_pager_hosts; - - yss->pager_port = pager_port; - yss->filetransfer_host = strdup(filetransfer_host); - yss->filetransfer_port = filetransfer_port; - yss->webcam_host = strdup(webcam_host); - yss->webcam_port = webcam_port; - yss->webcam_description = strdup(webcam_description); - yss->local_host = strdup(local_host); - yss->conn_type = conn_type; - - return yss; -} - -static void *_yahoo_assign_server_settings(va_list ap) -{ - struct yahoo_server_settings *yss = _yahoo_default_server_settings(); - char *key; - char *svalue; - int nvalue; - char **pvalue; - - while (1) { - key = va_arg(ap, char *); - if (key == NULL) { - break; - } - - if (!strcmp(key, "pager_host")) { - svalue = va_arg(ap, char *); - free(yss->pager_host); - yss->pager_host = strdup(svalue); - yss->pager_host_list = NULL; - } else if (!strcmp(key, "pager_host_list")) { - pvalue = va_arg(ap, char **); - yss->pager_host_list = pvalue; - free(yss->pager_host); - yss->pager_host = NULL; - } else if (!strcmp(key, "pager_port")) { - nvalue = va_arg(ap, int); - yss->pager_port = nvalue; - } else if (!strcmp(key, "filetransfer_host")) { - svalue = va_arg(ap, char *); - free(yss->filetransfer_host); - yss->filetransfer_host = strdup(svalue); - } else if (!strcmp(key, "filetransfer_port")) { - nvalue = va_arg(ap, int); - yss->filetransfer_port = nvalue; - } else if (!strcmp(key, "webcam_host")) { - svalue = va_arg(ap, char *); - free(yss->webcam_host); - yss->webcam_host = strdup(svalue); - } else if (!strcmp(key, "webcam_port")) { - nvalue = va_arg(ap, int); - yss->webcam_port = nvalue; - } else if (!strcmp(key, "webcam_description")) { - svalue = va_arg(ap, char *); - free(yss->webcam_description); - yss->webcam_description = strdup(svalue); - } else if (!strcmp(key, "local_host")) { - svalue = va_arg(ap, char *); - free(yss->local_host); - yss->local_host = strdup(svalue); - } else if (!strcmp(key, "conn_type")) { - nvalue = va_arg(ap, int); - yss->conn_type = nvalue; - } else { - WARNING(("Unknown key passed to yahoo_init, " - "perhaps you didn't terminate the list " - "with NULL")); - } - } - - return yss; -} - -static void yahoo_free_server_settings(struct yahoo_server_settings *yss) -{ - if (!yss) { - return; - } - - free(yss->pager_host); - free(yss->filetransfer_host); - free(yss->webcam_host); - free(yss->webcam_description); - free(yss->local_host); - - free(yss); -} - -static YList *conns = NULL; -static YList *inputs = NULL; -static int last_id = 0; - -static void add_to_list(struct yahoo_data *yd) -{ - conns = y_list_prepend(conns, yd); -} - -static struct yahoo_data *find_conn_by_id(int id) -{ - YList *l; - - for (l = conns; l; l = y_list_next(l)) { - struct yahoo_data *yd = l->data; - if (yd->client_id == id) { - return yd; - } - } - return NULL; -} - -static void del_from_list(struct yahoo_data *yd) -{ - conns = y_list_remove(conns, yd); -} - -/* call repeatedly to get the next one */ -/* -static struct yahoo_input_data * find_input_by_id(int id) -{ - YList *l; - for(l = inputs; l; l = y_list_next(l)) { - struct yahoo_input_data *yid = l->data; - if(yid->yd->client_id == id) - return yid; - } - return NULL; -} -*/ - -#if 0 -static struct yahoo_input_data *find_input_by_id_and_webcam_user(int id, - const char *who) -{ - YList *l; - - LOG(("find_input_by_id_and_webcam_user")); - for (l = inputs; l; l = y_list_next(l)) { - struct yahoo_input_data *yid = l->data; - if (yid->type == YAHOO_CONNECTION_WEBCAM - && yid->yd->client_id == id && yid->wcm && ((who - && yid->wcm->user - && !strcmp(who, yid->wcm->user)) - || !(yid->wcm->user && !who))) { - return yid; - } - } - return NULL; -} -#endif - -static struct yahoo_input_data *find_input_by_id_and_type(int id, - enum yahoo_connection_type type) -{ - YList *l; - - LOG(("find_input_by_id_and_type")); - for (l = inputs; l; l = y_list_next(l)) { - struct yahoo_input_data *yid = l->data; - if (yid->type == type && yid->yd->client_id == id) { - return yid; - } - } - return NULL; -} - -static struct yahoo_input_data *find_input_by_id_and_fd(int id, void *fd) -{ - YList *l; - - LOG(("find_input_by_id_and_fd")); - for (l = inputs; l; l = y_list_next(l)) { - struct yahoo_input_data *yid = l->data; - if (yid->fd == fd && yid->yd->client_id == id) { - return yid; - } - } - return NULL; -} - -static int count_inputs_with_id(int id) -{ - int c = 0; - YList *l; - - LOG(("counting %d", id)); - for (l = inputs; l; l = y_list_next(l)) { - struct yahoo_input_data *yid = l->data; - if (yid->yd->client_id == id) { - c++; - } - } - LOG(("%d", c)); - return c; -} - -/* Free a buddy list */ -static void yahoo_free_buddies(YList *list) -{ - YList *l; - - for (l = list; l; l = l->next) { - struct yahoo_buddy *bud = l->data; - if (!bud) { - continue; - } - - FREE(bud->group); - FREE(bud->id); - FREE(bud->real_name); - if (bud->yab_entry) { - FREE(bud->yab_entry->fname); - FREE(bud->yab_entry->lname); - FREE(bud->yab_entry->nname); - FREE(bud->yab_entry->id); - FREE(bud->yab_entry->email); - FREE(bud->yab_entry->hphone); - FREE(bud->yab_entry->wphone); - FREE(bud->yab_entry->mphone); - FREE(bud->yab_entry); - } - FREE(bud); - l->data = bud = NULL; - } - - y_list_free(list); -} - -/* Free an identities list */ -static void yahoo_free_identities(YList *list) -{ - while (list) { - YList *n = list; - FREE(list->data); - list = y_list_remove_link(list, list); - y_list_free_1(n); - } -} - -/* Free webcam data */ -static void yahoo_free_webcam(struct yahoo_webcam *wcm) -{ - if (wcm) { - FREE(wcm->user); - FREE(wcm->server); - FREE(wcm->key); - FREE(wcm->description); - FREE(wcm->my_ip); - } - FREE(wcm); -} - -static void yahoo_free_data(struct yahoo_data *yd) -{ - FREE(yd->user); - FREE(yd->password); - FREE(yd->cookie_y); - FREE(yd->cookie_t); - FREE(yd->cookie_b); - FREE(yd->cookie_c); - FREE(yd->login_cookie); - FREE(yd->login_id); - - yahoo_free_buddies(yd->buddies); - yahoo_free_buddies(yd->ignore); - yahoo_free_identities(yd->identities); - - yahoo_free_server_settings(yd->server_settings); - - FREE(yd); -} - -#define YAHOO_PACKET_HDRLEN (4 + 2 + 2 + 2 + 2 + 4 + 4) - -static struct yahoo_packet *yahoo_packet_new(enum yahoo_service service, - enum ypacket_status status, int id) -{ - struct yahoo_packet *pkt = y_new0(struct yahoo_packet, 1); - - pkt->service = service; - pkt->status = status; - pkt->id = id; - - return pkt; -} - -static void yahoo_packet_hash(struct yahoo_packet *pkt, int key, - const char *value) -{ - struct yahoo_pair *pair = y_new0(struct yahoo_pair, 1); - - pair->key = key; - pair->value = strdup(value); - pkt->hash = y_list_append(pkt->hash, pair); -} - -static int yahoo_packet_length(struct yahoo_packet *pkt) -{ - YList *l; - - int len = 0; - - for (l = pkt->hash; l; l = l->next) { - struct yahoo_pair *pair = l->data; - int tmp = pair->key; - do { - tmp /= 10; - len++; - } while (tmp); - len += 2; - len += strlen(pair->value); - len += 2; - } - - return len; -} - -#define yahoo_put16(buf, data) ( \ - (*(buf) = (unsigned char) ((data) >> 8) & 0xff), \ - (*((buf) + 1) = (unsigned char) (data) & 0xff), \ - 2) -#define yahoo_get16(buf) ((((*(buf)) & 0xff) << 8) + ((*((buf) + 1)) & 0xff)) -#define yahoo_put32(buf, data) ( \ - (*((buf)) = (unsigned char) ((data) >> 24) & 0xff), \ - (*((buf) + 1) = (unsigned char) ((data) >> 16) & 0xff), \ - (*((buf) + 2) = (unsigned char) ((data) >> 8) & 0xff), \ - (*((buf) + 3) = (unsigned char) (data) & 0xff), \ - 4) -#define yahoo_get32(buf) ((((*(buf)) & 0xff) << 24) + \ - (((*((buf) + 1)) & 0xff) << 16) + \ - (((*((buf) + 2)) & 0xff) << 8) + \ - (((*((buf) + 3)) & 0xff))) - -static void yahoo_packet_read(struct yahoo_packet *pkt, unsigned char *data, - int len) -{ - int pos = 0; - - while (pos + 1 < len) { - char *key, *value = NULL; - int accept; - int x; - - struct yahoo_pair *pair = y_new0(struct yahoo_pair, 1); - - key = malloc(len + 1); - x = 0; - while (pos + 1 < len) { - if (data[pos] == 0xc0 && data[pos + 1] == 0x80) { - break; - } - key[x++] = data[pos++]; - } - key[x] = 0; - pos += 2; - pair->key = strtol(key, NULL, 10); - free(key); - - /* Libyahoo2 developer(s) don't seem to have the time to fix - this problem, so for now try to work around it: - - Sometimes we receive an invalid packet with not any more - data at this point. I don't know how to handle this in a - clean way, but let's hope this is clean enough: */ - - if (pos + 1 < len) { - accept = x; - /* if x is 0 there was no key, so don't accept it */ - if (accept) { - value = malloc(len - pos + 1); - } - x = 0; - while (pos + 1 < len) { - if (data[pos] == 0xc0 && data[pos + 1] == 0x80) { - break; - } - if (accept) { - value[x++] = data[pos++]; - } - } - if (accept) { - value[x] = 0; - } - pos += 2; - } else { - accept = 0; - } - - if (accept) { - pair->value = strdup(value); - FREE(value); - pkt->hash = y_list_append(pkt->hash, pair); - DEBUG_MSG(("Key: %d \tValue: %s", pair->key, - pair->value)); - } else { - FREE(pair); - } - } -} - -static void yahoo_packet_write(struct yahoo_packet *pkt, unsigned char *data) -{ - YList *l; - int pos = 0; - - for (l = pkt->hash; l; l = l->next) { - struct yahoo_pair *pair = l->data; - unsigned char buf[100]; - - snprintf((char *) buf, sizeof(buf), "%d", pair->key); - strcpy((char *) data + pos, (char *) buf); - pos += strlen((char *) buf); - data[pos++] = 0xc0; - data[pos++] = 0x80; - - strcpy((char *) data + pos, pair->value); - pos += strlen(pair->value); - data[pos++] = 0xc0; - data[pos++] = 0x80; - } -} - -static void yahoo_dump_unhandled(struct yahoo_packet *pkt) -{ - YList *l; - - NOTICE(("Service: 0x%02x\tStatus: %d", pkt->service, pkt->status)); - for (l = pkt->hash; l; l = l->next) { - struct yahoo_pair *pair = l->data; - NOTICE(("\t%d => %s", pair->key, pair->value)); - } -} - -static void yahoo_packet_dump(unsigned char *data, int len) -{ - if (yahoo_get_log_level() >= YAHOO_LOG_DEBUG) { - int i; - for (i = 0; i < len; i++) { - if ((i % 8 == 0) && i) { - YAHOO_CALLBACK (ext_yahoo_log) (" "); - } - if ((i % 16 == 0) && i) { - YAHOO_CALLBACK (ext_yahoo_log) ("\n"); - } - YAHOO_CALLBACK (ext_yahoo_log) ("%02x ", data[i]); - } - YAHOO_CALLBACK (ext_yahoo_log) ("\n"); - for (i = 0; i < len; i++) { - if ((i % 8 == 0) && i) { - YAHOO_CALLBACK (ext_yahoo_log) (" "); - } - if ((i % 16 == 0) && i) { - YAHOO_CALLBACK (ext_yahoo_log) ("\n"); - } - if (isprint(data[i])) { - YAHOO_CALLBACK (ext_yahoo_log) (" %c ", data[i]); - } else { - YAHOO_CALLBACK (ext_yahoo_log) (" . "); - } - } - YAHOO_CALLBACK (ext_yahoo_log) ("\n"); - } -} - -/* yahoo's variant of base64 */ -static void to_y64(unsigned char *out, const unsigned char *in, int inlen) -{ - char *encoded = base64_encode(in, inlen); - int i = 0; - - do { - if (encoded[i] == '+') { - out[i] = '.'; - } else if (encoded[i] == '/') { - out[i] = '_'; - } else if (encoded[i] == '=') { - out[i] = '-'; - } else { - out[i] = encoded[i]; - } - } while (encoded[i++]); - - g_free(encoded); -} - -static void yahoo_add_to_send_queue(struct yahoo_input_data *yid, void *data, - int length) -{ - struct data_queue *tx = y_new0(struct data_queue, 1); - - tx->queue = y_new0(unsigned char, length); - tx->len = length; - memcpy(tx->queue, data, length); - - yid->txqueues = y_list_append(yid->txqueues, tx); - - if (!yid->write_tag) { - yid->write_tag = - YAHOO_CALLBACK (ext_yahoo_add_handler) (yid->yd-> - client_id, yid->fd, YAHOO_INPUT_WRITE, yid); - } -} - -static void yahoo_send_packet(struct yahoo_input_data *yid, - struct yahoo_packet *pkt, int extra_pad) -{ - int pktlen = yahoo_packet_length(pkt); - int len = YAHOO_PACKET_HDRLEN + pktlen; - unsigned char *data; - int pos = 0; - - if (yid->fd < 0) { - return; - } - - data = y_new0(unsigned char, len + 1); - - memcpy(data + pos, "YMSG", 4); - pos += 4; - pos += yahoo_put16(data + pos, YAHOO_PROTO_VER); /* version [latest 12 0x000c] */ - pos += yahoo_put16(data + pos, 0x0000); /* HIWORD pkt length??? */ - pos += yahoo_put16(data + pos, pktlen + extra_pad); /* LOWORD pkt length? */ - pos += yahoo_put16(data + pos, pkt->service); /* service */ - pos += yahoo_put32(data + pos, pkt->status); /* status [4bytes] */ - pos += yahoo_put32(data + pos, pkt->id); /* session [4bytes] */ - - yahoo_packet_write(pkt, data + pos); - - yahoo_packet_dump(data, len); - - if (yid->type == YAHOO_CONNECTION_FT) { - yahoo_send_data(yid->fd, data, len); - } else { - yahoo_add_to_send_queue(yid, data, len); - } - FREE(data); -} - -static void yahoo_packet_free(struct yahoo_packet *pkt) -{ - while (pkt->hash) { - struct yahoo_pair *pair = pkt->hash->data; - YList *tmp; - FREE(pair->value); - FREE(pair); - tmp = pkt->hash; - pkt->hash = y_list_remove_link(pkt->hash, pkt->hash); - y_list_free_1(tmp); - } - FREE(pkt); -} - -static int yahoo_send_data(void *fd, void *data, int len) -{ - int ret; - int e; - - if (fd == NULL) { - return -1; - } - - yahoo_packet_dump(data, len); - - do { - ret = YAHOO_CALLBACK (ext_yahoo_write) (fd, data, len); - } while (ret == -1 && errno == EINTR); - e = errno; - - if (ret == -1) { - LOG(("wrote data: ERR %s", strerror(errno))); - } else { - LOG(("wrote data: OK")); - } - - errno = e; - return ret; -} - -void yahoo_close(int id) -{ - struct yahoo_data *yd = find_conn_by_id(id); - - if (!yd) { - return; - } - - del_from_list(yd); - - yahoo_free_data(yd); - if (id == last_id) { - last_id--; - } -} - -static void yahoo_input_close(struct yahoo_input_data *yid) -{ - inputs = y_list_remove(inputs, yid); - - LOG(("yahoo_input_close(read)")); - YAHOO_CALLBACK (ext_yahoo_remove_handler) (yid->yd->client_id, - yid->read_tag); - LOG(("yahoo_input_close(write)")); - YAHOO_CALLBACK (ext_yahoo_remove_handler) (yid->yd->client_id, - yid->write_tag); - yid->read_tag = yid->write_tag = 0; - if (yid->fd) { - YAHOO_CALLBACK (ext_yahoo_close) (yid->fd); - } - yid->fd = 0; - FREE(yid->rxqueue); - if (count_inputs_with_id(yid->yd->client_id) == 0) { - LOG(("closing %d", yid->yd->client_id)); - yahoo_close(yid->yd->client_id); - } - yahoo_free_webcam(yid->wcm); - if (yid->wcd) { - FREE(yid->wcd); - } - if (yid->ys) { - FREE(yid->ys->lsearch_text); - FREE(yid->ys); - } - FREE(yid); -} - -static int is_same_bud(const void *a, const void *b) -{ - const struct yahoo_buddy *subject = a; - const struct yahoo_buddy *object = b; - - return strcmp(subject->id, object->id); -} - -static char *getcookie(char *rawcookie) -{ - char *cookie = NULL; - char *tmpcookie; - char *cookieend; - - if (strlen(rawcookie) < 2) { - return NULL; - } - - tmpcookie = strdup(rawcookie + 2); - cookieend = strchr(tmpcookie, ';'); - - if (cookieend) { - *cookieend = '\0'; - } - - cookie = strdup(tmpcookie); - FREE(tmpcookie); - /* cookieend=NULL; not sure why this was there since the value is not preserved in the stack -dd */ - - return cookie; -} - -static char *getlcookie(char *cookie) -{ - char *tmp; - char *tmpend; - char *login_cookie = NULL; - - tmpend = strstr(cookie, "n="); - if (tmpend) { - tmp = strdup(tmpend + 2); - tmpend = strchr(tmp, '&'); - if (tmpend) { - *tmpend = '\0'; - } - login_cookie = strdup(tmp); - FREE(tmp); - } - - return login_cookie; -} - -static void yahoo_process_notify(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) -{ - struct yahoo_data *yd = yid->yd; - char *msg = NULL; - char *from = NULL; - char *to = NULL; - int stat = 0; - int accept = 0; - char *ind = NULL; - YList *l; - - for (l = pkt->hash; l; l = l->next) { - struct yahoo_pair *pair = l->data; - if (pair->key == 4) { - from = pair->value; - } - if (pair->key == 5) { - to = pair->value; - } - if (pair->key == 49) { - msg = pair->value; - } - if (pair->key == 13) { - stat = atoi(pair->value); - } - if (pair->key == 14) { - ind = pair->value; - } - if (pair->key == 16) { /* status == -1 */ - NOTICE((pair->value)); - return; - } - - } - - if (!msg) { - return; - } - - if (!strncasecmp(msg, "TYPING", strlen("TYPING"))) { - YAHOO_CALLBACK (ext_yahoo_typing_notify) (yd->client_id, to, - from, stat); - } else if (!strncasecmp(msg, "GAME", strlen("GAME"))) { - YAHOO_CALLBACK (ext_yahoo_game_notify) (yd->client_id, to, from, - stat, ind); - } else if (!strncasecmp(msg, "WEBCAMINVITE", strlen("WEBCAMINVITE"))) { - if (!strcmp(ind, " ")) { - YAHOO_CALLBACK (ext_yahoo_webcam_invite) (yd->client_id, - to, from); - } else { - accept = atoi(ind); - /* accept the invitation (-1 = deny 1 = accept) */ - if (accept < 0) { - accept = 0; - } - YAHOO_CALLBACK (ext_yahoo_webcam_invite_reply) (yd-> - client_id, to, from, accept); - } - } else { - LOG(("Got unknown notification: %s", msg)); - } -} - -static void yahoo_process_conference(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) -{ - struct yahoo_data *yd = yid->yd; - char *msg = NULL; - char *host = NULL; - char *who = NULL; - char *room = NULL; - char *id = NULL; - int utf8 = 0; - YList *members = NULL; - YList *l; - - for (l = pkt->hash; l; l = l->next) { - struct yahoo_pair *pair = l->data; - if (pair->key == 50) { - host = pair->value; - } - - if (pair->key == 52) { /* invite */ - members = y_list_append(members, strdup(pair->value)); - } - if (pair->key == 53) { /* logon */ - who = pair->value; - } - if (pair->key == 54) { /* decline */ - who = pair->value; - } - if (pair->key == 55) { /* unavailable (status == 2) */ - who = pair->value; - } - if (pair->key == 56) { /* logoff */ - who = pair->value; - } - - if (pair->key == 57) { - room = pair->value; - } - - if (pair->key == 58) { /* join message */ - msg = pair->value; - } - if (pair->key == 14) { /* decline/conf message */ - msg = pair->value; - } - - if (pair->key == 13) { - ; - } - if (pair->key == 16) { /* error */ - msg = pair->value; - } - - if (pair->key == 1) { /* my id */ - id = pair->value; - } - if (pair->key == 3) { /* message sender */ - who = pair->value; - } - - if (pair->key == 97) { - utf8 = atoi(pair->value); - } - } - - if (!room) { - return; - } - - if (host) { - for (l = members; l; l = l->next) { - char *w = l->data; - if (!strcmp(w, host)) { - break; - } - } - if (!l) { - members = y_list_append(members, strdup(host)); - } - } - /* invite, decline, join, left, message -> status == 1 */ - - switch (pkt->service) { - case YAHOO_SERVICE_CONFINVITE: - if (pkt->status == 2) { - ; - } else if (members) { - YAHOO_CALLBACK (ext_yahoo_got_conf_invite) (yd-> - client_id, id, host, room, msg, members); - } else if (msg) { - YAHOO_CALLBACK (ext_yahoo_error) (yd->client_id, msg, 0, - E_CONFNOTAVAIL); - } - break; - case YAHOO_SERVICE_CONFADDINVITE: - if (pkt->status == 1) { - YAHOO_CALLBACK (ext_yahoo_got_conf_invite) (yd-> - client_id, id, host, room, msg, members); - } - break; - case YAHOO_SERVICE_CONFDECLINE: - if (who) { - YAHOO_CALLBACK (ext_yahoo_conf_userdecline) (yd-> - client_id, id, who, room, msg); - } - break; - case YAHOO_SERVICE_CONFLOGON: - if (who) { - YAHOO_CALLBACK (ext_yahoo_conf_userjoin) (yd->client_id, - id, who, room); - } - break; - case YAHOO_SERVICE_CONFLOGOFF: - if (who) { - YAHOO_CALLBACK (ext_yahoo_conf_userleave) (yd->client_id, - id, who, room); - } - break; - case YAHOO_SERVICE_CONFMSG: - if (who) { - YAHOO_CALLBACK (ext_yahoo_conf_message) (yd->client_id, - id, who, room, msg, utf8); - } - break; - } -} - -static void yahoo_process_chat(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) -{ - char *msg = NULL; - char *id = NULL; - char *who = NULL; - char *room = NULL; - char *topic = NULL; - YList *members = NULL; - struct yahoo_chat_member *currentmember = NULL; - int msgtype = 1; - int utf8 = 0; - int firstjoin = 0; - int membercount = 0; - int chaterr = 0; - YList *l; - - yahoo_dump_unhandled(pkt); - for (l = pkt->hash; l; l = l->next) { - struct yahoo_pair *pair = l->data; - - if (pair->key == 1) { - /* My identity */ - id = pair->value; - } - - if (pair->key == 104) { - /* Room name */ - room = pair->value; - } - - if (pair->key == 105) { - /* Room topic */ - topic = pair->value; - } - - if (pair->key == 108) { - /* Number of members in this packet */ - membercount = atoi(pair->value); - } - - if (pair->key == 109) { - /* message sender */ - who = pair->value; - - if (pkt->service == YAHOO_SERVICE_CHATJOIN) { - currentmember = - y_new0(struct yahoo_chat_member, 1); - currentmember->id = strdup(pair->value); - members = y_list_append(members, currentmember); - } - } - - if (pair->key == 110) { - /* age */ - if (pkt->service == YAHOO_SERVICE_CHATJOIN) { - currentmember->age = atoi(pair->value); - } - } - - if (pair->key == 113) { - /* attribs */ - if (pkt->service == YAHOO_SERVICE_CHATJOIN) { - currentmember->attribs = atoi(pair->value); - } - } - - if (pair->key == 141) { - /* alias */ - if (pkt->service == YAHOO_SERVICE_CHATJOIN) { - currentmember->alias = strdup(pair->value); - } - } - - if (pair->key == 142) { - /* location */ - if (pkt->service == YAHOO_SERVICE_CHATJOIN) { - currentmember->location = strdup(pair->value); - } - } - - if (pair->key == 130) { - /* first join */ - firstjoin = 1; - } - - if (pair->key == 117) { - /* message */ - msg = pair->value; - } - - if (pair->key == 124) { - /* Message type */ - msgtype = atoi(pair->value); - } - if (pair->key == 114) { - /* message error not sure what all the pair values mean */ - /* but -1 means no session in room */ - chaterr = atoi(pair->value); - } - } - - if (!room) { - if (pkt->service == YAHOO_SERVICE_CHATLOGOUT) { /* yahoo originated chat logout */ - YAHOO_CALLBACK (ext_yahoo_chat_yahoologout) (yid->yd-> - client_id, id); - return; - } - if (pkt->service == YAHOO_SERVICE_COMMENT && chaterr) { - YAHOO_CALLBACK (ext_yahoo_chat_yahooerror) (yid->yd-> - client_id, id); - return; - } - - WARNING(("We didn't get a room name, ignoring packet")); - return; - } - - switch (pkt->service) { - case YAHOO_SERVICE_CHATJOIN: - if (y_list_length(members) != membercount) { - WARNING(("Count of members doesn't match No. of members we got")); - } - if (firstjoin && members) { - YAHOO_CALLBACK (ext_yahoo_chat_join) (yid->yd->client_id, - id, room, topic, members, yid->fd); - } else if (who) { - if (y_list_length(members) != 1) { - WARNING(("Got more than 1 member on a normal join")); - } - /* this should only ever have one, but just in case */ - while (members) { - YList *n = members->next; - currentmember = members->data; - YAHOO_CALLBACK (ext_yahoo_chat_userjoin) (yid-> - yd->client_id, id, room, currentmember); - y_list_free_1(members); - members = n; - } - } - break; - case YAHOO_SERVICE_CHATEXIT: - if (who) { - YAHOO_CALLBACK (ext_yahoo_chat_userleave) (yid->yd-> - client_id, id, room, who); - } - break; - case YAHOO_SERVICE_COMMENT: - if (who) { - YAHOO_CALLBACK (ext_yahoo_chat_message) (yid->yd-> - client_id, id, who, room, msg, msgtype, utf8); - } - break; - } -} - -static void yahoo_process_message(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) -{ - struct yahoo_data *yd = yid->yd; - YList *l; - YList *messages = NULL; - - struct m { - int i_31; - int i_32; - char *to; - char *from; - long tm; - char *msg; - int utf8; - char *gunk; - } *message = y_new0(struct m, 1); - - for (l = pkt->hash; l; l = l->next) { - struct yahoo_pair *pair = l->data; - if (pair->key == 1 || pair->key == 4) { - if (!message->from) { - message->from = pair->value; - } - } else if (pair->key == 5) { - message->to = pair->value; - } else if (pair->key == 15) { - message->tm = strtol(pair->value, NULL, 10); - } else if (pair->key == 97) { - message->utf8 = atoi(pair->value); - } - /* This comes when the official client sends us a message */ - else if (pair->key == 429) { - message->gunk = pair->value; - } - /* user message *//* sys message */ - else if (pair->key == 14 || pair->key == 16) { - message->msg = pair->value; - } else if (pair->key == 31) { - if (message->i_31) { - messages = y_list_append(messages, message); - message = y_new0(struct m, 1); - } - message->i_31 = atoi(pair->value); - } else if (pair->key == 32) { - message->i_32 = atoi(pair->value); - } else { - LOG(("yahoo_process_message: status: %d, key: %d, value: %s", pkt->status, pair->key, - pair->value)); - } - } - - messages = y_list_append(messages, message); - - for (l = messages; l; l = l->next) { - message = l->data; - if (pkt->service == YAHOO_SERVICE_SYSMESSAGE) { - YAHOO_CALLBACK (ext_yahoo_system_message) (yd->client_id, - message->to, message->from, message->msg); - } else if (pkt->status <= 2 || pkt->status == 5) { - /* Confirm message receipt if we got the gunk */ - if (message->gunk) { - struct yahoo_packet *outpkt; - - outpkt = yahoo_packet_new(YAHOO_SERVICE_MESSAGE_CONFIRM, - YPACKET_STATUS_DEFAULT, 0); - yahoo_packet_hash(outpkt, 1, yd->user); - yahoo_packet_hash(outpkt, 5, message->from); - yahoo_packet_hash(outpkt, 302, "430"); - yahoo_packet_hash(outpkt, 430, message->gunk); - yahoo_packet_hash(outpkt, 303, "430"); - yahoo_packet_hash(outpkt, 450, "0"); - yahoo_send_packet(yid, outpkt, 0); - - yahoo_packet_free(outpkt); - } - - if (!strcmp(message->msg, "<ding>")) { - YAHOO_CALLBACK (ext_yahoo_got_buzz) (yd->client_id, - message->to, message->from, message->tm); - } else { - YAHOO_CALLBACK (ext_yahoo_got_im) (yd->client_id, - message->to, message->from, message->msg, - message->tm, pkt->status, message->utf8); - } - } else if (pkt->status == 0xffffffff) { - YAHOO_CALLBACK (ext_yahoo_error) (yd->client_id, - message->msg, 0, E_SYSTEM); - } - FREE(message); - } - - y_list_free(messages); -} - -/* - * Here's what multi-level packets look like. Data in brackets is the value. - * - * 3 level: - * ======= - * - * 302 (318) - Beginning level 1 - * 300 (318) - Begin level 2 - * 302 (319) - End level 2 header - * 300 (319) - Begin level 3 - * 301 (319) - End level 3 - * 303 (319) - End level 2 - * 303 (318) - End level 1 - * - * 2 level: - * ======= - * - * 302 (315) - Beginning level 1 - * 300 (315) - Begin level 2 - * 301 (315) - End level 2 - * 303 (315) - End level 1 - * - */ -static void yahoo_process_status(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) -{ - YList *l; - struct yahoo_data *yd = yid->yd; - - struct yahoo_process_status_entry *u; - - YList *users = 0; - - if (pkt->service == YAHOO_SERVICE_LOGOFF && pkt->status == -1) { - YAHOO_CALLBACK (ext_yahoo_login_response) (yd->client_id, - YAHOO_LOGIN_DUPL, NULL); - return; - } - - /* - * Status updates may be spread across multiple packets and not - * even on buddy boundaries, so keeping some state is important. - * So, continue where we left off, and only add a user entry to - * the list once it's complete (301-315 End buddy). - */ - u = yd->half_user; - - for (l = pkt->hash; l; l = l->next) { - struct yahoo_pair *pair = l->data; - - switch (pair->key) { - case 300: /* Begin buddy */ - if (!strcmp(pair->value, "315") && !u) { - u = yd->half_user = y_new0(struct yahoo_process_status_entry, 1); - } - break; - case 301: /* End buddy */ - if (!strcmp(pair->value, "315") && u) { - /* Sometimes user info comes in an odd format with no - "begin buddy" but *with* an "end buddy". Don't add - it twice. */ - if (!y_list_find(users, u)) { - users = y_list_prepend(users, u); - } - u = yd->half_user = NULL; - } - break; - case 0: /* we won't actually do anything with this */ - NOTICE(("key %d:%s", pair->key, pair->value)); - break; - case 1: /* we don't get the full buddy list here. */ - if (!yd->logged_in) { - yd->logged_in = 1; - if (yd->current_status < 0) { - yd->current_status = yd->initial_status; - } - YAHOO_CALLBACK (ext_yahoo_login_response) (yd-> - client_id, YAHOO_LOGIN_OK, NULL); - } - break; - case 8: /* how many online buddies we have */ - NOTICE(("key %d:%s", pair->key, pair->value)); - break; - case 7: /* the current buddy */ - if (!u) { - /* This will only happen in case of a single level message */ - u = y_new0(struct yahoo_process_status_entry, 1); - users = y_list_prepend(users, u); - } - u->name = pair->value; - break; - case 10: /* state */ - u->state = strtol(pair->value, NULL, 10); - break; - case 19: /* custom status message */ - u->msg = pair->value; - break; - case 47: /* is it an away message or not. Not applicable for YMSG16 anymore */ - u->away = atoi(pair->value); - break; - case 137: /* seconds idle */ - u->idle = atoi(pair->value); - break; - case 11: /* this is the buddy's session id */ - u->buddy_session = atoi(pair->value); - break; - case 17: /* in chat? */ - u->f17 = atoi(pair->value); - break; - case 13: /* bitmask, bit 0 = pager, bit 1 = chat, bit 2 = game */ - u->flags = atoi(pair->value); - break; - case 60: /* SMS -> 1 MOBILE USER */ - /* sometimes going offline makes this 2, but invisible never sends it */ - u->mobile = atoi(pair->value); - break; - case 138: - u->f138 = atoi(pair->value); - break; - case 184: - u->f184 = pair->value; - break; - case 192: - u->f192 = atoi(pair->value); - break; - case 10001: - u->f10001 = atoi(pair->value); - break; - case 10002: - u->f10002 = atoi(pair->value); - break; - case 198: - u->f198 = atoi(pair->value); - break; - case 197: - u->f197 = pair->value; - break; - case 205: - u->f205 = pair->value; - break; - case 213: - u->f213 = atoi(pair->value); - break; - case 16: /* Custom error message */ - YAHOO_CALLBACK (ext_yahoo_error) (yd->client_id, - pair->value, 0, E_CUSTOM); - break; - default: - WARNING(("unknown status key %d:%s", pair->key, - pair->value)); - break; - } - } - - while (users) { - YList *t = users; - struct yahoo_process_status_entry *u = users->data; - - if (u->name != NULL) { - if (pkt->service == - YAHOO_SERVICE_LOGOFF - /*|| u->flags == 0 No flags for YMSG16 */) { - YAHOO_CALLBACK (ext_yahoo_status_changed) (yd-> - client_id, u->name, - YAHOO_STATUS_OFFLINE, NULL, 1, 0, 0); - } else { - /* Key 47 always seems to be 1 for YMSG16 */ - if (!u->state) { - u->away = 0; - } else { - u->away = 1; - } - - YAHOO_CALLBACK (ext_yahoo_status_changed) (yd-> - client_id, u->name, u->state, u->msg, - u->away, u->idle, u->mobile); - } - } - - users = y_list_remove_link(users, users); - y_list_free_1(t); - FREE(u); - } -} - -static void yahoo_process_buddy_list(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) -{ - struct yahoo_data *yd = yid->yd; - YList *l; - int last_packet = 0; - char *cur_group = NULL; - struct yahoo_buddy *newbud = NULL; - - /* we could be getting multiple packets here */ - for (l = pkt->hash; l; l = l->next) { - struct yahoo_pair *pair = l->data; - - switch (pair->key) { - case 300: - case 301: - case 302: - break; /* Separators. Our logic does not need them */ - case 303: - if (318 == atoi(pair->value)) { - last_packet = 1; - } - break; - case 65: - cur_group = strdup(pair->value); - break; - case 7: - newbud = y_new0(struct yahoo_buddy, 1); - newbud->id = strdup(pair->value); - if (cur_group) { - newbud->group = strdup(cur_group); - } else if (yd->buddies) { - struct yahoo_buddy *lastbud = - (struct yahoo_buddy *) y_list_nth(yd-> - buddies, - y_list_length(yd->buddies) - 1)->data; - newbud->group = strdup(lastbud->group); - } else { - newbud->group = strdup("Buddies"); - } - - yd->buddies = y_list_append(yd->buddies, newbud); - - break; - } - } - - /* we could be getting multiple packets here */ - if (pkt->hash && !last_packet) { - return; - } - - YAHOO_CALLBACK (ext_yahoo_got_buddies) (yd->client_id, yd->buddies); - - /* Logged in */ - if (!yd->logged_in) { - yd->logged_in = 1; - if (yd->current_status < 0) { - yd->current_status = yd->initial_status; - } - YAHOO_CALLBACK (ext_yahoo_login_response) (yd->client_id, - YAHOO_LOGIN_OK, NULL); - - /* - yahoo_set_away(yd->client_id, yd->initial_status, NULL, - (yd->initial_status == YAHOO_STATUS_AVAILABLE) ? 0 : 1); - - yahoo_get_yab(yd->client_id); - */ - } - -} - -static void yahoo_process_list(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) -{ - struct yahoo_data *yd = yid->yd; - YList *l; - - /* we could be getting multiple packets here */ - for (l = pkt->hash; l; l = l->next) { - struct yahoo_pair *pair = l->data; - - switch (pair->key) { - case 89: /* identities */ - { - char **identities = - y_strsplit(pair->value, ",", -1); - int i; - for (i = 0; identities[i]; i++) { - yd->identities = - y_list_append(yd->identities, - strdup(identities[i])); - } - y_strfreev(identities); - } - YAHOO_CALLBACK (ext_yahoo_got_identities) (yd->client_id, - yd->identities); - break; - case 59: /* cookies */ - if (pair->value[0] == 'Y') { - FREE(yd->cookie_y); - FREE(yd->login_cookie); - - yd->cookie_y = getcookie(pair->value); - yd->login_cookie = getlcookie(yd->cookie_y); - - } else if (pair->value[0] == 'T') { - FREE(yd->cookie_t); - yd->cookie_t = getcookie(pair->value); - - } else if (pair->value[0] == 'C') { - FREE(yd->cookie_c); - yd->cookie_c = getcookie(pair->value); - } - - break; - case 3: /* my id */ - case 90: /* 1 */ - case 100: /* 0 */ - case 101: /* NULL */ - case 102: /* NULL */ - case 93: /* 86400/1440 */ - break; - } - } - - if (yd->cookie_y && yd->cookie_t) { /* We don't get cookie_c anymore */ - YAHOO_CALLBACK (ext_yahoo_got_cookies) (yd->client_id); - } -} - -static void yahoo_process_verify(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) -{ - struct yahoo_data *yd = yid->yd; - - if (pkt->status != 0x01) { - DEBUG_MSG(("expected status: 0x01, got: %d", pkt->status)); - YAHOO_CALLBACK (ext_yahoo_login_response) (yd->client_id, - YAHOO_LOGIN_LOCK, ""); - return; - } - - pkt = yahoo_packet_new(YAHOO_SERVICE_AUTH, YPACKET_STATUS_DEFAULT, - yd->session_id); - - yahoo_packet_hash(pkt, 1, yd->user); - yahoo_send_packet(yid, pkt, 0); - - yahoo_packet_free(pkt); - -} - -static void yahoo_process_picture_checksum(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) -{ - struct yahoo_data *yd = yid->yd; - char *from = NULL; - char *to = NULL; - int checksum = 0; - YList *l; - - for (l = pkt->hash; l; l = l->next) { - struct yahoo_pair *pair = l->data; - - switch (pair->key) { - case 1: - case 4: - from = pair->value; - case 5: - to = pair->value; - break; - case 212: - break; - case 192: - checksum = atoi(pair->value); - break; - } - } - - YAHOO_CALLBACK (ext_yahoo_got_buddyicon_checksum) (yd->client_id, to, - from, checksum); -} - -static void yahoo_process_picture(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) -{ - struct yahoo_data *yd = yid->yd; - char *url = NULL; - char *from = NULL; - char *to = NULL; - int status = 0; - int checksum = 0; - YList *l; - - for (l = pkt->hash; l; l = l->next) { - struct yahoo_pair *pair = l->data; - - switch (pair->key) { - case 1: - case 4: /* sender */ - from = pair->value; - break; - case 5: /* we */ - to = pair->value; - break; - case 13: /* request / sending */ - status = atoi(pair->value); - break; - case 20: /* url */ - url = pair->value; - break; - case 192: /*checksum */ - checksum = atoi(pair->value); - break; - } - } - - switch (status) { - case 1: /* this is a request, ignore for now */ - YAHOO_CALLBACK (ext_yahoo_got_buddyicon_request) (yd->client_id, - to, from); - break; - case 2: /* this is cool - we get a picture :) */ - YAHOO_CALLBACK (ext_yahoo_got_buddyicon) (yd->client_id, to, - from, url, checksum); - break; - } -} - -static void yahoo_process_picture_upload(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) -{ - struct yahoo_data *yd = yid->yd; - YList *l; - char *url = NULL; - - if (pkt->status != 1) { - return; /* something went wrong */ - - } - for (l = pkt->hash; l; l = l->next) { - struct yahoo_pair *pair = l->data; - - switch (pair->key) { - case 5: /* we */ - break; - case 20: /* url */ - url = pair->value; - break; - case 27: /* local filename */ - break; - case 38: /* time */ - break; - } - } - - YAHOO_CALLBACK (ext_yahoo_buddyicon_uploaded) (yd->client_id, url); -} - -void yahoo_login(int id, int initial) -{ - struct yahoo_data *yd = find_conn_by_id(id); - struct connect_callback_data *ccd; - struct yahoo_server_settings *yss; - int tag; - - char *host; - - struct yahoo_input_data *yid = y_new0(struct yahoo_input_data, 1); - - yid->yd = yd; - yid->type = YAHOO_CONNECTION_PAGER; - inputs = y_list_prepend(inputs, yid); - - yd->initial_status = initial; - yss = yd->server_settings; - - ccd = y_new0(struct connect_callback_data, 1); - ccd->yd = yd; - - host = yss->pager_host; - - if (!host) { - host = yss->pager_host_list[0]; - } - - tag = YAHOO_CALLBACK (ext_yahoo_connect_async) (yd->client_id, - host, yss->pager_port, yahoo_connected, ccd, 0); - - /* - * if tag <= 0, then callback has already been called - * so ccd will have been freed - */ - if (tag > 0) { - ccd->tag = tag; - } else if (tag < 0) { - YAHOO_CALLBACK (ext_yahoo_login_response) (yd->client_id, - YAHOO_LOGIN_SOCK, NULL); - } -} - -struct yahoo_https_auth_data { - struct yahoo_input_data *yid; - char *token; - char *chal; -}; - -static void yahoo_https_auth_token_init(struct yahoo_https_auth_data *had); -static void yahoo_https_auth_token_finish(struct http_request *req); -static void yahoo_https_auth_init(struct yahoo_https_auth_data *had); -static void yahoo_https_auth_finish(struct http_request *req); - -/* Extract a value from a login.yahoo.com response. Assume CRLF-linebreaks - and FAIL miserably if they're not there... */ -static char *yahoo_ha_find_key(char *response, char *key) -{ - char *s, *end; - int len = strlen(key); - - s = response; - do { - if (strncmp(s, key, len) == 0 && s[len] == '=') { - s += len + 1; - if ((end = strchr(s, '\r'))) { - return g_strndup(s, end - s); - } else { - return g_strdup(s); - } - } - - if ((s = strchr(s, '\n'))) { - s++; - } - } while (s && *s); - - return NULL; -} - -static enum yahoo_status yahoo_https_status_parse(int code) -{ - switch (code) { - case 1212: return (enum yahoo_status) YAHOO_LOGIN_PASSWD; - case 1213: return (enum yahoo_status) YAHOO_LOGIN_LOCK; - case 1235: return (enum yahoo_status) YAHOO_LOGIN_UNAME; - default: return (enum yahoo_status) code; - } -} - -static void yahoo_https_auth(struct yahoo_input_data *yid, const char *seed, const char *sn) -{ - struct yahoo_https_auth_data *had = g_new0(struct yahoo_https_auth_data, 1); - - had->yid = yid; - had->chal = g_strdup(seed); - - yahoo_https_auth_token_init(had); -} - -static void yahoo_https_auth_token_init(struct yahoo_https_auth_data *had) -{ - struct yahoo_input_data *yid = had->yid; - struct yahoo_data *yd = yid->yd; - char *login, *passwd, *chal; - char *url; - - login = g_strndup(yd->user, 3 * strlen(yd->user)); - http_encode(login); - passwd = g_strndup(yd->password, 3 * strlen(yd->password)); - http_encode(passwd); - chal = g_strndup(had->chal, 3 * strlen(had->chal)); - http_encode(chal); - - url = g_strdup_printf("https://login.yahoo.com/config/pwtoken_get?src=ymsgr&ts=%d&login=%s&passwd=%s&chal=%s", - (int) time(NULL), login, passwd, chal); - - http_dorequest_url(url, yahoo_https_auth_token_finish, had); - - g_free(url); - g_free(chal); - g_free(passwd); - g_free(login); -} - -static void yahoo_https_auth_token_finish(struct http_request *req) -{ - struct yahoo_https_auth_data *had = req->data; - struct yahoo_input_data *yid; - struct yahoo_data *yd; - int st; - - if (y_list_find(inputs, had->yid) == NULL) { - return; - } - - yid = had->yid; - yd = yid->yd; - - if (req->status_code != 200) { - YAHOO_CALLBACK (ext_yahoo_login_response) (yd->client_id, 2000 + req->status_code, NULL); - goto fail; - } - - if (sscanf(req->reply_body, "%d", &st) != 1 || st != 0) { - YAHOO_CALLBACK (ext_yahoo_login_response) (yd->client_id, yahoo_https_status_parse(st), NULL); - goto fail; - } - - if ((had->token = yahoo_ha_find_key(req->reply_body, "ymsgr")) == NULL) { - YAHOO_CALLBACK (ext_yahoo_login_response) (yd->client_id, 3001, NULL); - goto fail; - } - - yahoo_https_auth_init(had); - return; - -fail: - g_free(had->token); - g_free(had->chal); - g_free(had); -} - -static void yahoo_https_auth_init(struct yahoo_https_auth_data *had) -{ - char *url; - - url = g_strdup_printf("https://login.yahoo.com/config/pwtoken_login?src=ymsgr&ts=%d&token=%s", - (int) time(NULL), had->token); - - http_dorequest_url(url, yahoo_https_auth_finish, had); - - g_free(url); -} - -static void yahoo_https_auth_finish(struct http_request *req) -{ - struct yahoo_https_auth_data *had = req->data; - struct yahoo_input_data *yid; - struct yahoo_data *yd; - struct yahoo_packet *pack; - char *crumb = NULL; - int st; - - if (y_list_find(inputs, had->yid) == NULL) { - return; - } - - yid = had->yid; - yd = yid->yd; - - md5_byte_t result[16]; - md5_state_t ctx; - - unsigned char yhash[32]; - - if (req->status_code != 200) { - YAHOO_CALLBACK (ext_yahoo_login_response) (yd->client_id, 2000 + req->status_code, NULL); - goto fail; - } - - if (sscanf(req->reply_body, "%d", &st) != 1 || st != 0) { - YAHOO_CALLBACK (ext_yahoo_login_response) (yd->client_id, yahoo_https_status_parse(st), NULL); - goto fail; - } - - if ((yd->cookie_y = yahoo_ha_find_key(req->reply_body, "Y")) == NULL || - (yd->cookie_t = yahoo_ha_find_key(req->reply_body, "T")) == NULL || - (crumb = yahoo_ha_find_key(req->reply_body, "crumb")) == NULL) { - YAHOO_CALLBACK (ext_yahoo_login_response) (yd->client_id, 3002, NULL); - goto fail; - } - - md5_init(&ctx); - md5_append(&ctx, (unsigned char *) crumb, 11); - md5_append(&ctx, (unsigned char *) had->chal, strlen(had->chal)); - md5_finish(&ctx, result); - to_y64(yhash, result, 16); - - pack = yahoo_packet_new(YAHOO_SERVICE_AUTHRESP, yd->initial_status, yd->session_id); - yahoo_packet_hash(pack, 1, yd->user); - yahoo_packet_hash(pack, 0, yd->user); - yahoo_packet_hash(pack, 277, yd->cookie_y); - yahoo_packet_hash(pack, 278, yd->cookie_t); - yahoo_packet_hash(pack, 307, (char *) yhash); - yahoo_packet_hash(pack, 244, "524223"); - yahoo_packet_hash(pack, 2, yd->user); - yahoo_packet_hash(pack, 2, "1"); - yahoo_packet_hash(pack, 98, "us"); - yahoo_packet_hash(pack, 135, "7.5.0.647"); - - yahoo_send_packet(yid, pack, 0); - - yahoo_packet_free(pack); - -fail: - g_free(crumb); - g_free(had->token); - g_free(had->chal); - g_free(had); -} - -static void yahoo_process_auth(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) -{ - char *seed = NULL; - char *sn = NULL; - YList *l = pkt->hash; - int m = 0; - struct yahoo_data *yd = yid->yd; - - while (l) { - struct yahoo_pair *pair = l->data; - - switch (pair->key) { - case 94: - seed = pair->value; - break; - case 1: - sn = pair->value; - break; - case 13: - m = atoi(pair->value); - break; - } - l = l->next; - } - - if (!seed) { - return; - } - - if (m == 2) { - yahoo_https_auth(yid, seed, sn); - } else { - /* call error */ - WARNING(("unknown auth type %d", m)); - YAHOO_CALLBACK (ext_yahoo_login_response) (yd->client_id, - YAHOO_LOGIN_UNKNOWN, NULL); - } -} - -static void yahoo_process_auth_resp(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) -{ - struct yahoo_data *yd = yid->yd; - char *url = NULL; - int login_status = -1; - - YList *l; - - for (l = pkt->hash; l; l = l->next) { - struct yahoo_pair *pair = l->data; - if (pair->key == 0) { - ; /* login_id */ - } else if (pair->key == 1) { - ; /* handle */ - } else if (pair->key == 20) { - url = pair->value; - } else if (pair->key == 66) { - login_status = atoi(pair->value); - } - } - - if (pkt->status == YPACKET_STATUS_DISCONNECTED) { - YAHOO_CALLBACK (ext_yahoo_login_response) (yd->client_id, - login_status, url); - /* yahoo_logoff(yd->client_id); */ - } -} - -static void yahoo_process_mail(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) -{ - struct yahoo_data *yd = yid->yd; - char *who = NULL; - char *email = NULL; - char *subj = NULL; - int count = 0; - YList *l; - - for (l = pkt->hash; l; l = l->next) { - struct yahoo_pair *pair = l->data; - if (pair->key == 9) { - count = strtol(pair->value, NULL, 10); - } else if (pair->key == 43) { - who = pair->value; - } else if (pair->key == 42) { - email = pair->value; - } else if (pair->key == 18) { - subj = pair->value; - } else { - LOG(("key: %d => value: %s", pair->key, pair->value)); - } - } - - if (who && email && subj) { - char from[1024]; - snprintf(from, sizeof(from), "%s (%s)", who, email); - YAHOO_CALLBACK (ext_yahoo_mail_notify) (yd->client_id, from, - subj, count); - } else if (count > 0) { - YAHOO_CALLBACK (ext_yahoo_mail_notify) (yd->client_id, NULL, - NULL, count); - } -} - -static void yahoo_process_new_contact(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) -{ - struct yahoo_data *yd = yid->yd; - char *me = NULL; - char *who = NULL; - char *msg = NULL; - int online = -1; - - YList *l; - - for (l = pkt->hash; l; l = l->next) { - struct yahoo_pair *pair = l->data; - if (pair->key == 4) { - who = pair->value; - } else if (pair->key == 5) { - me = pair->value; - } else if (pair->key == 14) { - msg = pair->value; - } else if (pair->key == 13) { - online = strtol(pair->value, NULL, 10); - } - } - - if (who && online < 0) { - YAHOO_CALLBACK (ext_yahoo_contact_added) (yd->client_id, me, who, - msg); - } else if (online == 2) { - YAHOO_CALLBACK (ext_yahoo_rejected) (yd->client_id, who, msg); - } -} - -/* UNUSED? */ -static void yahoo_process_contact(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) -{ - struct yahoo_data *yd = yid->yd; - char *id = NULL; - char *who = NULL; - char *msg = NULL; - char *name = NULL; - int state = YAHOO_STATUS_AVAILABLE; - int away = 0; - int idle = 0; - int mobile = 0; - - YList *l; - - for (l = pkt->hash; l; l = l->next) { - struct yahoo_pair *pair = l->data; - if (pair->key == 1) { - id = pair->value; - } else if (pair->key == 3) { - who = pair->value; - } else if (pair->key == 14) { - msg = pair->value; - } else if (pair->key == 7) { - name = pair->value; - } else if (pair->key == 10) { - state = strtol(pair->value, NULL, 10); - } else if (pair->key == 15) { - ; /* tm */ - } else if (pair->key == 13) { - ; /* online */ - } else if (pair->key == 47) { - away = strtol(pair->value, NULL, 10); - } else if (pair->key == 137) { - idle = strtol(pair->value, NULL, 10); - } else if (pair->key == 60) { - mobile = strtol(pair->value, NULL, 10); - } - - } - - if (id) { - YAHOO_CALLBACK (ext_yahoo_contact_added) (yd->client_id, id, who, - msg); - } else if (name) { - YAHOO_CALLBACK (ext_yahoo_status_changed) (yd->client_id, name, - state, msg, away, idle, mobile); - } else if (pkt->status == 0x07) { - YAHOO_CALLBACK (ext_yahoo_rejected) (yd->client_id, who, msg); - } -} - -static void yahoo_process_buddyadd(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) -{ - struct yahoo_data *yd = yid->yd; - char *who = NULL; - char *where = NULL; - int status = 0; - - struct yahoo_buddy *bud = NULL; - - YList *l; - - for (l = pkt->hash; l; l = l->next) { - struct yahoo_pair *pair = l->data; - if (pair->key == 1) { - ; /* Me... don't care */ - } - if (pair->key == 7) { - who = pair->value; - } - if (pair->key == 65) { - where = pair->value; - } - if (pair->key == 66) { - status = strtol(pair->value, NULL, 10); - } - } - - if (!who) { - return; - } - if (!where) { - where = "Unknown"; - } - - bud = y_new0(struct yahoo_buddy, 1); - bud->id = strdup(who); - bud->group = strdup(where); - bud->real_name = NULL; - - yd->buddies = y_list_append(yd->buddies, bud); - -#if 0 - /* BitlBee: This seems to be wrong in my experience. I think: - status = 0: Success - status = 2: Already on list - status = 3: Doesn't exist - status = 42: Invalid handle (possibly banned/reserved, I get it for - handles like joe or jjjjjj) - Haven't seen others yet. But whenever the add is successful, there - will be a separate "went online" packet when the auth. request is - accepted. Couldn't find any test account that doesn't require auth. - unfortunately (if there is even such a thing?) */ - - /* A non-zero status (i've seen 2) seems to mean the buddy is already - * added and is online */ - if (status) { - LOG(("Setting online see packet for info")); - yahoo_dump_unhandled(pkt); - YAHOO_CALLBACK (ext_yahoo_status_changed) (yd->client_id, who, - YAHOO_STATUS_AVAILABLE, NULL, 0, 0, 0); - } -#endif - /* BitlBee: Need ACK of added buddy, if it was successful. */ - if (status == 0) { - YList *tmp = y_list_append(NULL, bud); - YAHOO_CALLBACK (ext_yahoo_got_buddies) (yd->client_id, tmp); - y_list_free(tmp); - } -} - -static void yahoo_process_buddydel(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) -{ - struct yahoo_data *yd = yid->yd; - char *who = NULL; - char *where = NULL; - struct yahoo_buddy *bud; - - YList *buddy; - - YList *l; - - for (l = pkt->hash; l; l = l->next) { - struct yahoo_pair *pair = l->data; - if (pair->key == 1) { - ; /* Me... don't care */ - } else if (pair->key == 7) { - who = pair->value; - } else if (pair->key == 65) { - where = pair->value; - } else if (pair->key == 66) { - ; /* unk_66 */ - } else { - DEBUG_MSG(("unknown key: %d = %s", pair->key, - pair->value)); - } - } - - if (!who || !where) { - return; - } - - bud = y_new0(struct yahoo_buddy, 1); - bud->id = strdup(who); - bud->group = strdup(where); - - buddy = y_list_find_custom(yd->buddies, bud, is_same_bud); - - FREE(bud->id); - FREE(bud->group); - FREE(bud); - - if (buddy) { - bud = buddy->data; - yd->buddies = y_list_remove_link(yd->buddies, buddy); - y_list_free_1(buddy); - - FREE(bud->id); - FREE(bud->group); - FREE(bud->real_name); - FREE(bud); - - bud = NULL; - } -} - -static void yahoo_process_ignore(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) -{ - YList *l; - - for (l = pkt->hash; l; l = l->next) { - struct yahoo_pair *pair = l->data; - if (pair->key == 0) { - ; /* who */ - } - if (pair->key == 1) { - ; /* Me... don't care */ - } - if (pair->key == 13) { /* 1 == ignore, 2 == unignore */ - ; - } - if (pair->key == 66) { - ; /* status */ - } - } - - /* - * status - * 0 - ok - * 2 - already in ignore list, could not add - * 3 - not in ignore list, could not delete - * 12 - is a buddy, could not add - */ - -/* if(status) - YAHOO_CALLBACK(ext_yahoo_error)(yd->client_id, who, 0, status); -*/ -} - -static void yahoo_process_voicechat(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) -{ - char *who = NULL; - char *me = NULL; - char *room = NULL; - - YList *l; - - for (l = pkt->hash; l; l = l->next) { - struct yahoo_pair *pair = l->data; - if (pair->key == 4) { - who = pair->value; - } - if (pair->key == 5) { - me = pair->value; - } - if (pair->key == 13) { - ; /* voice room */ - } - if (pair->key == 57) { - room = pair->value; - } - } - - NOTICE(("got voice chat invite from %s in %s to identity %s", who, room, - me)); - /* - * send: s:0 1:me 5:who 57:room 13:1 - * ???? s:4 5:who 10:99 19:-1615114531 - * gotr: s:4 5:who 10:99 19:-1615114615 - * ???? s:1 5:me 4:who 57:room 13:3room - * got: s:1 5:me 4:who 57:room 13:1room - * rej: s:0 1:me 5:who 57:room 13:3 - * rejr: s:4 5:who 10:99 19:-1617114599 - */ -} - -static void yahoo_process_ping(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) -{ - char *errormsg = NULL; - - YList *l; - - for (l = pkt->hash; l; l = l->next) { - struct yahoo_pair *pair = l->data; - if (pair->key == 16) { - errormsg = pair->value; - } - } - - NOTICE(("got ping packet")); - YAHOO_CALLBACK (ext_yahoo_got_ping) (yid->yd->client_id, errormsg); -} - -static void yahoo_process_buddy_change_group(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) -{ - YList *l; - char *me = NULL; - char *who = NULL; - char *old_group = NULL; - char *new_group = NULL; - - for (l = pkt->hash; l; l = l->next) { - struct yahoo_pair *pair = l->data; - if (pair->key == 1) { - me = pair->value; - } - if (pair->key == 7) { - who = pair->value; - } - if (pair->key == 224) { - old_group = pair->value; - } - if (pair->key == 264) { - new_group = pair->value; - } - } - - YAHOO_CALLBACK (ext_yahoo_got_buddy_change_group) (yid->yd->client_id, - me, who, old_group, new_group); -} - -static void _yahoo_webcam_get_server_connected(void *fd, int error, void *d) -{ - struct yahoo_input_data *yid = d; - char *who = yid->wcm->user; - char *data = NULL; - char *packet = NULL; - unsigned char magic_nr[] = { 0, 1, 0 }; - unsigned char header_len = 8; - unsigned int len = 0; - unsigned int pos = 0; - - if (error || !fd) { - FREE(who); - FREE(yid); - return; - } - - yid->fd = fd; - inputs = y_list_prepend(inputs, yid); - - /* send initial packet */ - if (who) { - data = strdup("<RVWCFG>"); - } else { - data = strdup("<RUPCFG>"); - } - yahoo_add_to_send_queue(yid, data, strlen(data)); - FREE(data); - - /* send data */ - if (who) { - data = strdup("g="); - data = y_string_append(data, who); - data = y_string_append(data, "\r\n"); - } else { - data = strdup("f=1\r\n"); - } - len = strlen(data); - packet = y_new0(char, header_len + len); - packet[pos++] = header_len; - memcpy(packet + pos, magic_nr, sizeof(magic_nr)); - pos += sizeof(magic_nr); - pos += yahoo_put32(packet + pos, len); - memcpy(packet + pos, data, len); - pos += len; - yahoo_add_to_send_queue(yid, packet, pos); - FREE(packet); - FREE(data); - - yid->read_tag = - YAHOO_CALLBACK (ext_yahoo_add_handler) (yid->yd->client_id, fd, - YAHOO_INPUT_READ, yid); -} - -static void yahoo_webcam_get_server(struct yahoo_input_data *y, char *who, - char *key) -{ - struct yahoo_input_data *yid = y_new0(struct yahoo_input_data, 1); - struct yahoo_server_settings *yss = y->yd->server_settings; - - yid->type = YAHOO_CONNECTION_WEBCAM_MASTER; - yid->yd = y->yd; - yid->wcm = y_new0(struct yahoo_webcam, 1); - yid->wcm->user = who ? strdup(who) : NULL; - yid->wcm->direction = who ? YAHOO_WEBCAM_DOWNLOAD : YAHOO_WEBCAM_UPLOAD; - yid->wcm->key = strdup(key); - - YAHOO_CALLBACK (ext_yahoo_connect_async) (yid->yd->client_id, - yss->webcam_host, yss->webcam_port, - _yahoo_webcam_get_server_connected, yid, 0); - -} - -static YList *webcam_queue = NULL; -static void yahoo_process_webcam_key(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) -{ - char *key = NULL; - char *who = NULL; - - YList *l; - - yahoo_dump_unhandled(pkt); - for (l = pkt->hash; l; l = l->next) { - struct yahoo_pair *pair = l->data; - if (pair->key == 5) { - ; /* me */ - } - if (pair->key == 61) { - key = pair->value; - } - } - - l = webcam_queue; - if (!l) { - return; - } - who = l->data; - webcam_queue = y_list_remove_link(webcam_queue, webcam_queue); - y_list_free_1(l); - yahoo_webcam_get_server(yid, who, key); - FREE(who); -} - -static void yahoo_packet_process(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) -{ - DEBUG_MSG(("yahoo_packet_process: 0x%02x", pkt->service)); - switch (pkt->service) { - case YAHOO_SERVICE_USERSTAT: - case YAHOO_SERVICE_LOGON: - case YAHOO_SERVICE_LOGOFF: - case YAHOO_SERVICE_ISAWAY: - case YAHOO_SERVICE_ISBACK: - case YAHOO_SERVICE_GAMELOGON: - case YAHOO_SERVICE_GAMELOGOFF: - case YAHOO_SERVICE_IDACT: - case YAHOO_SERVICE_IDDEACT: - case YAHOO_SERVICE_Y6_STATUS_UPDATE: - case YAHOO_SERVICE_Y8_STATUS: - yahoo_process_status(yid, pkt); - break; - case YAHOO_SERVICE_NOTIFY: - yahoo_process_notify(yid, pkt); - break; - case YAHOO_SERVICE_MESSAGE: - case YAHOO_SERVICE_GAMEMSG: - case YAHOO_SERVICE_SYSMESSAGE: - yahoo_process_message(yid, pkt); - break; - case YAHOO_SERVICE_NEWMAIL: - yahoo_process_mail(yid, pkt); - break; - case YAHOO_SERVICE_Y7_AUTHORIZATION: - yahoo_process_new_contact(yid, pkt); - break; - case YAHOO_SERVICE_NEWCONTACT: - yahoo_process_contact(yid, pkt); - break; - case YAHOO_SERVICE_LIST: - yahoo_process_list(yid, pkt); - break; - case YAHOO_SERVICE_VERIFY: - yahoo_process_verify(yid, pkt); - break; - case YAHOO_SERVICE_AUTH: - yahoo_process_auth(yid, pkt); - break; - case YAHOO_SERVICE_AUTHRESP: - yahoo_process_auth_resp(yid, pkt); - break; - case YAHOO_SERVICE_CONFINVITE: - case YAHOO_SERVICE_CONFADDINVITE: - case YAHOO_SERVICE_CONFDECLINE: - case YAHOO_SERVICE_CONFLOGON: - case YAHOO_SERVICE_CONFLOGOFF: - case YAHOO_SERVICE_CONFMSG: - yahoo_process_conference(yid, pkt); - break; - case YAHOO_SERVICE_CHATONLINE: - case YAHOO_SERVICE_CHATGOTO: - case YAHOO_SERVICE_CHATJOIN: - case YAHOO_SERVICE_CHATLEAVE: - case YAHOO_SERVICE_CHATEXIT: - case YAHOO_SERVICE_CHATLOGOUT: - case YAHOO_SERVICE_CHATPING: - case YAHOO_SERVICE_COMMENT: - yahoo_process_chat(yid, pkt); - break; - case YAHOO_SERVICE_P2PFILEXFER: - case YAHOO_SERVICE_Y7_FILETRANSFER: - yahoo_process_filetransfer(yid, pkt); - break; - case YAHOO_SERVICE_Y7_FILETRANSFERINFO: - yahoo_process_filetransferinfo(yid, pkt); - break; - case YAHOO_SERVICE_Y7_FILETRANSFERACCEPT: - yahoo_process_filetransferaccept(yid, pkt); - break; - case YAHOO_SERVICE_ADDBUDDY: - yahoo_process_buddyadd(yid, pkt); - break; - case YAHOO_SERVICE_REMBUDDY: - yahoo_process_buddydel(yid, pkt); - break; - case YAHOO_SERVICE_IGNORECONTACT: - yahoo_process_ignore(yid, pkt); - break; - case YAHOO_SERVICE_VOICECHAT: - yahoo_process_voicechat(yid, pkt); - break; - case YAHOO_SERVICE_WEBCAM: - yahoo_process_webcam_key(yid, pkt); - break; - case YAHOO_SERVICE_PING: - yahoo_process_ping(yid, pkt); - break; - case YAHOO_SERVICE_Y7_CHANGE_GROUP: - yahoo_process_buddy_change_group(yid, pkt); - break; - case YAHOO_SERVICE_IDLE: - case YAHOO_SERVICE_MAILSTAT: - case YAHOO_SERVICE_CHATINVITE: - case YAHOO_SERVICE_CALENDAR: - case YAHOO_SERVICE_NEWPERSONALMAIL: - case YAHOO_SERVICE_ADDIDENT: - case YAHOO_SERVICE_ADDIGNORE: - case YAHOO_SERVICE_GOTGROUPRENAME: - case YAHOO_SERVICE_GROUPRENAME: - case YAHOO_SERVICE_PASSTHROUGH2: - case YAHOO_SERVICE_CHATLOGON: - case YAHOO_SERVICE_CHATLOGOFF: - case YAHOO_SERVICE_CHATMSG: - case YAHOO_SERVICE_REJECTCONTACT: - case YAHOO_SERVICE_PEERTOPEER: - WARNING(("unhandled service 0x%02x", pkt->service)); - yahoo_dump_unhandled(pkt); - break; - case YAHOO_SERVICE_PICTURE: - yahoo_process_picture(yid, pkt); - break; - case YAHOO_SERVICE_PICTURE_CHECKSUM: - yahoo_process_picture_checksum(yid, pkt); - break; - case YAHOO_SERVICE_PICTURE_UPLOAD: - yahoo_process_picture_upload(yid, pkt); - break; - case YAHOO_SERVICE_Y8_LIST: /* Buddy List */ - yahoo_process_buddy_list(yid, pkt); - break; - default: - WARNING(("unknown service 0x%02x", pkt->service)); - yahoo_dump_unhandled(pkt); - break; - } -} - -static struct yahoo_packet *yahoo_getdata(struct yahoo_input_data *yid) -{ - struct yahoo_packet *pkt; - struct yahoo_data *yd = yid->yd; - int pos = 0; - int pktlen; - - if (!yd) { - return NULL; - } - - DEBUG_MSG(("rxlen is %d", yid->rxlen)); - if (yid->rxlen < YAHOO_PACKET_HDRLEN) { - DEBUG_MSG(("len < YAHOO_PACKET_HDRLEN")); - return NULL; - } - - pos += 4; /* YMSG */ - pos += 2; - pos += 2; - - pktlen = yahoo_get16(yid->rxqueue + pos); - pos += 2; - DEBUG_MSG(("%d bytes to read, rxlen is %d", pktlen, yid->rxlen)); - - if (yid->rxlen < (YAHOO_PACKET_HDRLEN + pktlen)) { - DEBUG_MSG(("len < YAHOO_PACKET_HDRLEN + pktlen")); - return NULL; - } - - LOG(("reading packet")); - yahoo_packet_dump(yid->rxqueue, YAHOO_PACKET_HDRLEN + pktlen); - - pkt = yahoo_packet_new(0, 0, 0); - - pkt->service = yahoo_get16(yid->rxqueue + pos); - pos += 2; - pkt->status = yahoo_get32(yid->rxqueue + pos); - pos += 4; - DEBUG_MSG(("Yahoo Service: 0x%02x Status: %d", pkt->service, - pkt->status)); - pkt->id = yahoo_get32(yid->rxqueue + pos); - pos += 4; - - yd->session_id = pkt->id; - - yahoo_packet_read(pkt, yid->rxqueue + pos, pktlen); - - yid->rxlen -= YAHOO_PACKET_HDRLEN + pktlen; - DEBUG_MSG(("rxlen == %d, rxqueue == %p", yid->rxlen, yid->rxqueue)); - if (yid->rxlen > 0) { - unsigned char *tmp = y_memdup(yid->rxqueue + YAHOO_PACKET_HDRLEN - + pktlen, yid->rxlen); - FREE(yid->rxqueue); - yid->rxqueue = tmp; - DEBUG_MSG(("new rxlen == %d, rxqueue == %p", yid->rxlen, - yid->rxqueue)); - } else { - DEBUG_MSG(("freed rxqueue == %p", yid->rxqueue)); - FREE(yid->rxqueue); - } - - return pkt; -} - -#if 0 -static struct yab *yahoo_yab_read(unsigned char *d, int len) -{ - char *st, *en; - char *data = (char *) d; - struct yab *yab = NULL; - - data[len] = '\0'; - - DEBUG_MSG(("Got yab: %s", data)); - st = en = strstr(data, "e0=\""); - if (st) { - yab = y_new0(struct yab, 1); - - st += strlen("e0=\""); - en = strchr(st, '"'); - *en++ = '\0'; - yab->email = yahoo_xmldecode(st); - } - - if (!en) { - return NULL; - } - - st = strstr(en, "id=\""); - if (st) { - st += strlen("id=\""); - en = strchr(st, '"'); - *en++ = '\0'; - yab->yid = atoi(yahoo_xmldecode(st)); - } - - st = strstr(en, "fn=\""); - if (st) { - st += strlen("fn=\""); - en = strchr(st, '"'); - *en++ = '\0'; - yab->fname = yahoo_xmldecode(st); - } - - st = strstr(en, "ln=\""); - if (st) { - st += strlen("ln=\""); - en = strchr(st, '"'); - *en++ = '\0'; - yab->lname = yahoo_xmldecode(st); - } - - st = strstr(en, "nn=\""); - if (st) { - st += strlen("nn=\""); - en = strchr(st, '"'); - *en++ = '\0'; - yab->nname = yahoo_xmldecode(st); - } - - st = strstr(en, "yi=\""); - if (st) { - st += strlen("yi=\""); - en = strchr(st, '"'); - *en++ = '\0'; - yab->id = yahoo_xmldecode(st); - } - - st = strstr(en, "hphone=\""); - if (st) { - st += strlen("hphone=\""); - en = strchr(st, '"'); - *en++ = '\0'; - yab->hphone = yahoo_xmldecode(st); - } - - st = strstr(en, "wphone=\""); - if (st) { - st += strlen("wphone=\""); - en = strchr(st, '"'); - *en++ = '\0'; - yab->wphone = yahoo_xmldecode(st); - } - - st = strstr(en, "mphone=\""); - if (st) { - st += strlen("mphone=\""); - en = strchr(st, '"'); - *en++ = '\0'; - yab->mphone = yahoo_xmldecode(st); - } - - st = strstr(en, "dbid=\""); - if (st) { - st += strlen("dbid=\""); - en = strchr(st, '"'); - *en++ = '\0'; - yab->dbid = atoi(st); - } - - return yab; -} - -static struct yab *yahoo_getyab(struct yahoo_input_data *yid) -{ - struct yab *yab = NULL; - int pos = 0, end = 0; - struct yahoo_data *yd = yid->yd; - - if (!yd) { - return NULL; - } - - do { - DEBUG_MSG(("rxlen is %d", yid->rxlen)); - - if (yid->rxlen <= strlen("<ct")) { - return NULL; - } - - /* start with <ct */ - while (pos < yid->rxlen - strlen("<ct") + 1 - && memcmp(yid->rxqueue + pos, "<ct", strlen("<ct"))) { - pos++; - } - - if (pos >= yid->rxlen - 1) { - return NULL; - } - - end = pos + 2; - /* end with > */ - while (end < yid->rxlen - strlen(">") - && memcmp(yid->rxqueue + end, ">", strlen(">"))) { - end++; - } - - if (end >= yid->rxlen - 1) { - return NULL; - } - - yab = yahoo_yab_read(yid->rxqueue + pos, end + 2 - pos); - - yid->rxlen -= end + 1; - DEBUG_MSG(("rxlen == %d, rxqueue == %p", yid->rxlen, - yid->rxqueue)); - if (yid->rxlen > 0) { - unsigned char *tmp = - y_memdup(yid->rxqueue + end + 1, yid->rxlen); - FREE(yid->rxqueue); - yid->rxqueue = tmp; - DEBUG_MSG(("new rxlen == %d, rxqueue == %p", yid->rxlen, - yid->rxqueue)); - } else { - DEBUG_MSG(("freed rxqueue == %p", yid->rxqueue)); - FREE(yid->rxqueue); - } - - } while (!yab && end < yid->rxlen - 1); - - return yab; -} -#endif - -static char *yahoo_getwebcam_master(struct yahoo_input_data *yid) -{ - unsigned int pos = 0; - unsigned int len = 0; - unsigned int status = 0; - char *server = NULL; - struct yahoo_data *yd = yid->yd; - - if (!yid || !yd) { - return NULL; - } - - DEBUG_MSG(("rxlen is %d", yid->rxlen)); - - len = yid->rxqueue[pos++]; - if (yid->rxlen < len) { - return NULL; - } - - /* extract status (0 = ok, 6 = webcam not online) */ - status = yid->rxqueue[pos++]; - - if (status == 0) { - pos += 2; /* skip next 2 bytes */ - server = y_memdup(yid->rxqueue + pos, 16); - pos += 16; - } else if (status == 6) { - YAHOO_CALLBACK (ext_yahoo_webcam_closed) - (yd->client_id, yid->wcm->user, 4); - } - - /* skip rest of the data */ - - yid->rxlen -= len; - DEBUG_MSG(("rxlen == %d, rxqueue == %p", yid->rxlen, yid->rxqueue)); - if (yid->rxlen > 0) { - unsigned char *tmp = y_memdup(yid->rxqueue + pos, yid->rxlen); - FREE(yid->rxqueue); - yid->rxqueue = tmp; - DEBUG_MSG(("new rxlen == %d, rxqueue == %p", yid->rxlen, - yid->rxqueue)); - } else { - DEBUG_MSG(("freed rxqueue == %p", yid->rxqueue)); - FREE(yid->rxqueue); - } - - return server; -} - -static int yahoo_get_webcam_data(struct yahoo_input_data *yid) -{ - unsigned char reason = 0; - unsigned int pos = 0; - unsigned int begin = 0; - unsigned int end = 0; - unsigned int closed = 0; - unsigned char header_len = 0; - char *who; - int connect = 0; - struct yahoo_data *yd = yid->yd; - - if (!yd) { - return -1; - } - - if (!yid->wcm || !yid->wcd || !yid->rxlen) { - return -1; - } - - DEBUG_MSG(("rxlen is %d", yid->rxlen)); - - /* if we are not reading part of image then read header */ - if (!yid->wcd->to_read) { - header_len = yid->rxqueue[pos++]; - yid->wcd->packet_type = 0; - - if (yid->rxlen < header_len) { - return 0; - } - - if (header_len >= 8) { - reason = yid->rxqueue[pos++]; - /* next 2 bytes should always be 05 00 */ - pos += 2; - yid->wcd->data_size = yahoo_get32(yid->rxqueue + pos); - pos += 4; - yid->wcd->to_read = yid->wcd->data_size; - } - if (header_len >= 13) { - yid->wcd->packet_type = yid->rxqueue[pos++]; - yid->wcd->timestamp = yahoo_get32(yid->rxqueue + pos); - pos += 4; - } - - /* skip rest of header */ - pos = header_len; - } - - begin = pos; - pos += yid->wcd->to_read; - if (pos > yid->rxlen) { - pos = yid->rxlen; - } - - /* if it is not an image then make sure we have the whole packet */ - if (yid->wcd->packet_type != 0x02) { - if ((pos - begin) != yid->wcd->data_size) { - yid->wcd->to_read = 0; - return 0; - } else { - yahoo_packet_dump(yid->rxqueue + begin, pos - begin); - } - } - - DEBUG_MSG(("packet type %.2X, data length %d", yid->wcd->packet_type, - yid->wcd->data_size)); - - /* find out what kind of packet we got */ - switch (yid->wcd->packet_type) { - case 0x00: - /* user requests to view webcam (uploading) */ - if (yid->wcd->data_size && - yid->wcm->direction == YAHOO_WEBCAM_UPLOAD) { - end = begin; - while (end <= yid->rxlen && yid->rxqueue[end++] != 13) { - ; - } - if (end > begin) { - who = y_memdup(yid->rxqueue + begin, - end - begin); - who[end - begin - 1] = 0; - YAHOO_CALLBACK (ext_yahoo_webcam_viewer) (yd-> - client_id, who + 2, 2); - FREE(who); - } - } - - if (yid->wcm->direction == YAHOO_WEBCAM_DOWNLOAD) { - /* timestamp/status field */ - /* 0 = declined viewing permission */ - /* 1 = accepted viewing permission */ - if (yid->wcd->timestamp == 0) { - YAHOO_CALLBACK (ext_yahoo_webcam_closed) (yd-> - client_id, yid->wcm->user, 3); - } - } - break; - case 0x01: /* status packets?? */ - /* timestamp contains status info */ - /* 00 00 00 01 = we have data?? */ - break; - case 0x02: /* image data */ - YAHOO_CALLBACK (ext_yahoo_got_webcam_image) (yd->client_id, - yid->wcm->user, yid->rxqueue + begin, - yid->wcd->data_size, pos - begin, yid->wcd->timestamp); - break; - case 0x05: /* response packets when uploading */ - if (!yid->wcd->data_size) { - YAHOO_CALLBACK (ext_yahoo_webcam_data_request) (yd-> - client_id, yid->wcd->timestamp); - } - break; - case 0x07: /* connection is closing */ - switch (reason) { - case 0x01: /* user closed connection */ - closed = 1; - break; - case 0x0F: /* user cancelled permission */ - closed = 2; - break; - } - YAHOO_CALLBACK (ext_yahoo_webcam_closed) (yd->client_id, - yid->wcm->user, closed); - break; - case 0x0C: /* user connected */ - case 0x0D: /* user disconnected */ - if (yid->wcd->data_size) { - who = y_memdup(yid->rxqueue + begin, pos - begin + 1); - who[pos - begin] = 0; - if (yid->wcd->packet_type == 0x0C) { - connect = 1; - } else { - connect = 0; - } - YAHOO_CALLBACK (ext_yahoo_webcam_viewer) (yd->client_id, - who, connect); - FREE(who); - } - break; - case 0x13: /* user data */ - /* i=user_ip (ip of the user we are viewing) */ - /* j=user_ext_ip (external ip of the user we */ - /* are viewing) */ - break; - case 0x17: /* ?? */ - break; - } - yid->wcd->to_read -= pos - begin; - - yid->rxlen -= pos; - DEBUG_MSG(("rxlen == %d, rxqueue == %p", yid->rxlen, yid->rxqueue)); - if (yid->rxlen > 0) { - unsigned char *tmp = y_memdup(yid->rxqueue + pos, yid->rxlen); - FREE(yid->rxqueue); - yid->rxqueue = tmp; - DEBUG_MSG(("new rxlen == %d, rxqueue == %p", yid->rxlen, - yid->rxqueue)); - } else { - DEBUG_MSG(("freed rxqueue == %p", yid->rxqueue)); - FREE(yid->rxqueue); - } - - /* If we read a complete packet return success */ - if (!yid->wcd->to_read) { - return 1; - } - - return 0; -} - -int yahoo_write_ready(int id, void *fd, void *data) -{ - struct yahoo_input_data *yid = data; - int len; - struct data_queue *tx; - - LOG(("write callback: id=%d fd=%p data=%p", id, fd, data)); - if (!yid || !yid->txqueues) { - return -2; - } - - tx = yid->txqueues->data; - LOG(("writing %d bytes", tx->len)); - len = yahoo_send_data(fd, tx->queue, MIN(1024, tx->len)); - - if (len == -1 && errno == EAGAIN) { - return 1; - } - - if (len <= 0) { - int e = errno; - DEBUG_MSG(("len == %d (<= 0)", len)); - while (yid->txqueues) { - YList *l = yid->txqueues; - tx = l->data; - free(tx->queue); - free(tx); - yid->txqueues = - y_list_remove_link(yid->txqueues, - yid->txqueues); - y_list_free_1(l); - } - LOG(("yahoo_write_ready(%d, %p) len < 0", id, fd)); - YAHOO_CALLBACK (ext_yahoo_remove_handler) (id, yid->write_tag); - yid->write_tag = 0; - errno = e; - return 0; - } - - - tx->len -= len; - if (tx->len > 0) { - unsigned char *tmp = y_memdup(tx->queue + len, tx->len); - FREE(tx->queue); - tx->queue = tmp; - } else { - YList *l = yid->txqueues; - free(tx->queue); - free(tx); - yid->txqueues = - y_list_remove_link(yid->txqueues, yid->txqueues); - y_list_free_1(l); - /* - if(!yid->txqueues) - LOG(("yahoo_write_ready(%d, %d) !yxqueues", id, fd)); - */ - if (!yid->txqueues) { - LOG(("yahoo_write_ready(%d, %p) !txqueues", id, fd)); - YAHOO_CALLBACK (ext_yahoo_remove_handler) (id, - yid->write_tag); - yid->write_tag = 0; - } - } - - return 1; -} - -static void yahoo_process_pager_connection(struct yahoo_input_data *yid, - int over) -{ - struct yahoo_packet *pkt; - struct yahoo_data *yd = yid->yd; - int id = yd->client_id; - - if (over) { - return; - } - - while (find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER) - && (pkt = yahoo_getdata(yid)) != NULL) { - - yahoo_packet_process(yid, pkt); - - yahoo_packet_free(pkt); - } -} - -static void yahoo_process_chatcat_connection(struct yahoo_input_data *yid, - int over) -{ - if (over) { - return; - } - - if (strstr((char *) yid->rxqueue + (yid->rxlen - 20), "</content>")) { - YAHOO_CALLBACK (ext_yahoo_chat_cat_xml) (yid->yd->client_id, - (char *) yid->rxqueue); - } -} - -#if 0 -static void yahoo_process_yab_connection(struct yahoo_input_data *yid, int over) -{ - struct yahoo_data *yd = yid->yd; - struct yab *yab; - YList *buds; - int changed = 0; - int id = yd->client_id; - int yab_used = 0; - - LOG(("Got data for YAB")); - - if (over) { - return; - } - - while (find_input_by_id_and_type(id, YAHOO_CONNECTION_YAB) - && (yab = yahoo_getyab(yid)) != NULL) { - if (!yab->id) { - continue; - } - - changed = 1; - yab_used = 0; - for (buds = yd->buddies; buds; buds = buds->next) { - struct yahoo_buddy *bud = buds->data; - if (!strcmp(bud->id, yab->id)) { - yab_used = 1; - bud->yab_entry = yab; - if (yab->nname) { - bud->real_name = strdup(yab->nname); - } else if (yab->fname && yab->lname) { - bud->real_name = y_new0(char, - strlen(yab->fname) + - strlen(yab->lname) + 2); - sprintf(bud->real_name, "%s %s", - yab->fname, yab->lname); - } else if (yab->fname) { - bud->real_name = strdup(yab->fname); - } - break; /* for */ - } - } - - if (!yab_used) { - FREE(yab->fname); - FREE(yab->lname); - FREE(yab->nname); - FREE(yab->id); - FREE(yab->email); - FREE(yab->hphone); - FREE(yab->wphone); - FREE(yab->mphone); - FREE(yab); - } - - } - - if (changed) { - YAHOO_CALLBACK (ext_yahoo_got_buddies) (yd->client_id, - yd->buddies); - } -} -#endif - -static void yahoo_process_search_connection(struct yahoo_input_data *yid, - int over) -{ - struct yahoo_found_contact *yct = NULL; - char *p = (char *) yid->rxqueue, *np, *cp; - int k, n; - int start = 0, found = 0, total = 0; - YList *contacts = NULL; - struct yahoo_input_data *pyid = - find_input_by_id_and_type(yid->yd->client_id, - YAHOO_CONNECTION_PAGER); - - if (!over || !pyid) { - return; - } - - if (p && (p = strstr(p, "\r\n\r\n"))) { - p += 4; - - for (k = 0; (p = strchr(p, 4)) && (k < 4); k++) { - p++; - n = atoi(p); - switch (k) { - case 0: - found = pyid->ys->lsearch_nfound = n; - break; - case 2: - start = pyid->ys->lsearch_nstart = n; - break; - case 3: - total = pyid->ys->lsearch_ntotal = n; - break; - } - } - - if (p) { - p++; - } - - k = 0; - while (p && *p) { - cp = p; - np = strchr(p, 4); - - if (!np) { - break; - } - *np = 0; - p = np + 1; - - switch (k++) { - case 1: - if (strlen(cp) > 2 - && y_list_length(contacts) < total) { - yct = y_new0(struct yahoo_found_contact, - 1); - contacts = y_list_append(contacts, yct); - yct->id = cp + 2; - } else { - *p = 0; - } - break; - case 2: - yct->online = !strcmp(cp, "2") ? 1 : 0; - break; - case 3: - yct->gender = cp; - break; - case 4: - yct->age = atoi(cp); - break; - case 5: - /* not worth the context switch for strcmp */ - if (cp[0] != '\005' || cp[1] != '\000') { - yct->location = cp; - } - k = 0; - break; - } - } - } - - YAHOO_CALLBACK (ext_yahoo_got_search_result) (yid->yd->client_id, found, - start, total, contacts); - - while (contacts) { - YList *node = contacts; - contacts = y_list_remove_link(contacts, node); - free(node->data); - y_list_free_1(node); - } -} - -static void _yahoo_webcam_connected(void *fd, int error, void *d) -{ - struct yahoo_input_data *yid = d; - struct yahoo_webcam *wcm = yid->wcm; - struct yahoo_data *yd = yid->yd; - char conn_type[100]; - char *data = NULL; - char *packet = NULL; - unsigned char magic_nr[] = { 1, 0, 0, 0, 1 }; - unsigned header_len = 0; - unsigned int len = 0; - unsigned int pos = 0; - - if (error || !fd) { - FREE(yid); - return; - } - - yid->fd = fd; - inputs = y_list_prepend(inputs, yid); - - LOG(("Connected")); - /* send initial packet */ - switch (wcm->direction) { - case YAHOO_WEBCAM_DOWNLOAD: - data = strdup("<REQIMG>"); - break; - case YAHOO_WEBCAM_UPLOAD: - data = strdup("<SNDIMG>"); - break; - default: - return; - } - yahoo_add_to_send_queue(yid, data, strlen(data)); - FREE(data); - - /* send data */ - switch (wcm->direction) { - case YAHOO_WEBCAM_DOWNLOAD: - header_len = 8; - data = strdup("a=2\r\nc=us\r\ne=21\r\nu="); - data = y_string_append(data, yd->user); - data = y_string_append(data, "\r\nt="); - data = y_string_append(data, wcm->key); - data = y_string_append(data, "\r\ni="); - data = y_string_append(data, wcm->my_ip); - data = y_string_append(data, "\r\ng="); - data = y_string_append(data, wcm->user); - data = y_string_append(data, "\r\no=w-2-5-1\r\np="); - snprintf(conn_type, sizeof(conn_type), "%d", wcm->conn_type); - data = y_string_append(data, conn_type); - data = y_string_append(data, "\r\n"); - break; - case YAHOO_WEBCAM_UPLOAD: - header_len = 13; - data = strdup("a=2\r\nc=us\r\nu="); - data = y_string_append(data, yd->user); - data = y_string_append(data, "\r\nt="); - data = y_string_append(data, wcm->key); - data = y_string_append(data, "\r\ni="); - data = y_string_append(data, wcm->my_ip); - data = y_string_append(data, "\r\no=w-2-5-1\r\np="); - snprintf(conn_type, sizeof(conn_type), "%d", wcm->conn_type); - data = y_string_append(data, conn_type); - data = y_string_append(data, "\r\nb="); - data = y_string_append(data, wcm->description); - data = y_string_append(data, "\r\n"); - break; - } - - len = strlen(data); - packet = y_new0(char, header_len + len); - packet[pos++] = header_len; - packet[pos++] = 0; - switch (wcm->direction) { - case YAHOO_WEBCAM_DOWNLOAD: - packet[pos++] = 1; - packet[pos++] = 0; - break; - case YAHOO_WEBCAM_UPLOAD: - packet[pos++] = 5; - packet[pos++] = 0; - break; - } - - pos += yahoo_put32(packet + pos, len); - if (wcm->direction == YAHOO_WEBCAM_UPLOAD) { - memcpy(packet + pos, magic_nr, sizeof(magic_nr)); - pos += sizeof(magic_nr); - } - memcpy(packet + pos, data, len); - yahoo_add_to_send_queue(yid, packet, header_len + len); - FREE(packet); - FREE(data); - - yid->read_tag = - YAHOO_CALLBACK (ext_yahoo_add_handler) (yid->yd->client_id, - yid->fd, YAHOO_INPUT_READ, yid); -} - -static void yahoo_webcam_connect(struct yahoo_input_data *y) -{ - struct yahoo_webcam *wcm = y->wcm; - struct yahoo_input_data *yid; - - if (!wcm || !wcm->server || !wcm->key) { - return; - } - - yid = y_new0(struct yahoo_input_data, 1); - yid->type = YAHOO_CONNECTION_WEBCAM; - yid->yd = y->yd; - - /* copy webcam data to new connection */ - yid->wcm = y->wcm; - y->wcm = NULL; - - yid->wcd = y_new0(struct yahoo_webcam_data, 1); - - LOG(("Connecting to: %s:%d", wcm->server, wcm->port)); - YAHOO_CALLBACK (ext_yahoo_connect_async) (y->yd->client_id, wcm->server, - wcm->port, _yahoo_webcam_connected, yid, 0); - -} - -static void yahoo_process_webcam_master_connection(struct yahoo_input_data *yid, - int over) -{ - char *server; - struct yahoo_server_settings *yss; - - if (over) { - return; - } - - server = yahoo_getwebcam_master(yid); - - if (server) { - yss = yid->yd->server_settings; - yid->wcm->server = strdup(server); - yid->wcm->port = yss->webcam_port; - yid->wcm->conn_type = yss->conn_type; - yid->wcm->my_ip = strdup(yss->local_host); - if (yid->wcm->direction == YAHOO_WEBCAM_UPLOAD) { - yid->wcm->description = strdup(yss->webcam_description); - } - yahoo_webcam_connect(yid); - FREE(server); - } -} - -static void yahoo_process_webcam_connection(struct yahoo_input_data *yid, - int over) -{ - int id = yid->yd->client_id; - void *fd = yid->fd; - - if (over) { - return; - } - - /* as long as we still have packets available keep processing them */ - while (find_input_by_id_and_fd(id, fd) - && yahoo_get_webcam_data(yid) == 1) { - ; - } -} - -static void(*yahoo_process_connection[]) (struct yahoo_input_data *, - int over) = { - yahoo_process_pager_connection, yahoo_process_ft_connection, - NULL, /*yahoo_process_yab_connection, */ - yahoo_process_webcam_master_connection, - yahoo_process_webcam_connection, - yahoo_process_chatcat_connection, - yahoo_process_search_connection -}; - -int yahoo_read_ready(int id, void *fd, void *data) -{ - struct yahoo_input_data *yid = data; - char buf[1024]; - int len; - - LOG(("read callback: id=%d fd=%p data=%p", id, fd, data)); - if (!yid) { - return -2; - } - - do { - len = YAHOO_CALLBACK (ext_yahoo_read) (fd, buf, sizeof(buf)); - } while (len == -1 && errno == EINTR); - - if (len == -1 && (errno == EAGAIN || errno == EINTR)) { /* we'll try again later */ - return 1; - } - - if (len <= 0) { - int e = errno; - DEBUG_MSG(("len == %d (<= 0)", len)); - - if (yid->type == YAHOO_CONNECTION_PAGER) { - YAHOO_CALLBACK (ext_yahoo_login_response) (yid->yd-> - client_id, YAHOO_LOGIN_SOCK, NULL); - } - - yahoo_process_connection[yid->type] (yid, 1); - yahoo_input_close(yid); - - /* no need to return an error, because we've already fixed it */ - if (len == 0) { - return 1; - } - - errno = e; - LOG(("read error: %s", strerror(errno))); - return -1; - } - - yid->rxqueue = - y_renew(unsigned char, yid->rxqueue, len + yid->rxlen + 1); - memcpy(yid->rxqueue + yid->rxlen, buf, len); - yid->rxlen += len; - yid->rxqueue[yid->rxlen] = 0; - - yahoo_process_connection[yid->type] (yid, 0); - - return len; -} - -int yahoo_init_with_attributes(const char *username, const char *password, ...) -{ - va_list ap; - struct yahoo_data *yd; - - yd = y_new0(struct yahoo_data, 1); - - if (!yd) { - return 0; - } - - yd->user = strdup(username); - yd->password = strdup(password); - - yd->initial_status = -1; - yd->current_status = -1; - - yd->client_id = ++last_id; - - add_to_list(yd); - - va_start(ap, password); - yd->server_settings = _yahoo_assign_server_settings(ap); - va_end(ap); - - return yd->client_id; -} - -int yahoo_init(const char *username, const char *password) -{ - return yahoo_init_with_attributes(username, password, NULL); -} - -static void yahoo_connected(void *fd, int error, void *data) -{ - struct connect_callback_data *ccd = data; - struct yahoo_data *yd = ccd->yd; - struct yahoo_packet *pkt; - struct yahoo_input_data *yid; - struct yahoo_server_settings *yss = yd->server_settings; - - if (error) { - int tag; - if (fallback_ports[ccd->i]) { - char *host = yss->pager_host; - - if (!host) { - host = yss->pager_host_list[ccd->server_i]; - } - - yss->pager_port = fallback_ports[ccd->i++]; - tag = YAHOO_CALLBACK (ext_yahoo_connect_async) (yd-> - client_id, host, yss->pager_port, - yahoo_connected, ccd, 0); - - if (tag > 0) { - ccd->tag = tag; - } - } else if (yss->pager_host_list - && yss->pager_host_list[ccd->server_i]) { - - /* Get back to the default port */ - yss->pager_port = pager_port; - ccd->server_i++; - LOG(("Fallback: Connecting to %s:%d", yss->pager_host_list[ccd->server_i], yss->pager_port)); - - ccd->i = 0; - tag = YAHOO_CALLBACK (ext_yahoo_connect_async) (yd->client_id, - yss->pager_host_list[ccd->server_i], - yss->pager_port, - yahoo_connected, ccd, 0); - } else { - FREE(ccd); - YAHOO_CALLBACK (ext_yahoo_login_response) (yd->client_id, - YAHOO_LOGIN_SOCK, NULL); - } - return; - } - - FREE(ccd); - - /* fd == NULL && error == 0 means connect was cancelled */ - if (!fd) { - return; - } - - pkt = yahoo_packet_new(YAHOO_SERVICE_AUTH, YPACKET_STATUS_DEFAULT, - yd->session_id); - NOTICE(("Sending initial packet")); - - yahoo_packet_hash(pkt, 1, yd->user); - - yid = find_input_by_id_and_type(yd->client_id, YAHOO_CONNECTION_PAGER); - yid->fd = fd; - - yahoo_send_packet(yid, pkt, 0); - - yahoo_packet_free(pkt); - - yid->read_tag = - YAHOO_CALLBACK (ext_yahoo_add_handler) (yid->yd->client_id, - yid->fd, YAHOO_INPUT_READ, yid); -} - -void *yahoo_get_fd(int id) -{ - struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); - - if (!yid) { - return 0; - } else { - return yid->fd; - } -} - -#if 0 -void yahoo_send_buzz(int id, const char *from, const char *who) -{ - yahoo_send_im(id, from, who, "<ding>", 1, 0); -} -#endif - -void yahoo_send_im(int id, const char *from, const char *who, const char *what, - int utf8, int picture) -{ - struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); - struct yahoo_packet *pkt = NULL; - struct yahoo_data *yd; - char pic_str[10]; - - if (!yid) { - return; - } - - yd = yid->yd; - - pkt = yahoo_packet_new(YAHOO_SERVICE_MESSAGE, (enum ypacket_status) YAHOO_STATUS_OFFLINE, - yd->session_id); - - snprintf(pic_str, sizeof(pic_str), "%d", picture); - - if (from && strcmp(from, yd->user)) { - yahoo_packet_hash(pkt, 0, yd->user); - } - yahoo_packet_hash(pkt, 1, from ? from : yd->user); - yahoo_packet_hash(pkt, 5, who); - yahoo_packet_hash(pkt, 14, what); - - if (utf8) { - yahoo_packet_hash(pkt, 97, "1"); - } - - yahoo_packet_hash(pkt, 63, ";0"); /* imvironment name; or ;0 */ - yahoo_packet_hash(pkt, 64, "0"); - yahoo_packet_hash(pkt, 206, pic_str); - - yahoo_send_packet(yid, pkt, 0); - - yahoo_packet_free(pkt); -} - -void yahoo_send_typing(int id, const char *from, const char *who, int typ) -{ - struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); - struct yahoo_data *yd; - struct yahoo_packet *pkt = NULL; - - if (!yid) { - return; - } - - yd = yid->yd; - pkt = yahoo_packet_new(YAHOO_SERVICE_NOTIFY, YPACKET_STATUS_NOTIFY, - yd->session_id); - - yahoo_packet_hash(pkt, 5, who); - yahoo_packet_hash(pkt, 1, from ? from : yd->user); - yahoo_packet_hash(pkt, 14, " "); - yahoo_packet_hash(pkt, 13, typ ? "1" : "0"); - yahoo_packet_hash(pkt, 49, "TYPING"); - - yahoo_send_packet(yid, pkt, 0); - - yahoo_packet_free(pkt); -} - -void yahoo_set_away(int id, enum yahoo_status state, const char *msg, int away) -{ - struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); - struct yahoo_data *yd; - struct yahoo_packet *pkt = NULL; - int old_status; - char s[4]; - - if (!yid) { - return; - } - - yd = yid->yd; - - old_status = yd->current_status; - yd->current_status = state; - - /* Thank you libpurple :) */ - if (yd->current_status == YAHOO_STATUS_INVISIBLE) { - pkt = yahoo_packet_new(YAHOO_SERVICE_Y6_VISIBLE_TOGGLE, - (enum ypacket_status) YAHOO_STATUS_AVAILABLE, 0); - yahoo_packet_hash(pkt, 13, "2"); - yahoo_send_packet(yid, pkt, 0); - yahoo_packet_free(pkt); - - return; - } - - pkt = yahoo_packet_new(YAHOO_SERVICE_Y6_STATUS_UPDATE, - yd->current_status, yd->session_id); - snprintf(s, sizeof(s), "%d", yd->current_status); - yahoo_packet_hash(pkt, 10, s); - yahoo_packet_hash(pkt, 19, msg && state == YAHOO_STATUS_CUSTOM ? msg : ""); - yahoo_packet_hash(pkt, 47, (away == 2) ? "2" : (away) ? "1" : "0"); - yahoo_send_packet(yid, pkt, 0); - yahoo_packet_free(pkt); - - if (old_status == YAHOO_STATUS_INVISIBLE) { - pkt = yahoo_packet_new(YAHOO_SERVICE_Y6_VISIBLE_TOGGLE, - (enum ypacket_status) YAHOO_STATUS_AVAILABLE, 0); - yahoo_packet_hash(pkt, 13, "1"); - yahoo_send_packet(yid, pkt, 0); - yahoo_packet_free(pkt); - } -} - -void yahoo_logoff(int id) -{ - struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); - struct yahoo_data *yd; - struct yahoo_packet *pkt = NULL; - - if (!yid) { - return; - } - yd = yid->yd; - - LOG(("yahoo_logoff: current status: %d", yd->current_status)); - - if (yd->current_status != -1 && 0) { - /* Meh. Don't send this. The event handlers are not going to - get to do this so it'll just leak memory. And the TCP - connection reset will hopefully be clear enough. */ - pkt = yahoo_packet_new(YAHOO_SERVICE_LOGOFF, - YPACKET_STATUS_DEFAULT, yd->session_id); - yd->current_status = -1; - - if (pkt) { - yahoo_send_packet(yid, pkt, 0); - yahoo_packet_free(pkt); - } - } - -/* do { - yahoo_input_close(yid); - } while((yid = find_input_by_id(id)));*/ - -} - -#if 0 -void yahoo_get_list(int id) -{ - struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); - struct yahoo_data *yd; - struct yahoo_packet *pkt = NULL; - - if (!yid) { - return; - } - yd = yid->yd; - - pkt = yahoo_packet_new(YAHOO_SERVICE_LIST, YPACKET_STATUS_DEFAULT, - yd->session_id); - yahoo_packet_hash(pkt, 1, yd->user); - if (pkt) { - yahoo_send_packet(yid, pkt, 0); - yahoo_packet_free(pkt); - } -} -#endif - -static void _yahoo_http_connected(int id, void *fd, int error, void *data) -{ - struct yahoo_input_data *yid = data; - - if (fd == NULL || error) { - inputs = y_list_remove(inputs, yid); - FREE(yid); - return; - } - - yid->fd = fd; - yid->read_tag = - YAHOO_CALLBACK (ext_yahoo_add_handler) (yid->yd->client_id, fd, - YAHOO_INPUT_READ, yid); -} - -#if 0 -/* FIXME Get address book from address.yahoo.com instead */ -void yahoo_get_yab(int id) -{ - struct yahoo_data *yd = find_conn_by_id(id); - struct yahoo_input_data *yid; - char url[1024]; - char buff[2048]; - - if (!yd) { - return; - } - - yid = y_new0(struct yahoo_input_data, 1); - yid->yd = yd; - yid->type = YAHOO_CONNECTION_YAB; - - LOG(("Sending request for Address Book")); - - snprintf(url, 1024, - "http://address.yahoo.com/yab/us?v=XM&prog=ymsgr&.intl=us" - "&diffs=1&t=0&tags=short&rt=0&prog-ver=8.1.0.249&useutf8=1&legenc=codepage-1252"); - - snprintf(buff, sizeof(buff), "Y=%s; T=%s", yd->cookie_y, yd->cookie_t); - - inputs = y_list_prepend(inputs, yid); - - yahoo_http_get(yid->yd->client_id, url, buff, 0, 0, - _yahoo_http_connected, yid); -} - -struct yahoo_post_data { - struct yahoo_input_data *yid; - char *data; -}; - -static void _yahoo_http_post_connected(int id, void *fd, int error, void *data) -{ - struct yahoo_post_data *yad = data; - struct yahoo_input_data *yid = yad->yid; - char *buff = yad->data; - - if (!fd) { - inputs = y_list_remove(inputs, yid); - FREE(yid); - return; - } - - YAHOO_CALLBACK (ext_yahoo_write) (fd, buff, strlen(buff)); - - yid->fd = fd; - yid->read_tag = - YAHOO_CALLBACK (ext_yahoo_add_handler) (yid->yd->client_id, fd, - YAHOO_INPUT_READ, yid); - - FREE(buff); - FREE(yad); -} - -/* FIXME This is also likely affected */ -void yahoo_set_yab(int id, struct yab *yab) -{ - struct yahoo_post_data *yad = y_new0(struct yahoo_post_data, 1); - struct yahoo_data *yd = find_conn_by_id(id); - struct yahoo_input_data *yid; - char url[1024]; - char buff[1024]; - char post[1024]; - int size = 0; - - if (!yd) { - return; - } - - yid = y_new0(struct yahoo_input_data, 1); - yid->type = YAHOO_CONNECTION_YAB; - yid->yd = yd; - - if (yab->yid) { - size = snprintf(post, sizeof(post), "<?xml version=\"1.0\" encoding=\"utf-8\"?>" - "<ab k=\"%s\" cc=\"%d\">" - "<ct id=\"%d\" e=\"1\" yi=\"%s\" nn=\"%s\" />" - "</ab>", yd->user, 9, yab->yid, /* Don't know why */ - yab->id, yab->nname ? yab->nname : ""); - } else { - size = snprintf(post, sizeof(post), "<?xml version=\"1.0\" encoding=\"utf-8\"?>" - "<ab k=\"%s\" cc=\"%d\">" - "<ct a=\"1\" yi=\"%s\" nn=\"%s\" />" - "</ab>", yd->user, 1, /* Don't know why */ - yab->id, yab->nname ? yab->nname : ""); - } - - yad->yid = yid; - yad->data = strdup(post); - - strcpy(url, "http://address.yahoo.com/yab/us?v=XM&prog=ymsgr&.intl=us" - "&sync=1&tags=short&noclear=1&useutf8=1&legenc=codepage-1252"); - - snprintf(buff, sizeof(buff), "Y=%s; T=%s", yd->cookie_y, yd->cookie_t); - - inputs = y_list_prepend(inputs, yid); - - yahoo_http_post(yid->yd->client_id, url, buff, size, - _yahoo_http_post_connected, yad); -} - -void yahoo_set_identity_status(int id, const char *identity, int active) -{ - struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); - struct yahoo_data *yd; - struct yahoo_packet *pkt = NULL; - - if (!yid) { - return; - } - yd = yid->yd; - - pkt = yahoo_packet_new(active ? YAHOO_SERVICE_IDACT : - YAHOO_SERVICE_IDDEACT, YPACKET_STATUS_DEFAULT, yd->session_id); - yahoo_packet_hash(pkt, 3, identity); - if (pkt) { - yahoo_send_packet(yid, pkt, 0); - yahoo_packet_free(pkt); - } -} - -void yahoo_refresh(int id) -{ - struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); - struct yahoo_data *yd; - struct yahoo_packet *pkt = NULL; - - if (!yid) { - return; - } - yd = yid->yd; - - pkt = yahoo_packet_new(YAHOO_SERVICE_USERSTAT, YPACKET_STATUS_DEFAULT, - yd->session_id); - if (pkt) { - yahoo_send_packet(yid, pkt, 0); - yahoo_packet_free(pkt); - } -} -#endif - -void yahoo_keepalive(int id) -{ - struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); - struct yahoo_data *yd; - struct yahoo_packet *pkt = NULL; - - if (!yid) { - return; - } - yd = yid->yd; - - pkt = yahoo_packet_new(YAHOO_SERVICE_PING, YPACKET_STATUS_DEFAULT, - yd->session_id); - yahoo_send_packet(yid, pkt, 0); - yahoo_packet_free(pkt); -} - -#if 0 -void yahoo_chat_keepalive(int id) -{ - struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); - struct yahoo_data *yd; - struct yahoo_packet *pkt = NULL; - - if (!yid) { - return; - } - - yd = yid->yd; - - pkt = yahoo_packet_new(YAHOO_SERVICE_CHATPING, YPACKET_STATUS_DEFAULT, - yd->session_id); - yahoo_send_packet(yid, pkt, 0); - yahoo_packet_free(pkt); -} -#endif - -void yahoo_add_buddy(int id, const char *who, const char *group, - const char *msg) -{ - struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); - struct yahoo_data *yd; - struct yahoo_packet *pkt; - - if (!yid) { - return; - } - yd = yid->yd; - - if (!yd->logged_in) { - return; - } - - pkt = yahoo_packet_new(YAHOO_SERVICE_ADDBUDDY, YPACKET_STATUS_DEFAULT, - yd->session_id); - if (msg != NULL) { /* add message/request "it's me add me" */ - yahoo_packet_hash(pkt, 14, msg); - } else { - yahoo_packet_hash(pkt, 14, ""); - } - yahoo_packet_hash(pkt, 65, group); - yahoo_packet_hash(pkt, 97, "1"); - yahoo_packet_hash(pkt, 1, yd->user); - yahoo_packet_hash(pkt, 302, "319"); - yahoo_packet_hash(pkt, 300, "319"); - yahoo_packet_hash(pkt, 7, who); - yahoo_packet_hash(pkt, 334, "0"); - yahoo_packet_hash(pkt, 301, "319"); - yahoo_packet_hash(pkt, 303, "319"); - yahoo_send_packet(yid, pkt, 0); - yahoo_packet_free(pkt); -} - -void yahoo_remove_buddy(int id, const char *who, const char *group) -{ - struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); - struct yahoo_data *yd; - struct yahoo_packet *pkt = NULL; - - if (!yid) { - return; - } - yd = yid->yd; - - pkt = yahoo_packet_new(YAHOO_SERVICE_REMBUDDY, YPACKET_STATUS_DEFAULT, - yd->session_id); - - yahoo_packet_hash(pkt, 1, yd->user); - yahoo_packet_hash(pkt, 7, who); - yahoo_packet_hash(pkt, 65, group); - yahoo_send_packet(yid, pkt, 0); - yahoo_packet_free(pkt); -} - -void yahoo_confirm_buddy(int id, const char *who, int reject, const char *msg) -{ - struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); - struct yahoo_data *yd; - struct yahoo_packet *pkt; - - if (!yid) { - return; - } - yd = yid->yd; - - if (!yd->logged_in) { - return; - } - - pkt = yahoo_packet_new(YAHOO_SERVICE_Y7_AUTHORIZATION, - YPACKET_STATUS_DEFAULT, yd->session_id); - yahoo_packet_hash(pkt, 1, yd->user); - yahoo_packet_hash(pkt, 5, who); - if (reject) { - yahoo_packet_hash(pkt, 13, "2"); - } else { - yahoo_packet_hash(pkt, 241, "0"); - yahoo_packet_hash(pkt, 13, "1"); - } - - yahoo_packet_hash(pkt, 334, "0"); - - if (reject) { - yahoo_packet_hash(pkt, 14, msg ? msg : ""); - yahoo_packet_hash(pkt, 97, "1"); - } - - yahoo_send_packet(yid, pkt, 0); - yahoo_packet_free(pkt); -} - -#if 0 -void yahoo_ignore_buddy(int id, const char *who, int unignore) -{ - struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); - struct yahoo_data *yd; - struct yahoo_packet *pkt; - - if (!yid) { - return; - } - yd = yid->yd; - - if (!yd->logged_in) { - return; - } - - pkt = yahoo_packet_new(YAHOO_SERVICE_IGNORECONTACT, - YPACKET_STATUS_DEFAULT, yd->session_id); - yahoo_packet_hash(pkt, 1, yd->user); - yahoo_packet_hash(pkt, 7, who); - yahoo_packet_hash(pkt, 13, unignore ? "2" : "1"); - yahoo_send_packet(yid, pkt, 0); - yahoo_packet_free(pkt); -} - -void yahoo_stealth_buddy(int id, const char *who, int unstealth) -{ - struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); - struct yahoo_data *yd; - struct yahoo_packet *pkt; - - if (!yid) { - return; - } - yd = yid->yd; - - if (!yd->logged_in) { - return; - } - - pkt = yahoo_packet_new(YAHOO_SERVICE_STEALTH_PERM, - YPACKET_STATUS_DEFAULT, yd->session_id); - yahoo_packet_hash(pkt, 1, yd->user); - yahoo_packet_hash(pkt, 7, who); - yahoo_packet_hash(pkt, 31, unstealth ? "2" : "1"); - yahoo_packet_hash(pkt, 13, "2"); - yahoo_send_packet(yid, pkt, 0); - yahoo_packet_free(pkt); -} -#endif - -void yahoo_change_buddy_group(int id, const char *who, const char *old_group, - const char *new_group) -{ - struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); - struct yahoo_data *yd; - struct yahoo_packet *pkt = NULL; - - if (!yid) { - return; - } - yd = yid->yd; - - pkt = yahoo_packet_new(YAHOO_SERVICE_Y7_CHANGE_GROUP, - YPACKET_STATUS_DEFAULT, yd->session_id); - yahoo_packet_hash(pkt, 1, yd->user); - yahoo_packet_hash(pkt, 302, "240"); - yahoo_packet_hash(pkt, 300, "240"); - yahoo_packet_hash(pkt, 7, who); - yahoo_packet_hash(pkt, 224, old_group); - yahoo_packet_hash(pkt, 264, new_group); - yahoo_packet_hash(pkt, 301, "240"); - yahoo_packet_hash(pkt, 303, "240"); - - yahoo_send_packet(yid, pkt, 0); - yahoo_packet_free(pkt); -} - -#if 0 -void yahoo_group_rename(int id, const char *old_group, const char *new_group) -{ - struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); - struct yahoo_data *yd; - struct yahoo_packet *pkt = NULL; - - if (!yid) { - return; - } - yd = yid->yd; - - pkt = yahoo_packet_new(YAHOO_SERVICE_GROUPRENAME, - YPACKET_STATUS_DEFAULT, yd->session_id); - yahoo_packet_hash(pkt, 1, yd->user); - yahoo_packet_hash(pkt, 65, old_group); - yahoo_packet_hash(pkt, 67, new_group); - - yahoo_send_packet(yid, pkt, 0); - yahoo_packet_free(pkt); -} - -void yahoo_conference_addinvite(int id, const char *from, const char *who, - const char *room, const YList *members, const char *msg) -{ - struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); - struct yahoo_data *yd; - struct yahoo_packet *pkt; - - if (!yid) { - return; - } - yd = yid->yd; - - pkt = yahoo_packet_new(YAHOO_SERVICE_CONFADDINVITE, - YPACKET_STATUS_DEFAULT, yd->session_id); - - yahoo_packet_hash(pkt, 1, (from ? from : yd->user)); - yahoo_packet_hash(pkt, 51, who); - yahoo_packet_hash(pkt, 57, room); - yahoo_packet_hash(pkt, 58, msg); - yahoo_packet_hash(pkt, 13, "0"); - for (; members; members = members->next) { - yahoo_packet_hash(pkt, 52, (char *) members->data); - yahoo_packet_hash(pkt, 53, (char *) members->data); - } - /* 52, 53 -> other members? */ - - yahoo_send_packet(yid, pkt, 0); - - yahoo_packet_free(pkt); -} -#endif - -void yahoo_conference_invite(int id, const char *from, YList *who, - const char *room, const char *msg) -{ - struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); - struct yahoo_data *yd; - struct yahoo_packet *pkt; - - if (!yid) { - return; - } - yd = yid->yd; - - pkt = yahoo_packet_new(YAHOO_SERVICE_CONFINVITE, YPACKET_STATUS_DEFAULT, - yd->session_id); - - yahoo_packet_hash(pkt, 1, (from ? from : yd->user)); - yahoo_packet_hash(pkt, 50, yd->user); - for (; who; who = who->next) { - yahoo_packet_hash(pkt, 52, (char *) who->data); - } - yahoo_packet_hash(pkt, 57, room); - yahoo_packet_hash(pkt, 58, msg); - yahoo_packet_hash(pkt, 13, "0"); - - yahoo_send_packet(yid, pkt, 0); - - yahoo_packet_free(pkt); -} - -void yahoo_conference_logon(int id, const char *from, YList *who, - const char *room) -{ - struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); - struct yahoo_data *yd; - struct yahoo_packet *pkt; - - if (!yid) { - return; - } - yd = yid->yd; - - pkt = yahoo_packet_new(YAHOO_SERVICE_CONFLOGON, YPACKET_STATUS_DEFAULT, - yd->session_id); - - yahoo_packet_hash(pkt, 1, (from ? from : yd->user)); - yahoo_packet_hash(pkt, 3, (from ? from : yd->user)); - yahoo_packet_hash(pkt, 57, room); - for (; who; who = who->next) { - yahoo_packet_hash(pkt, 3, (char *) who->data); - } - - yahoo_send_packet(yid, pkt, 0); - - yahoo_packet_free(pkt); -} - -void yahoo_conference_decline(int id, const char *from, YList *who, - const char *room, const char *msg) -{ - struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); - struct yahoo_data *yd; - struct yahoo_packet *pkt; - - if (!yid) { - return; - } - yd = yid->yd; - - pkt = yahoo_packet_new(YAHOO_SERVICE_CONFDECLINE, - YPACKET_STATUS_DEFAULT, yd->session_id); - - yahoo_packet_hash(pkt, 1, (from ? from : yd->user)); - yahoo_packet_hash(pkt, 3, (from ? from : yd->user)); - for (; who; who = who->next) { - yahoo_packet_hash(pkt, 3, (char *) who->data); - } - yahoo_packet_hash(pkt, 57, room); - yahoo_packet_hash(pkt, 14, msg); - - yahoo_send_packet(yid, pkt, 0); - - yahoo_packet_free(pkt); -} - -void yahoo_conference_logoff(int id, const char *from, YList *who, - const char *room) -{ - struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); - struct yahoo_data *yd; - struct yahoo_packet *pkt; - - if (!yid) { - return; - } - yd = yid->yd; - - pkt = yahoo_packet_new(YAHOO_SERVICE_CONFLOGOFF, YPACKET_STATUS_DEFAULT, - yd->session_id); - - yahoo_packet_hash(pkt, 1, (from ? from : yd->user)); - yahoo_packet_hash(pkt, 3, (from ? from : yd->user)); - for (; who; who = who->next) { - yahoo_packet_hash(pkt, 3, (char *) who->data); - } - - yahoo_packet_hash(pkt, 57, room); - - yahoo_send_packet(yid, pkt, 0); - - yahoo_packet_free(pkt); -} - -void yahoo_conference_message(int id, const char *from, YList *who, - const char *room, const char *msg, int utf8) -{ - struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); - struct yahoo_data *yd; - struct yahoo_packet *pkt; - - if (!yid) { - return; - } - yd = yid->yd; - - pkt = yahoo_packet_new(YAHOO_SERVICE_CONFMSG, YPACKET_STATUS_DEFAULT, - yd->session_id); - - yahoo_packet_hash(pkt, 1, (from ? from : yd->user)); - yahoo_packet_hash(pkt, 53, (from ? from : yd->user)); - for (; who; who = who->next) { - yahoo_packet_hash(pkt, 53, (char *) who->data); - } - - yahoo_packet_hash(pkt, 57, room); - yahoo_packet_hash(pkt, 14, msg); - - if (utf8) { - yahoo_packet_hash(pkt, 97, "1"); - } - - yahoo_send_packet(yid, pkt, 0); - - yahoo_packet_free(pkt); -} - -#if 0 -void yahoo_get_chatrooms(int id, int chatroomid) -{ - struct yahoo_data *yd = find_conn_by_id(id); - struct yahoo_input_data *yid; - char url[1024]; - char buff[1024]; - - if (!yd) { - return; - } - - yid = y_new0(struct yahoo_input_data, 1); - yid->yd = yd; - yid->type = YAHOO_CONNECTION_CHATCAT; - - if (chatroomid == 0) { - snprintf(url, 1024, - "http://insider.msg.yahoo.com/ycontent/?chatcat=0"); - } else { - snprintf(url, 1024, - "http://insider.msg.yahoo.com/ycontent/?chatroom_%d=0", - chatroomid); - } - - snprintf(buff, sizeof(buff), "Y=%s; T=%s", yd->cookie_y, yd->cookie_t); - - inputs = y_list_prepend(inputs, yid); - - yahoo_http_get(yid->yd->client_id, url, buff, 0, 0, - _yahoo_http_connected, yid); -} - -void yahoo_chat_logon(int id, const char *from, const char *room, - const char *roomid) -{ - struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); - struct yahoo_data *yd; - struct yahoo_packet *pkt; - - if (!yid) { - return; - } - - yd = yid->yd; - - pkt = yahoo_packet_new(YAHOO_SERVICE_CHATONLINE, YPACKET_STATUS_DEFAULT, - yd->session_id); - - yahoo_packet_hash(pkt, 1, (from ? from : yd->user)); - yahoo_packet_hash(pkt, 109, yd->user); - yahoo_packet_hash(pkt, 6, "abcde"); - - yahoo_send_packet(yid, pkt, 0); - - yahoo_packet_free(pkt); - - pkt = yahoo_packet_new(YAHOO_SERVICE_CHATJOIN, YPACKET_STATUS_DEFAULT, - yd->session_id); - - yahoo_packet_hash(pkt, 1, (from ? from : yd->user)); - yahoo_packet_hash(pkt, 104, room); - yahoo_packet_hash(pkt, 129, roomid); - yahoo_packet_hash(pkt, 62, "2"); /* ??? */ - - yahoo_send_packet(yid, pkt, 0); - - yahoo_packet_free(pkt); -} - -void yahoo_chat_message(int id, const char *from, const char *room, - const char *msg, const int msgtype, const int utf8) -{ - struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); - struct yahoo_data *yd; - struct yahoo_packet *pkt; - char buf[2]; - - if (!yid) { - return; - } - - yd = yid->yd; - - pkt = yahoo_packet_new(YAHOO_SERVICE_COMMENT, YPACKET_STATUS_DEFAULT, - yd->session_id); - - yahoo_packet_hash(pkt, 1, (from ? from : yd->user)); - yahoo_packet_hash(pkt, 104, room); - yahoo_packet_hash(pkt, 117, msg); - - snprintf(buf, sizeof(buf), "%d", msgtype); - yahoo_packet_hash(pkt, 124, buf); - - if (utf8) { - yahoo_packet_hash(pkt, 97, "1"); - } - - yahoo_send_packet(yid, pkt, 0); - - yahoo_packet_free(pkt); -} - -void yahoo_chat_logoff(int id, const char *from) -{ - struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); - struct yahoo_data *yd; - struct yahoo_packet *pkt; - - if (!yid) { - return; - } - - yd = yid->yd; - - pkt = yahoo_packet_new(YAHOO_SERVICE_CHATLOGOUT, YPACKET_STATUS_DEFAULT, - yd->session_id); - - yahoo_packet_hash(pkt, 1, (from ? from : yd->user)); - - yahoo_send_packet(yid, pkt, 0); - - yahoo_packet_free(pkt); -} - -void yahoo_buddyicon_request(int id, const char *who) -{ - struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); - struct yahoo_data *yd; - struct yahoo_packet *pkt; - - if (!yid) { - return; - } - - yd = yid->yd; - - pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE, YPACKET_STATUS_DEFAULT, - 0); - yahoo_packet_hash(pkt, 4, yd->user); - yahoo_packet_hash(pkt, 5, who); - yahoo_packet_hash(pkt, 13, "1"); - yahoo_send_packet(yid, pkt, 0); - - yahoo_packet_free(pkt); -} - -void yahoo_send_picture_info(int id, const char *who, const char *url, - int checksum) -{ - struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); - struct yahoo_data *yd; - struct yahoo_packet *pkt; - char checksum_str[10]; - - if (!yid) { - return; - } - - yd = yid->yd; - - snprintf(checksum_str, sizeof(checksum_str), "%d", checksum); - - pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE, YPACKET_STATUS_DEFAULT, - 0); - yahoo_packet_hash(pkt, 1, yd->user); - yahoo_packet_hash(pkt, 4, yd->user); - yahoo_packet_hash(pkt, 5, who); - yahoo_packet_hash(pkt, 13, "2"); - yahoo_packet_hash(pkt, 20, url); - yahoo_packet_hash(pkt, 192, checksum_str); - yahoo_send_packet(yid, pkt, 0); - - yahoo_packet_free(pkt); -} - -void yahoo_send_picture_update(int id, const char *who, int type) -{ - struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); - struct yahoo_data *yd; - struct yahoo_packet *pkt; - char type_str[10]; - - if (!yid) { - return; - } - - yd = yid->yd; - - snprintf(type_str, sizeof(type_str), "%d", type); - - pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE_UPDATE, - YPACKET_STATUS_DEFAULT, 0); - yahoo_packet_hash(pkt, 1, yd->user); - yahoo_packet_hash(pkt, 5, who); - yahoo_packet_hash(pkt, 206, type_str); - yahoo_send_packet(yid, pkt, 0); - - yahoo_packet_free(pkt); -} - -void yahoo_send_picture_checksum(int id, const char *who, int checksum) -{ - struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); - struct yahoo_data *yd; - struct yahoo_packet *pkt; - char checksum_str[10]; - - if (!yid) { - return; - } - - yd = yid->yd; - - snprintf(checksum_str, sizeof(checksum_str), "%d", checksum); - - pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE_CHECKSUM, - YPACKET_STATUS_DEFAULT, 0); - yahoo_packet_hash(pkt, 1, yd->user); - if (who != 0) { - yahoo_packet_hash(pkt, 5, who); - } - yahoo_packet_hash(pkt, 192, checksum_str); - yahoo_packet_hash(pkt, 212, "1"); - yahoo_send_packet(yid, pkt, 0); - - yahoo_packet_free(pkt); -} - -void yahoo_webcam_close_feed(int id, const char *who) -{ - struct yahoo_input_data *yid = - find_input_by_id_and_webcam_user(id, who); - - if (yid) { - yahoo_input_close(yid); - } -} - -void yahoo_webcam_get_feed(int id, const char *who) -{ - struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); - struct yahoo_data *yd; - struct yahoo_packet *pkt; - - if (!yid) { - return; - } - - /* - * add the user to the queue. this is a dirty hack, since - * the yahoo server doesn't tell us who's key it's returning, - * we have to just hope that it sends back keys in the same - * order that we request them. - * The queue is popped in yahoo_process_webcam_key - */ - webcam_queue = y_list_append(webcam_queue, who ? strdup(who) : NULL); - - yd = yid->yd; - - pkt = yahoo_packet_new(YAHOO_SERVICE_WEBCAM, YPACKET_STATUS_DEFAULT, - yd->session_id); - - yahoo_packet_hash(pkt, 1, yd->user); - if (who != NULL) { - yahoo_packet_hash(pkt, 5, who); - } - yahoo_send_packet(yid, pkt, 0); - - yahoo_packet_free(pkt); -} - -void yahoo_webcam_send_image(int id, unsigned char *image, unsigned int length, - unsigned int timestamp) -{ - struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_WEBCAM); - unsigned char *packet; - unsigned char header_len = 13; - unsigned int pos = 0; - - if (!yid) { - return; - } - - packet = y_new0(unsigned char, header_len); - - packet[pos++] = header_len; - packet[pos++] = 0; - packet[pos++] = 5; /* version byte?? */ - packet[pos++] = 0; - pos += yahoo_put32(packet + pos, length); - packet[pos++] = 2; /* packet type, image */ - pos += yahoo_put32(packet + pos, timestamp); - yahoo_add_to_send_queue(yid, packet, header_len); - FREE(packet); - - if (length) { - yahoo_add_to_send_queue(yid, image, length); - } -} - -void yahoo_webcam_accept_viewer(int id, const char *who, int accept) -{ - struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_WEBCAM); - char *packet = NULL; - char *data = NULL; - unsigned char header_len = 13; - unsigned int pos = 0; - unsigned int len = 0; - - if (!yid) { - return; - } - - data = strdup("u="); - data = y_string_append(data, (char *) who); - data = y_string_append(data, "\r\n"); - len = strlen(data); - - packet = y_new0(char, header_len + len); - packet[pos++] = header_len; - packet[pos++] = 0; - packet[pos++] = 5; /* version byte?? */ - packet[pos++] = 0; - pos += yahoo_put32(packet + pos, len); - packet[pos++] = 0; /* packet type */ - pos += yahoo_put32(packet + pos, accept); - memcpy(packet + pos, data, len); - FREE(data); - yahoo_add_to_send_queue(yid, packet, header_len + len); - FREE(packet); -} - -void yahoo_webcam_invite(int id, const char *who) -{ - struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); - struct yahoo_packet *pkt; - - if (!yid) { - return; - } - - pkt = yahoo_packet_new(YAHOO_SERVICE_NOTIFY, YPACKET_STATUS_NOTIFY, - yid->yd->session_id); - - yahoo_packet_hash(pkt, 49, "WEBCAMINVITE"); - yahoo_packet_hash(pkt, 14, " "); - yahoo_packet_hash(pkt, 13, "0"); - yahoo_packet_hash(pkt, 1, yid->yd->user); - yahoo_packet_hash(pkt, 5, who); - yahoo_send_packet(yid, pkt, 0); - - yahoo_packet_free(pkt); -} - -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) -{ - struct yahoo_data *yd = find_conn_by_id(id); - struct yahoo_input_data *yid; - char url[1024]; - char buff[1024]; - char *ctext, *p; - - if (!yd) { - return; - } - - yid = y_new0(struct yahoo_input_data, 1); - yid->yd = yd; - yid->type = YAHOO_CONNECTION_SEARCH; - - /* - age range - .ar=1 - 13-18, 2 - 18-25, 3 - 25-35, 4 - 35-50, 5 - 50-70, 6 - 70+ - */ - - snprintf(buff, sizeof(buff), "&.sq=%%20&.tt=%d&.ss=%d", total, - startpos); - - ctext = strdup(text); - while ((p = strchr(ctext, ' '))) { - *p = '+'; - } - - snprintf(url, 1024, - "http://members.yahoo.com/interests?.oc=m&.kw=%s&.sb=%d&.g=%d&.ar=0%s%s%s", - ctext, t, g, photo ? "&.p=y" : "", yahoo_only ? "&.pg=y" : "", - startpos ? buff : ""); - - FREE(ctext); - - snprintf(buff, sizeof(buff), "Y=%s; T=%s", yd->cookie_y, yd->cookie_t); - - inputs = y_list_prepend(inputs, yid); - yahoo_http_get(yid->yd->client_id, url, buff, 0, 0, - _yahoo_http_connected, yid); -} - -void yahoo_search(int id, enum yahoo_search_type t, const char *text, - enum yahoo_search_gender g, enum yahoo_search_agerange ar, int photo, - int yahoo_only) -{ - struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); - struct yahoo_search_state *yss; - - if (!yid) { - return; - } - - if (!yid->ys) { - yid->ys = y_new0(struct yahoo_search_state, 1); - } - - yss = yid->ys; - - FREE(yss->lsearch_text); - yss->lsearch_type = t; - yss->lsearch_text = strdup(text); - yss->lsearch_gender = g; - yss->lsearch_agerange = ar; - yss->lsearch_photo = photo; - yss->lsearch_yahoo_only = yahoo_only; - - yahoo_search_internal(id, t, text, g, ar, photo, yahoo_only, 0, 0); -} - -void yahoo_search_again(int id, int start) -{ - struct yahoo_input_data *yid = - find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); - struct yahoo_search_state *yss; - - if (!yid || !yid->ys) { - return; - } - - yss = yid->ys; - - if (start == -1) { - start = yss->lsearch_nstart + yss->lsearch_nfound; - } - - yahoo_search_internal(id, yss->lsearch_type, yss->lsearch_text, - yss->lsearch_gender, yss->lsearch_agerange, - yss->lsearch_photo, yss->lsearch_yahoo_only, - start, yss->lsearch_ntotal); -} - -void yahoo_send_picture(int id, const char *name, unsigned long size, - yahoo_get_fd_callback callback, void *data) -{ - /* Not Implemented */ -} -#endif - -/* File Transfer */ -static YList *active_file_transfers = NULL; - -enum { - FT_STATE_HEAD = 1, - FT_STATE_RECV, - FT_STATE_RECV_START, - FT_STATE_SEND -}; - -struct send_file_data { - int client_id; - char *id; - char *who; - char *filename; - char *ip_addr; - char *token; - int size; - - struct yahoo_input_data *yid; - int state; - - yahoo_get_fd_callback callback; - void *data; -}; - -#if 0 -static char *yahoo_get_random(void) -{ - int i = 0; - int r = 0; - int c = 0; - char out[25]; - - out[24] = '\0'; - out[23] = '$'; - out[22] = '$'; - - for (i = 0; i < 22; i++) { - if (r == 0) { - r = rand(); - } - - c = r % 61; - - if (c < 26) { - out[i] = c + 'a'; - } else if (c < 52) { - out[i] = c - 26 + 'A'; - } else { - out[i] = c - 52 + '0'; - } - - r /= 61; - } - - return strdup(out); -} -#endif - -static int _are_same_id(const void *sfd1, const void *id) -{ - return strcmp(((struct send_file_data *) sfd1)->id, (char *) id); -} - -static int _are_same_yid(const void *sfd1, const void *yid) -{ - if (((struct send_file_data *) sfd1)->yid == yid) { - return 0; - } else { - return 1; - } -} - -static struct send_file_data *yahoo_get_active_transfer(char *id) -{ - YList *l = y_list_find_custom(active_file_transfers, id, - _are_same_id); - - if (l) { - return (struct send_file_data *) l->data; - } - - return NULL; -} - -static struct send_file_data *yahoo_get_active_transfer_with_yid(void *yid) -{ - YList *l = y_list_find_custom(active_file_transfers, yid, - _are_same_yid); - - if (l) { - return (struct send_file_data *) l->data; - } - - return NULL; -} - -static void yahoo_add_active_transfer(struct send_file_data *sfd) -{ - active_file_transfers = y_list_prepend(active_file_transfers, sfd); -} - -static void yahoo_remove_active_transfer(struct send_file_data *sfd) -{ - if (sfd == NULL) { - return; - } - - active_file_transfers = y_list_remove(active_file_transfers, sfd); - free(sfd->id); - free(sfd->who); - free(sfd->filename); - free(sfd->ip_addr); - FREE(sfd); -} - -static void _yahoo_ft_upload_connected(int id, void *fd, int error, void *data) -{ - struct send_file_data *sfd = data; - struct yahoo_input_data *yid = sfd->yid; - - if (!fd) { - inputs = y_list_remove(inputs, yid); - FREE(yid); - return; - } - - sfd->callback(id, fd, error, sfd->data); - - yid->fd = fd; - yid->read_tag = - YAHOO_CALLBACK (ext_yahoo_add_handler) (yid->yd->client_id, fd, - YAHOO_INPUT_READ, yid); -} - -static void yahoo_file_transfer_upload(struct yahoo_data *yd, - struct send_file_data *sfd) -{ - char url[256]; - char buff[4096]; - char *sender_enc = NULL, *recv_enc = NULL, *token_enc = NULL; - - struct yahoo_input_data *yid = y_new0(struct yahoo_input_data, 1); - - yid->yd = yd; - yid->type = YAHOO_CONNECTION_FT; - - inputs = y_list_prepend(inputs, yid); - sfd->yid = yid; - sfd->state = FT_STATE_SEND; - - token_enc = yahoo_urlencode(sfd->token); - sender_enc = yahoo_urlencode(yd->user); - recv_enc = yahoo_urlencode(sfd->who); - - snprintf(url, sizeof(url), - "http://%s/relay?token=%s&sender=%s&recver=%s", sfd->ip_addr, - token_enc, sender_enc, recv_enc); - - snprintf(buff, sizeof(buff), "T=%s; Y=%s", yd->cookie_t, yd->cookie_y); - - yahoo_http_post(yd->client_id, url, buff, sfd->size, - _yahoo_ft_upload_connected, sfd); - - FREE(token_enc); - FREE(sender_enc); - FREE(recv_enc); -} - -static void yahoo_init_ft_recv(struct yahoo_data *yd, - struct send_file_data *sfd) -{ - char url[256]; - char buff[1024]; - char *sender_enc = NULL, *recv_enc = NULL, *token_enc = NULL; - - struct yahoo_input_data *yid = y_new0(struct yahoo_input_data, 1); - - yid->yd = yd; - yid->type = YAHOO_CONNECTION_FT; - - inputs = y_list_prepend(inputs, yid); - sfd->yid = yid; - sfd->state = FT_STATE_HEAD; - - token_enc = yahoo_urlencode(sfd->token); - sender_enc = yahoo_urlencode(sfd->who); - recv_enc = yahoo_urlencode(yd->user); - - snprintf(url, sizeof(url), - "http://%s/relay?token=%s&sender=%s&recver=%s", sfd->ip_addr, - token_enc, sender_enc, recv_enc); - - snprintf(buff, sizeof(buff), "Y=%s; T=%s", yd->cookie_y, yd->cookie_t); - - yahoo_http_head(yid->yd->client_id, url, buff, 0, NULL, - _yahoo_http_connected, yid); - - FREE(token_enc); - FREE(sender_enc); - FREE(recv_enc); -} - -static void yahoo_file_transfer_accept(struct yahoo_input_data *yid, - struct send_file_data *sfd) -{ - struct yahoo_packet *pkt; - - pkt = yahoo_packet_new(YAHOO_SERVICE_Y7_FILETRANSFERACCEPT, - YPACKET_STATUS_DEFAULT, yid->yd->session_id); - - yahoo_packet_hash(pkt, 1, yid->yd->user); - yahoo_packet_hash(pkt, 5, sfd->who); - yahoo_packet_hash(pkt, 265, sfd->id); - yahoo_packet_hash(pkt, 27, sfd->filename); - yahoo_packet_hash(pkt, 249, "3"); - yahoo_packet_hash(pkt, 251, sfd->token); - - yahoo_send_packet(yid, pkt, 0); - - yahoo_packet_free(pkt); - - yahoo_init_ft_recv(yid->yd, sfd); -} - -static void yahoo_process_filetransferaccept(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) -{ - YList *l; - struct send_file_data *sfd; - char *id = NULL; - char *token = NULL; - - for (l = pkt->hash; l; l = l->next) { - struct yahoo_pair *pair = l->data; - switch (pair->key) { - case 4: - /* who */ - break; - case 5: - /* Me... don't care */ - break; - case 249: - break; - case 265: - id = pair->value; - break; - case 251: - token = pair->value; - break; - case 27: - /* filename */ - break; - } - } - - sfd = yahoo_get_active_transfer(id); - - if (sfd) { - sfd->token = strdup(token); - - yahoo_file_transfer_upload(yid->yd, sfd); - } else { - YAHOO_CALLBACK (ext_yahoo_file_transfer_done) - (yid->yd->client_id, YAHOO_FILE_TRANSFER_UNKNOWN, - sfd ? sfd->data : NULL); - - yahoo_remove_active_transfer(sfd); - } -} - -static void yahoo_process_filetransferinfo(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) -{ - YList *l; - char *id = NULL; - char *token = NULL; - char *ip_addr = NULL; - - struct send_file_data *sfd; - - for (l = pkt->hash; l; l = l->next) { - struct yahoo_pair *pair = l->data; - switch (pair->key) { - case 1: - case 4: - /* who */ - break; - case 5: - /* Me... don't care */ - break; - case 249: - break; - case 265: - id = pair->value; - break; - case 250: - ip_addr = pair->value; - break; - case 251: - token = pair->value; - break; - case 27: - /* filename */ - break; - } - } - - sfd = yahoo_get_active_transfer(id); - - if (sfd) { - sfd->token = strdup(token); - sfd->ip_addr = strdup(ip_addr); - - yahoo_file_transfer_accept(yid, sfd); - } else { - YAHOO_CALLBACK (ext_yahoo_file_transfer_done) - (yid->yd->client_id, YAHOO_FILE_TRANSFER_UNKNOWN, - sfd ? sfd->data : NULL); - - yahoo_remove_active_transfer(sfd); - } -} - -static void yahoo_send_filetransferinfo(struct yahoo_data *yd, - struct send_file_data *sfd) -{ - struct yahoo_input_data *yid; - struct yahoo_packet *pkt; - - yid = find_input_by_id_and_type(yd->client_id, YAHOO_CONNECTION_PAGER); - sfd->ip_addr = YAHOO_CALLBACK (ext_yahoo_get_ip_addr)("relay.yahoo.com"); - - if (!sfd->ip_addr) { - YAHOO_CALLBACK (ext_yahoo_file_transfer_done) - (yd->client_id, YAHOO_FILE_TRANSFER_RELAY, sfd->data); - - yahoo_remove_active_transfer(sfd); - - return; - } - - pkt = yahoo_packet_new(YAHOO_SERVICE_Y7_FILETRANSFERINFO, - YPACKET_STATUS_DEFAULT, yd->session_id); - - yahoo_packet_hash(pkt, 1, yd->user); - yahoo_packet_hash(pkt, 5, sfd->who); - yahoo_packet_hash(pkt, 265, sfd->id); - yahoo_packet_hash(pkt, 27, sfd->filename); - yahoo_packet_hash(pkt, 249, "3"); - yahoo_packet_hash(pkt, 250, sfd->ip_addr); - - yahoo_send_packet(yid, pkt, 0); - - yahoo_packet_free(pkt); -} - -static void yahoo_process_filetransfer(struct yahoo_input_data *yid, - struct yahoo_packet *pkt) -{ - YList *l; - char *who = NULL; - char *filename = NULL; - char *msg = NULL; - char *id = NULL; - int action = 0; - int size = 0; - struct yahoo_data *yd = yid->yd; - - struct send_file_data *sfd; - - for (l = pkt->hash; l; l = l->next) { - struct yahoo_pair *pair = l->data; - switch (pair->key) { - case 4: - who = pair->value; - break; - case 5: - /* Me... don't care */ - break; - case 222: - action = atoi(pair->value); - break; - case 265: - id = pair->value; - break; - case 266: /* Don't know */ - break; - case 302: /* Start Data? */ - break; - case 300: - break; - case 27: - filename = pair->value; - break; - case 28: - size = atoi(pair->value); - break; - case 14: - msg = pair->value; - case 301: /* End Data? */ - break; - case 303: - break; - - } - } - - if (action == YAHOO_FILE_TRANSFER_INIT) { - /* Received a FT request from buddy */ - sfd = y_new0(struct send_file_data, 1); - - sfd->client_id = yd->client_id; - sfd->id = strdup(id); - sfd->who = strdup(who); - sfd->filename = strdup(filename); - sfd->size = size; - - yahoo_add_active_transfer(sfd); - - YAHOO_CALLBACK (ext_yahoo_got_file) (yd->client_id, yd->user, - who, msg, filename, size, sfd->id); - } else { - /* Response to our request */ - sfd = yahoo_get_active_transfer(id); - - if (sfd && action == YAHOO_FILE_TRANSFER_ACCEPT) { - yahoo_send_filetransferinfo(yd, sfd); - } else if (!sfd || action == YAHOO_FILE_TRANSFER_REJECT) { - YAHOO_CALLBACK (ext_yahoo_file_transfer_done) - (yd->client_id, YAHOO_FILE_TRANSFER_REJECT, - sfd ? sfd->data : NULL); - - yahoo_remove_active_transfer(sfd); - } - } -} - -#if 0 -void yahoo_send_file(int id, const char *who, const char *msg, - const char *name, unsigned long size, - yahoo_get_fd_callback callback, void *data) -{ - struct yahoo_packet *pkt = NULL; - char size_str[10]; - struct yahoo_input_data *yid; - struct yahoo_data *yd; - struct send_file_data *sfd; - - yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); - yd = find_conn_by_id(id); - sfd = y_new0(struct send_file_data, 1); - - sfd->client_id = id; - sfd->id = yahoo_get_random(); - sfd->who = strdup(who); - sfd->filename = strdup(name); - sfd->size = size; - sfd->callback = callback; - sfd->data = data; - - yahoo_add_active_transfer(sfd); - - if (!yd) { - return; - } - - pkt = yahoo_packet_new(YAHOO_SERVICE_Y7_FILETRANSFER, - YPACKET_STATUS_DEFAULT, yd->session_id); - - snprintf(size_str, sizeof(size_str), "%ld", size); - - yahoo_packet_hash(pkt, 1, yd->user); - yahoo_packet_hash(pkt, 5, who); - yahoo_packet_hash(pkt, 265, sfd->id); - yahoo_packet_hash(pkt, 222, "1"); - yahoo_packet_hash(pkt, 266, "1"); - yahoo_packet_hash(pkt, 302, "268"); - yahoo_packet_hash(pkt, 300, "268"); - yahoo_packet_hash(pkt, 27, name); - yahoo_packet_hash(pkt, 28, size_str); - yahoo_packet_hash(pkt, 301, "268"); - yahoo_packet_hash(pkt, 303, "268"); - - yahoo_send_packet(yid, pkt, 0); - - yahoo_packet_free(pkt); -} - -void yahoo_send_file_transfer_response(int client_id, int response, char *id, void *data) -{ - struct yahoo_packet *pkt = NULL; - char resp[2]; - struct yahoo_input_data *yid; - - struct send_file_data *sfd = yahoo_get_active_transfer(id); - - sfd->data = data; - - yid = find_input_by_id_and_type(client_id, YAHOO_CONNECTION_PAGER); - - pkt = yahoo_packet_new(YAHOO_SERVICE_Y7_FILETRANSFER, - YPACKET_STATUS_DEFAULT, yid->yd->session_id); - - snprintf(resp, sizeof(resp), "%d", response); - - yahoo_packet_hash(pkt, 1, yid->yd->user); - yahoo_packet_hash(pkt, 5, sfd->who); - yahoo_packet_hash(pkt, 265, sfd->id); - yahoo_packet_hash(pkt, 222, resp); - - yahoo_send_packet(yid, pkt, 0); - - yahoo_packet_free(pkt); - - if (response == YAHOO_FILE_TRANSFER_REJECT) { - yahoo_remove_active_transfer(sfd); - } -} -#endif - -static void yahoo_process_ft_connection(struct yahoo_input_data *yid, int over) -{ - struct send_file_data *sfd; - struct yahoo_data *yd = yid->yd; - - sfd = yahoo_get_active_transfer_with_yid(yid); - - if (!sfd) { - LOG(("Something funny happened. yid %p has no sfd.\n", yid)); - return; - } - - /* - * We want to handle only the complete data with HEAD since we don't - * want a situation where both the GET and HEAD are active. - * With SEND, we really can't do much with partial response - */ - if ((sfd->state == FT_STATE_HEAD || sfd->state == FT_STATE_SEND) - && !over) { - return; - } - - if (sfd->state == FT_STATE_HEAD) { - /* Do a GET */ - char url[256]; - char buff[1024]; - char *sender_enc = NULL, *recv_enc = NULL, *token_enc = NULL; - - struct yahoo_input_data *yid_ft = - y_new0(struct yahoo_input_data, 1); - - yid_ft->yd = yid->yd; - yid_ft->type = YAHOO_CONNECTION_FT; - - inputs = y_list_prepend(inputs, yid_ft); - sfd->yid = yid_ft; - sfd->state = FT_STATE_RECV; - - token_enc = yahoo_urlencode(sfd->token); - sender_enc = yahoo_urlencode(sfd->who); - recv_enc = yahoo_urlencode(yd->user); - - snprintf(url, sizeof(url), - "http://%s/relay?token=%s&sender=%s&recver=%s", sfd->ip_addr, - token_enc, sender_enc, recv_enc); - - snprintf(buff, sizeof(buff), "Y=%s; T=%s", yd->cookie_y, - yd->cookie_t); - - - yahoo_http_get(yd->client_id, url, buff, 1, 1, - _yahoo_http_connected, yid_ft); - - FREE(token_enc); - FREE(sender_enc); - FREE(recv_enc); - } else if (sfd->state == FT_STATE_RECV || - sfd->state == FT_STATE_RECV_START) { - - unsigned char *data_begin = NULL; - - if (yid->rxlen == 0) { - yahoo_remove_active_transfer(sfd); - } - - if (sfd->state != FT_STATE_RECV_START && - (data_begin = - (unsigned char *) strstr((char *) yid->rxqueue, - "\r\n\r\n"))) { - - sfd->state = FT_STATE_RECV_START; - - yid->rxlen -= 4 + (data_begin - yid->rxqueue) / sizeof(char); - data_begin += 4; - - if (yid->rxlen > 0) { - YAHOO_CALLBACK (ext_yahoo_got_ft_data) - (yd->client_id, data_begin, - yid->rxlen, sfd->data); - } - } else if (sfd->state == FT_STATE_RECV_START) { - YAHOO_CALLBACK (ext_yahoo_got_ft_data) (yd->client_id, - yid->rxqueue, yid->rxlen, sfd->data); - } - - FREE(yid->rxqueue); - yid->rxqueue = NULL; - yid->rxlen = 0; - } else if (sfd->state == FT_STATE_SEND) { - /* Sent file completed */ - int len = 0; - char *off = strstr((char *) yid->rxqueue, "Content-Length: "); - - if (off) { - off += 16; - len = atoi(off); - } - - if (len < sfd->size) { - YAHOO_CALLBACK (ext_yahoo_file_transfer_done) - (yd->client_id, - YAHOO_FILE_TRANSFER_FAILED, sfd->data); - } else { - YAHOO_CALLBACK (ext_yahoo_file_transfer_done) - (yd->client_id, - YAHOO_FILE_TRANSFER_DONE, sfd->data); - } - - yahoo_remove_active_transfer(sfd); - } -} - -/* End File Transfer */ - -#if 0 -enum yahoo_status yahoo_current_status(int id) -{ - struct yahoo_data *yd = find_conn_by_id(id); - - if (!yd) { - return YAHOO_STATUS_OFFLINE; - } - return yd->current_status; -} - -const YList *yahoo_get_buddylist(int id) -{ - struct yahoo_data *yd = find_conn_by_id(id); - - if (!yd) { - return NULL; - } - return yd->buddies; -} - -const YList *yahoo_get_ignorelist(int id) -{ - struct yahoo_data *yd = find_conn_by_id(id); - - if (!yd) { - return NULL; - } - return yd->ignore; -} - -const YList *yahoo_get_identities(int id) -{ - struct yahoo_data *yd = find_conn_by_id(id); - - if (!yd) { - return NULL; - } - return yd->identities; -} - -const char *yahoo_get_cookie(int id, const char *which) -{ - struct yahoo_data *yd = find_conn_by_id(id); - - if (!yd) { - return NULL; - } - if (!strncasecmp(which, "y", 1)) { - return yd->cookie_y; - } - if (!strncasecmp(which, "b", 1)) { - return yd->cookie_b; - } - if (!strncasecmp(which, "t", 1)) { - return yd->cookie_t; - } - if (!strncasecmp(which, "c", 1)) { - return yd->cookie_c; - } - if (!strncasecmp(which, "login", 5)) { - return yd->login_cookie; - } - return NULL; -} -#endif - -const char *yahoo_get_profile_url(void) -{ - return profile_url; -} |