diff options
Diffstat (limited to 'protocols/yahoo')
| -rw-r--r-- | protocols/yahoo/libyahoo2.c | 725 | ||||
| -rw-r--r-- | protocols/yahoo/yahoo.c | 121 | ||||
| -rw-r--r-- | protocols/yahoo/yahoo2.h | 3 | ||||
| -rw-r--r-- | protocols/yahoo/yahoo2_callbacks.h | 12 | ||||
| -rw-r--r-- | protocols/yahoo/yahoo2_types.h | 44 | 
5 files changed, 640 insertions, 265 deletions
| diff --git a/protocols/yahoo/libyahoo2.c b/protocols/yahoo/libyahoo2.c index a61955c4..5b2ff44e 100644 --- a/protocols/yahoo/libyahoo2.c +++ b/protocols/yahoo/libyahoo2.c @@ -88,6 +88,7 @@ char *strchr (), *strrchr ();  #endif  #include "base64.h" +#include "http_client.h"  #ifdef USE_STRUCT_CALLBACKS  struct yahoo_callbacks *yc=NULL; @@ -168,6 +169,7 @@ enum yahoo_service { /* these are easier to see in hex */  	YAHOO_SERVICE_PING,  	YAHOO_SERVICE_GOTGROUPRENAME, /* < 1, 36(old), 37(new) */  	YAHOO_SERVICE_SYSMESSAGE = 0x14, +	YAHOO_SERVICE_SKINNAME = 0x15,  	YAHOO_SERVICE_PASSTHROUGH2 = 0x16,  	YAHOO_SERVICE_CONFINVITE = 0x18,  	YAHOO_SERVICE_CONFLOGON, @@ -191,16 +193,19 @@ enum yahoo_service { /* these are easier to see in hex */  	YAHOO_SERVICE_AUTHRESP = 0x54,  	YAHOO_SERVICE_LIST,  	YAHOO_SERVICE_AUTH = 0x57, +	YAHOO_SERVICE_AUTHBUDDY = 0x6d,  	YAHOO_SERVICE_ADDBUDDY = 0x83,  	YAHOO_SERVICE_REMBUDDY,  	YAHOO_SERVICE_IGNORECONTACT,	/* > 1, 7, 13 < 1, 66, 13, 0*/  	YAHOO_SERVICE_REJECTCONTACT,  	YAHOO_SERVICE_GROUPRENAME = 0x89, /* > 1, 65(new), 66(0), 67(old) */ +	YAHOO_SERVICE_Y7_PING = 0x8A, /* 0 - id and that's it?? */  	YAHOO_SERVICE_CHATONLINE = 0x96, /* > 109(id), 1, 6(abcde) < 0,1*/  	YAHOO_SERVICE_CHATGOTO,  	YAHOO_SERVICE_CHATJOIN,	/* > 1 104-room 129-1600326591 62-2 */  	YAHOO_SERVICE_CHATLEAVE,  	YAHOO_SERVICE_CHATEXIT = 0x9b, +	YAHOO_SERVICE_CHATADDINVITE = 0x9d,  	YAHOO_SERVICE_CHATLOGOUT = 0xa0,  	YAHOO_SERVICE_CHATPING,  	YAHOO_SERVICE_COMMENT = 0xa8, @@ -208,7 +213,19 @@ enum yahoo_service { /* these are easier to see in hex */  	YAHOO_SERVICE_PICTURE_CHECKSUM = 0xbd,  	YAHOO_SERVICE_PICTURE = 0xbe,  	YAHOO_SERVICE_PICTURE_UPDATE = 0xc1, -	YAHOO_SERVICE_PICTURE_UPLOAD = 0xc2 +	YAHOO_SERVICE_PICTURE_UPLOAD = 0xc2, +	YAHOO_SERVICE_Y6_VISIBILITY=0xc5, +	YAHOO_SERVICE_Y6_STATUS_UPDATE=0xc6, +	YAHOO_PHOTOSHARE_INIT=0xd2,	 +	YAHOO_SERVICE_CONTACT_YMSG13=0xd6, +	YAHOO_PHOTOSHARE_PREV=0xd7, +	YAHOO_PHOTOSHARE_KEY=0xd8, +	YAHOO_PHOTOSHARE_TRANS=0xda, +	YAHOO_FILE_TRANSFER_INIT_YMSG13=0xdc, +	YAHOO_FILE_TRANSFER_GET_YMSG13=0xdd, +	YAHOO_FILE_TRANSFER_PUT_YMSG13=0xde, +	YAHOO_SERVICE_YMSG15_STATUS=0xf0, +	YAHOO_SERVICE_YMSG15_BUDDY_LIST=0xf1,  };  struct yahoo_pair { @@ -732,7 +749,7 @@ static void yahoo_send_packet(struct yahoo_input_data *yid, struct yahoo_packet  	data = y_new0(unsigned char, len + 1);  	memcpy(data + pos, "YMSG", 4); pos += 4; -	pos += yahoo_put16(data + pos, 0x000c); +	pos += yahoo_put16(data + pos, YAHOO_PROTO_VER);  	pos += yahoo_put16(data + pos, 0x0000);  	pos += yahoo_put16(data + pos, pktlen + extra_pad);  	pos += yahoo_put16(data + pos, pkt->service); @@ -746,7 +763,7 @@ static void yahoo_send_packet(struct yahoo_input_data *yid, struct yahoo_packet  	if( yid->type == YAHOO_CONNECTION_FT )  		yahoo_send_data(yid->fd, data, len);  	else -	yahoo_add_to_send_queue(yid, data, len); +		yahoo_add_to_send_queue(yid, data, len);  	FREE(data);  } @@ -837,55 +854,6 @@ static int is_same_bud(const void * a, const void * b) {  	return strcmp(subject->id, object->id);  } -static YList * bud_str2list(char *rawlist) -{ -	YList * l = NULL; - -	char **lines; -	char **split; -	char **buddies; -	char **tmp, **bud; - -	lines = y_strsplit(rawlist, "\n", -1); -	for (tmp = lines; *tmp; tmp++) { -		struct yahoo_buddy *newbud; - -		split = y_strsplit(*tmp, ":", 2); -		if (!split) -			continue; -		if (!split[0] || !split[1]) { -			y_strfreev(split); -			continue; -		} -		buddies = y_strsplit(split[1], ",", -1); - -		for (bud = buddies; bud && *bud; bud++) { -			newbud = y_new0(struct yahoo_buddy, 1); -			newbud->id = strdup(*bud); -			newbud->group = strdup(split[0]); - -			if(y_list_find_custom(l, newbud, is_same_bud)) { -				FREE(newbud->id); -				FREE(newbud->group); -				FREE(newbud); -				continue; -			} - -			newbud->real_name = NULL; - -			l = y_list_append(l, newbud); - -			NOTICE(("Added buddy %s to group %s", newbud->id, newbud->group)); -		} - -		y_strfreev(buddies); -		y_strfreev(split); -	} -	y_strfreev(lines); - -	return l; -} -  static char * getcookie(char *rawcookie)  {  	char * cookie=NULL; @@ -1342,134 +1310,150 @@ static void yahoo_process_message(struct yahoo_input_data *yid, struct yahoo_pac  	y_list_free(messages);  } - -static void yahoo_process_status(struct yahoo_input_data *yid, struct yahoo_packet *pkt) +static void yahoo_process_status(struct yahoo_input_data *yid, +	struct yahoo_packet *pkt)  {  	YList *l;  	struct yahoo_data *yd = yid->yd; -	struct user -	{ -		char *name;	/* 7	name */ -		int   state;	/* 10	state */ -		int   flags;	/* 13	flags, bit 0 = pager, bit 1 = chat, bit 2 = game */ -		int   mobile;	/* 60	mobile */ -		char *msg;	/* 19	custom status message */ -		int   away;	/* 47	away (or invisible)*/ -		int   buddy_session;	/* 11	state */ -		int   f17;	/* 17	in chat? then what about flags? */ -		int   idle;	/* 137	seconds idle */ -		int   f138;	/* 138	state */ -		char *f184;	/* 184	state */ -		int   f192;	/* 192	state */ -		int   f10001;	/* 10001	state */ -		int   f10002;	/* 10002	state */ -		int   f198;	/* 198	state */ -		char *f197;	/* 197	state */ -		char *f205;	/* 205	state */ -		int   f213;	/* 213	state */ -	} *u; +	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); +		YAHOO_CALLBACK(ext_yahoo_login_response) (yd->client_id, +			YAHOO_LOGIN_DUPL, NULL);  		return;  	} +	/* Status updates may be spread accross 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 0: /* we won't actually do anything with this */ +		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) { +				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. */ +		case 1:	/* we don't get the full buddy list here. */  			if (!yd->logged_in) { -				yd->logged_in = TRUE; -				if(yd->current_status < 0) +				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_CALLBACK(ext_yahoo_login_response) (yd-> +					client_id, YAHOO_LOGIN_OK, NULL);  			}  			break; -		case 8: /* how many online buddies we have */ +		case 8:	/* how many online buddies we have */  			NOTICE(("key %d:%s", pair->key, pair->value));  			break; -		case 7: /* the current buddy */ -			u = y_new0(struct user, 1); +		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; -			users = y_list_prepend(users, u);  			break; -		case 10: /* state */ -			((struct user*)users->data)->state = strtol(pair->value, NULL, 10); +		case 10:	/* state */ +			u->state = strtol(pair->value, NULL, 10);  			break; -		case 19: /* custom status message */ -			((struct user*)users->data)->msg = pair->value; +		case 19:	/* custom status message */ +			u->msg = pair->value;  			break; -		case 47: /* is it an away message or not */ -			((struct user*)users->data)->away = atoi(pair->value); +		case 47:	/* is it an away message or not. Not applicable for YMSG16 anymore */ +			u->away = atoi(pair->value);  			break; -		case 137: /* seconds idle */ -			((struct user*)users->data)->idle = atoi(pair->value); +		case 137:	/* seconds idle */ +			u->idle = atoi(pair->value);  			break; -		case 11: /* this is the buddy's session id */ -			((struct user*)users->data)->buddy_session = atoi(pair->value); +		case 11:	/* this is the buddy's session id */ +			u->buddy_session = atoi(pair->value);  			break; -		case 17: /* in chat? */ -			((struct user*)users->data)->f17 = atoi(pair->value); +		case 17:	/* in chat? */ +			u->f17 = atoi(pair->value);  			break; -		case 13: /* bitmask, bit 0 = pager, bit 1 = chat, bit 2 = game */ -			((struct user*)users->data)->flags = atoi(pair->value); +		case 13:	/* bitmask, bit 0 = pager, bit 1 = chat, bit 2 = game */ +			u->flags = atoi(pair->value);  			break; -		case 60: /* SMS -> 1 MOBILE USER */ +		case 60:	/* SMS -> 1 MOBILE USER */  			/* sometimes going offline makes this 2, but invisible never sends it */ -			((struct user*)users->data)->mobile = atoi(pair->value); +			u->mobile = atoi(pair->value);  			break;  		case 138: -			((struct user*)users->data)->f138 = atoi(pair->value); +			u->f138 = atoi(pair->value);  			break;  		case 184: -			((struct user*)users->data)->f184 = pair->value; +			u->f184 = pair->value;  			break;  		case 192: -			((struct user*)users->data)->f192 = atoi(pair->value); +			u->f192 = atoi(pair->value);  			break;  		case 10001: -			((struct user*)users->data)->f10001 = atoi(pair->value); +			u->f10001 = atoi(pair->value);  			break;  		case 10002: -			((struct user*)users->data)->f10002 = atoi(pair->value); +			u->f10002 = atoi(pair->value);  			break;  		case 198: -			((struct user*)users->data)->f198 = atoi(pair->value); +			u->f198 = atoi(pair->value);  			break;  		case 197: -			((struct user*)users->data)->f197 = pair->value; +			u->f197 = pair->value;  			break;  		case 205: -			((struct user*)users->data)->f205 = pair->value; +			u->f205 = pair->value;  			break;  		case 213: -			((struct user*)users->data)->f213 = atoi(pair->value); +			u->f213 = atoi(pair->value);  			break; -		case 16: /* Custom error message */ -			YAHOO_CALLBACK(ext_yahoo_error)(yd->client_id, pair->value, 0, E_CUSTOM); +		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)); +			WARNING(("unknown status key %d:%s", pair->key, +					pair->value));  			break;  		}  	} -	 +  	while (users) {  		YList *t = users; -		struct user *u = users->data; +		struct yahoo_process_status_entry *u = users->data;  		if (u->name != NULL) { -			if (pkt->service == YAHOO_SERVICE_LOGOFF || u->flags == 0) { -				YAHOO_CALLBACK(ext_yahoo_status_changed)(yd->client_id, u->name, YAHOO_STATUS_OFFLINE, NULL, 1, 0, 0); +			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 { -				YAHOO_CALLBACK(ext_yahoo_status_changed)(yd->client_id, u->name, u->state, u->msg, u->away, u->idle, u->mobile); +				/* 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);  			}  		} @@ -1479,88 +1463,130 @@ static void yahoo_process_status(struct yahoo_input_data *yid, struct yahoo_pack  	}  } -static void yahoo_process_list(struct yahoo_input_data *yid, struct yahoo_packet *pkt) +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; -	if (!yd->logged_in) { -		yd->logged_in = TRUE; -		if(yd->current_status < 0) -			yd->current_status = yd->initial_status; -		YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, YAHOO_LOGIN_OK, 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 87: /* buddies */ -			if(!yd->rawbuddylist) -				yd->rawbuddylist = strdup(pair->value); -			else { -				yd->rawbuddylist = y_string_append(yd->rawbuddylist, pair->value); -			} +		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); -		case 88: /* ignore list */ -			if(!yd->ignorelist) -				yd->ignorelist = strdup("Ignore:"); -			yd->ignorelist = y_string_append(yd->ignorelist, pair->value);  			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); -		case 89: /* identities */ +	/* 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,  +				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); +				y_strfreev(identities);  			} -			YAHOO_CALLBACK(ext_yahoo_got_identities)(yd->client_id, yd->identities); +			YAHOO_CALLBACK(ext_yahoo_got_identities) (yd->client_id, +				yd->identities);  			break; -		case 59: /* cookies */ -			if(yd->ignorelist) { -				yd->ignore = bud_str2list(yd->ignorelist); -				FREE(yd->ignorelist); -				YAHOO_CALLBACK(ext_yahoo_got_ignore)(yd->client_id, yd->ignore); -			} -			if(yd->rawbuddylist) { -				yd->buddies = bud_str2list(yd->rawbuddylist); -				FREE(yd->rawbuddylist); -				YAHOO_CALLBACK(ext_yahoo_got_buddies)(yd->client_id, yd->buddies); -			} - -			if(pair->value[0]=='Y') { +		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') { +			} else if (pair->value[0] == 'T') {  				FREE(yd->cookie_t);  				yd->cookie_t = getcookie(pair->value); -			} else if(pair->value[0]=='C') { +			} else if (pair->value[0] == 'C') {  				FREE(yd->cookie_c);  				yd->cookie_c = getcookie(pair->value); -			}  - -			if(yd->cookie_y && yd->cookie_t && yd->cookie_c) -				YAHOO_CALLBACK(ext_yahoo_got_cookies)(yd->client_id); +			}  			break; -		case 3: /* my id */ -		case 90: /* 1 */ -		case 100: /* 0 */ -		case 101: /* NULL */ -		case 102: /* NULL */ -		case 93: /* 86400/1440 */ +		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) @@ -2225,6 +2251,204 @@ static void yahoo_process_auth_0x0b(struct yahoo_input_data *yid, const char *se  	free(crypt_hash);  } +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 YAHOO_LOGIN_PASSWD; +		case 1213: return YAHOO_LOGIN_LOCK; +		case 1235: return YAHOO_LOGIN_UNAME; +		default: return (enum yahoo_status) code; +	} +} + +static void yahoo_process_auth_0x10(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; +	struct http_request *req; +	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); +	 +	req = 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; +	} +	 +	return yahoo_https_auth_init(had); +	 +fail: +	g_free(had->token); +	g_free(had->chal); +	g_free(had); +} + +static void yahoo_https_auth_init(struct yahoo_https_auth_data *had) +{ +	struct http_request *req; +	char *url; +	 +	url = g_strdup_printf("https://login.yahoo.com/config/pwtoken_login?src=ymsgr&ts=%d&token=%s", +	                      (int) time(NULL), had->token); +	 +	req = 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; @@ -2253,6 +2477,9 @@ static void yahoo_process_auth(struct yahoo_input_data *yid, struct yahoo_packet  		case 1:  			yahoo_process_auth_0x0b(yid, seed, sn);  			break; +		case 2: +			yahoo_process_auth_0x10(yid, seed, sn); +			break;  		default:  			/* call error */  			WARNING(("unknown auth type %d", m)); @@ -2407,7 +2634,7 @@ static void yahoo_process_buddyadd(struct yahoo_input_data *yid, struct yahoo_pa  		bud->real_name = NULL;  		yd->buddies = y_list_append(yd->buddies, bud); -		 +	  		/* Possibly called already, but at least the call above doesn't  		   seem to happen every time (not anytime I tried). */  		YAHOO_CALLBACK(ext_yahoo_contact_added)(yd->client_id, me, who, NULL); @@ -2416,6 +2643,26 @@ static void yahoo_process_buddyadd(struct yahoo_input_data *yid, struct yahoo_pa  /*	YAHOO_CALLBACK(ext_yahoo_status_changed)(yd->client_id, who, status, NULL, (status==YAHOO_STATUS_AVAILABLE?0:1)); */  } +static void yahoo_process_contact_ymsg13(struct yahoo_input_data *yid, struct yahoo_packet *pkt) +{ +	char* who=NULL; +	char* me=NULL;	 +	char* msg=NULL; +	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 +			DEBUG_MSG(("unknown key: %d = %s", pair->key, pair->value)); +	} + +	if(pkt->status==3) +		YAHOO_CALLBACK(ext_yahoo_contact_auth_request)(yid->yd->client_id, me, who, msg); +} +  static void yahoo_process_buddydel(struct yahoo_input_data *yid, struct yahoo_packet *pkt)  {  	struct yahoo_data *yd = yid->yd; @@ -2627,7 +2874,7 @@ static void yahoo_process_webcam_key(struct yahoo_input_data *yid, struct yahoo_  	char *who = NULL;  	YList *l; -	yahoo_dump_unhandled(pkt); +	// yahoo_dump_unhandled(pkt);  	for (l = pkt->hash; l; l = l->next) {  		struct yahoo_pair *pair = l->data;  		if (pair->key == 5) @@ -2649,6 +2896,7 @@ static void yahoo_process_webcam_key(struct yahoo_input_data *yid, struct yahoo_  static void yahoo_packet_process(struct yahoo_input_data *yid, struct yahoo_packet *pkt)  {  	DEBUG_MSG(("yahoo_packet_process: 0x%02x", pkt->service)); +	yahoo_dump_unhandled(pkt);  	switch (pkt->service)  	{  	case YAHOO_SERVICE_USERSTAT: @@ -2660,6 +2908,8 @@ static void yahoo_packet_process(struct yahoo_input_data *yid, struct yahoo_pack  	case YAHOO_SERVICE_GAMELOGOFF:  	case YAHOO_SERVICE_IDACT:  	case YAHOO_SERVICE_IDDEACT: +	case YAHOO_SERVICE_Y6_STATUS_UPDATE: +	case YAHOO_SERVICE_YMSG15_STATUS:  		yahoo_process_status(yid, pkt);  		break;  	case YAHOO_SERVICE_NOTIFY: @@ -2673,6 +2923,7 @@ static void yahoo_packet_process(struct yahoo_input_data *yid, struct yahoo_pack  	case YAHOO_SERVICE_NEWMAIL:  		yahoo_process_mail(yid, pkt);  		break; +	case YAHOO_SERVICE_REJECTCONTACT:  	case YAHOO_SERVICE_NEWCONTACT:  		yahoo_process_contact(yid, pkt);  		break; @@ -2713,6 +2964,9 @@ static void yahoo_packet_process(struct yahoo_input_data *yid, struct yahoo_pack  	case YAHOO_SERVICE_ADDBUDDY:  		yahoo_process_buddyadd(yid, pkt);  		break; +	case YAHOO_SERVICE_CONTACT_YMSG13: +		yahoo_process_contact_ymsg13(yid,pkt); +		break;  	case YAHOO_SERVICE_REMBUDDY:  		yahoo_process_buddydel(yid, pkt);  		break; @@ -2741,7 +2995,6 @@ static void yahoo_packet_process(struct yahoo_input_data *yid, struct yahoo_pack  	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); @@ -2755,6 +3008,8 @@ static void yahoo_packet_process(struct yahoo_input_data *yid, struct yahoo_pack  	case YAHOO_SERVICE_PICTURE_UPLOAD:  		yahoo_process_picture_upload(yid, pkt);  		break;	 +	case YAHOO_SERVICE_YMSG15_BUDDY_LIST:	/* Buddy List */ +		yahoo_process_buddy_list(yid, pkt);  	default:  		WARNING(("unknown service 0x%02x", pkt->service));  		yahoo_dump_unhandled(pkt); @@ -3538,7 +3793,7 @@ static void (*yahoo_process_connection[])(struct yahoo_input_data *, int over) =  	yahoo_process_webcam_master_connection,  	yahoo_process_webcam_connection,  	yahoo_process_chatcat_connection, -	yahoo_process_search_connection +	yahoo_process_search_connection,  };  int yahoo_read_ready(int id, int fd, void *data) @@ -3556,7 +3811,7 @@ int yahoo_read_ready(int id, int fd, void *data)  		len = read(fd, buf, sizeof(buf));  	} while(len == -1 && errno == EINTR); -	if(len == -1 && errno == EAGAIN)	/* we'll try again later */ +	if(len == -1 && (errno == EAGAIN||errno == EINTR))	/* we'll try again later */  		return 1;  	if (len <= 0) { @@ -3759,7 +4014,7 @@ void yahoo_send_typing(int id, const char *from, const char *who, int typ)  	pkt = yahoo_packet_new(YAHOO_SERVICE_NOTIFY, YAHOO_STATUS_NOTIFY, yd->session_id);  	yahoo_packet_hash(pkt, 5, who); -	yahoo_packet_hash(pkt, 4, from?from:yd->user); +	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"); @@ -3774,46 +4029,40 @@ 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 service; +	int old_status;  	char s[4];  	if(!yid)  		return;  	yd = yid->yd; +	old_status = yd->current_status; +	yd->current_status = state; -	if (msg) { -		yd->current_status = YAHOO_STATUS_CUSTOM; -	} else { -		yd->current_status = state; -	} +	/* Thank you libpurple :) */ +	if (yd->current_status == YAHOO_STATUS_INVISIBLE) { +		pkt = yahoo_packet_new(YAHOO_SERVICE_Y6_VISIBILITY, YAHOO_STATUS_AVAILABLE, 0); +		yahoo_packet_hash(pkt, 13, "2"); +		yahoo_send_packet(yid, pkt, 0); +		yahoo_packet_free(pkt); -	if (yd->current_status == YAHOO_STATUS_AVAILABLE) -		service = YAHOO_SERVICE_ISBACK; -	else -		service = YAHOO_SERVICE_ISAWAY; -	  -	if ((away == 2) && (yd->current_status == YAHOO_STATUS_AVAILABLE)) { -		pkt = yahoo_packet_new(YAHOO_SERVICE_ISAWAY, YAHOO_STATUS_BRB, yd->session_id); -		yahoo_packet_hash(pkt, 10, "999"); -		yahoo_packet_hash(pkt, 47, "2"); -	}else { -		pkt = yahoo_packet_new(service, YAHOO_STATUS_AVAILABLE, yd->session_id); -		snprintf(s, sizeof(s), "%d", yd->current_status); -		yahoo_packet_hash(pkt, 10, s); -		if (yd->current_status == YAHOO_STATUS_CUSTOM) { -			yahoo_packet_hash(pkt, 19, msg); -			yahoo_packet_hash(pkt, 47, (away == 2)? "2": (away) ?"1":"0"); -		} else { -			yahoo_packet_hash(pkt, 47, (away == 2)? "2": (away) ?"1":"0"); -		} -		 -		 -		 +		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_VISIBILITY, 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) @@ -3828,7 +4077,10 @@ void yahoo_logoff(int id)  	LOG(("yahoo_logoff: current status: %d", yd->current_status)); -	if(yd->current_status != -1) { +	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, YAHOO_STATUS_AVAILABLE, yd->session_id);  		yd->current_status = -1; @@ -4061,12 +4313,24 @@ void yahoo_add_buddy(int id, const char *who, const char *group, const char *msg  	if (!yd->logged_in)  		return; -	pkt = yahoo_packet_new(YAHOO_SERVICE_ADDBUDDY, YAHOO_STATUS_AVAILABLE, yd->session_id); -	yahoo_packet_hash(pkt, 1, yd->user); -	yahoo_packet_hash(pkt, 7, who); -	yahoo_packet_hash(pkt, 65, group); +	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);  } @@ -4090,6 +4354,49 @@ void yahoo_remove_buddy(int id, const char *who, const char *group)  	yahoo_packet_free(pkt);  } +void yahoo_accept_buddy_ymsg13(int id,const char* me,const char* who){ +	struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); +	struct yahoo_data *yd; + +	if(!yid) +		return; +	yd = yid->yd; + +	struct yahoo_packet* pkt=NULL; +	pkt= yahoo_packet_new(YAHOO_SERVICE_CONTACT_YMSG13,YAHOO_STATUS_AVAILABLE,0); + +	yahoo_packet_hash(pkt,1,me ?: yd->user);	 +	yahoo_packet_hash(pkt,5,who); +	yahoo_packet_hash(pkt,13,"1"); +	yahoo_packet_hash(pkt,334,"0"); +	yahoo_send_packet(yid, pkt, 0); +	yahoo_packet_free(pkt); +} + +void yahoo_reject_buddy_ymsg13(int id,const char* me,const char* who,const char* msg){ +	struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); +	struct yahoo_data *yd; + +	if(!yid) +		return; +	yd = yid->yd; + +	struct yahoo_packet* pkt=NULL; +	pkt= yahoo_packet_new(YAHOO_SERVICE_CONTACT_YMSG13,YAHOO_STATUS_AVAILABLE,0); + +	yahoo_packet_hash(pkt,1,me ?: yd->user);	 +	yahoo_packet_hash(pkt,5,who); +//	yahoo_packet_hash(pkt,241,YAHOO_PROTO_VER); +	yahoo_packet_hash(pkt,13,"2"); +	yahoo_packet_hash(pkt,334,"0"); +	yahoo_packet_hash(pkt,97,"1"); +	yahoo_packet_hash(pkt,14,msg?:""); + +	yahoo_send_packet(yid, pkt, 0); +	yahoo_packet_free(pkt); + +} +  void yahoo_reject_buddy(int id, const char *who, const char *msg)  {  	struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER); diff --git a/protocols/yahoo/yahoo.c b/protocols/yahoo/yahoo.c index 197d76a1..a47de966 100644 --- a/protocols/yahoo/yahoo.c +++ b/protocols/yahoo/yahoo.c @@ -129,6 +129,8 @@ static char *byahoo_strip( const char *in )  static void byahoo_init( account_t *acc )  {  	set_add( &acc->set, "mail_notifications", "false", set_eval_bool, acc ); +	 +	acc->flags |= ACC_FLAG_AWAY_MESSAGE | ACC_FLAG_STATUS_MESSAGE;  }  static void byahoo_login( account_t *acc ) @@ -197,27 +199,11 @@ static void byahoo_set_away( struct im_connection *ic, char *state, char *msg )  {  	struct byahoo_data *yd = (struct byahoo_data *) ic->proto_data; -	ic->away = NULL; -	 -	if( state && msg && g_strcasecmp( state, msg ) != 0 ) -	{ -		yd->current_status = YAHOO_STATUS_CUSTOM; -		ic->away = ""; -	} -	else if( state ) +	if( state && msg == NULL )  	{ -		/* Set msg to NULL since (if it isn't NULL already) it's equal -		   to state. msg must be empty if we want to use an existing -		   away state. */ -		msg = NULL; -		 -		ic->away = ""; -		if( g_strcasecmp( state, "Available" ) == 0 ) -		{ -			yd->current_status = YAHOO_STATUS_AVAILABLE; -			ic->away = NULL; -		} -		else if( g_strcasecmp( state, "Be Right Back" ) == 0 ) +		/* Use these states only if msg doesn't contain additional +		   info since away messages are only supported with CUSTOM. */ +		if( g_strcasecmp( state, "Be Right Back" ) == 0 )  			yd->current_status = YAHOO_STATUS_BRB;  		else if( g_strcasecmp( state, "Busy" ) == 0 )  			yd->current_status = YAHOO_STATUS_BUSY; @@ -237,35 +223,34 @@ static void byahoo_set_away( struct im_connection *ic, char *state, char *msg )  			yd->current_status = YAHOO_STATUS_STEPPEDOUT;  		else if( g_strcasecmp( state, "Invisible" ) == 0 )  			yd->current_status = YAHOO_STATUS_INVISIBLE; -		else if( g_strcasecmp( state, GAIM_AWAY_CUSTOM ) == 0 ) -		{ -			yd->current_status = YAHOO_STATUS_AVAILABLE; -			 -			ic->away = NULL; -		} +		else +			yd->current_status = YAHOO_STATUS_CUSTOM;  	} +	else if( state ) +		yd->current_status = YAHOO_STATUS_CUSTOM;  	else  		yd->current_status = YAHOO_STATUS_AVAILABLE; -	yahoo_set_away( yd->y2_id, yd->current_status, msg, ic->away != NULL ? 2 : 0 ); +	yahoo_set_away( yd->y2_id, yd->current_status, msg, state ? 2 : 0 );  }  static GList *byahoo_away_states( struct im_connection *ic )  { -	GList *m = NULL; - -	m = g_list_append( m, "Available" ); -	m = g_list_append( m, "Be Right Back" ); -	m = g_list_append( m, "Busy" ); -	m = g_list_append( m, "Not At Home" ); -	m = g_list_append( m, "Not At Desk" ); -	m = g_list_append( m, "Not In Office" ); -	m = g_list_append( m, "On Phone" ); -	m = g_list_append( m, "On Vacation" ); -	m = g_list_append( m, "Out To Lunch" ); -	m = g_list_append( m, "Stepped Out" ); -	m = g_list_append( m, "Invisible" ); -	m = g_list_append( m, GAIM_AWAY_CUSTOM ); +	static GList *m = NULL; + +	if( m == NULL ) +	{ +		m = g_list_append( m, "Be Right Back" ); +		m = g_list_append( m, "Busy" ); +		m = g_list_append( m, "Not At Home" ); +		m = g_list_append( m, "Not At Desk" ); +		m = g_list_append( m, "Not In Office" ); +		m = g_list_append( m, "On Phone" ); +		m = g_list_append( m, "On Vacation" ); +		m = g_list_append( m, "Out To Lunch" ); +		m = g_list_append( m, "Stepped Out" ); +		m = g_list_append( m, "Invisible" ); +	}  	return m;  } @@ -346,6 +331,20 @@ static struct groupchat *byahoo_chat_with( struct im_connection *ic, char *who )  	return c;  } +static void byahoo_auth_allow( struct im_connection *ic, const char *who ) +{ +	struct byahoo_data *yd = (struct byahoo_data *) ic->proto_data; +	 +	yahoo_accept_buddy_ymsg13( yd->y2_id, NULL, who ); +} + +static void byahoo_auth_deny( struct im_connection *ic, const char *who ) +{ +	struct byahoo_data *yd = (struct byahoo_data *) ic->proto_data; +	 +	yahoo_reject_buddy_ymsg13( yd->y2_id, NULL, who, NULL ); +} +  void byahoo_initmodule( )  {  	struct prpl *ret = g_new0(struct prpl, 1); @@ -371,6 +370,9 @@ void byahoo_initmodule( )  	ret->handle_cmp = g_strcasecmp; +	ret->auth_allow = byahoo_auth_allow; +	ret->auth_deny = byahoo_auth_deny; +	  	register_protocol(ret);  } @@ -450,9 +452,7 @@ gboolean byahoo_write_ready_callback( gpointer data, gint source, b_input_condit  {  	struct byahoo_write_ready_data *d = data; -	yahoo_write_ready( d->id, d->fd, d->data ); -	 -	return FALSE; +	return yahoo_write_ready( d->id, d->fd, d->data );  }  void ext_yahoo_login_response( int id, int succ, const char *url ) @@ -664,9 +664,6 @@ void ext_yahoo_error( int id, const char *err, int fatal, int num )  	struct im_connection *ic = byahoo_get_ic_by_id( id );  	imcb_error( ic, "%s", err ); -	 -	if( fatal ) -		imc_logout( ic, TRUE );  }  /* TODO: Clear up the mess of inp and d structures */ @@ -792,9 +789,22 @@ int ext_yahoo_connect(const char *host, int port)  static void byahoo_accept_conf( void *data )  {  	struct byahoo_conf_invitation *inv = data; +	struct groupchat *b; +	 +	for( b = inv->ic->groupchats; b; b = b->next ) +		if( b == inv->c ) +			break; +	 +	if( b != NULL ) +	{ +		yahoo_conference_logon( inv->yid, NULL, inv->members, inv->name ); +		imcb_chat_add_buddy( inv->c, inv->ic->acc->user ); +	} +	else +	{ +		imcb_log( inv->ic, "Duplicate/corrupted invitation to `%s'.", inv->name ); +	} -	yahoo_conference_logon( inv->yid, NULL, inv->members, inv->name ); -	imcb_chat_add_buddy( inv->c, inv->ic->acc->user );  	g_free( inv->name );  	g_free( inv );  } @@ -910,11 +920,18 @@ void ext_yahoo_chat_yahooerror( int id, const char *me )  {  } +void ext_yahoo_contact_auth_request( int id, const char *myid, const char *who, const char *msg ) +{ +	struct im_connection *ic = byahoo_get_ic_by_id( id ); +	 +	imcb_ask_auth( ic, who, NULL ); +} +  void ext_yahoo_contact_added( int id, const char *myid, const char *who, const char *msg )  { -	/* Groups schmoups. If I want to handle groups properly I can get the -	   buddy data from some internal libyahoo2 structure. */ -	imcb_add_buddy( byahoo_get_ic_by_id( id ), (char*) who, NULL ); +	struct im_connection *ic = byahoo_get_ic_by_id( id ); +	 +	imcb_add_buddy( ic, (char*) who, NULL );  }  void ext_yahoo_rejected( int id, const char *who, const char *msg ) diff --git a/protocols/yahoo/yahoo2.h b/protocols/yahoo/yahoo2.h index e54e09fb..2184a321 100644 --- a/protocols/yahoo/yahoo2.h +++ b/protocols/yahoo/yahoo2.h @@ -216,6 +216,9 @@ const char  * yahoo_get_profile_url( void );  void yahoo_buddyicon_request(int id, const char *who); +void yahoo_accept_buddy_ymsg13(int,const char*,const char*); +void yahoo_reject_buddy_ymsg13(int,const char*,const char*,const char*); +  #include "yahoo_httplib.h"  #ifdef __cplusplus diff --git a/protocols/yahoo/yahoo2_callbacks.h b/protocols/yahoo/yahoo2_callbacks.h index b7f4e99b..e2c8ea42 100644 --- a/protocols/yahoo/yahoo2_callbacks.h +++ b/protocols/yahoo/yahoo2_callbacks.h @@ -360,6 +360,18 @@ void YAHOO_CALLBACK_TYPE(ext_yahoo_got_file)(int id, const char *me, const char  /* + * Name: ext_yahoo_contact_auth_request + * 	Called when a contact wants to add you to his/her contact list + * Params: + * 	id   - the id that identifies the server connection + * 	myid - the identity s/he added + * 	who  - who did it + * 	msg  - any message sent + */ +void YAHOO_CALLBACK_TYPE(ext_yahoo_contact_auth_request)(int id, const char *myid, const char *who, const char *msg); + + +/*   * Name: ext_yahoo_contact_added   * 	Called when a contact is added to your list   * Params: diff --git a/protocols/yahoo/yahoo2_types.h b/protocols/yahoo/yahoo2_types.h index df1756eb..f05acb3c 100644 --- a/protocols/yahoo/yahoo2_types.h +++ b/protocols/yahoo/yahoo2_types.h @@ -56,7 +56,20 @@ enum yahoo_login_status {  	YAHOO_LOGIN_PASSWD = 13,  	YAHOO_LOGIN_LOCK = 14,  	YAHOO_LOGIN_DUPL = 99, -	YAHOO_LOGIN_SOCK = -1 +	YAHOO_LOGIN_SOCK = -1, +}; + +enum ypacket_status { +	YPACKET_STATUS_DISCONNECTED = -1, +	YPACKET_STATUS_DEFAULT = 0, +	YPACKET_STATUS_SERVERACK = 1, +	YPACKET_STATUS_GAME     = 0x2, +	YPACKET_STATUS_AWAY     = 0x4, +	YPACKET_STATUS_CONTINUED = 0x5, +	YPACKET_STATUS_INVISIBLE = 12, +	YPACKET_STATUS_NOTIFY = 0x16, /* TYPING */ +	YPACKET_STATUS_WEBLOGIN = 0x5a55aa55, +	YPACKET_STATUS_OFFLINE = 0x5a55aa56  };  enum yahoo_error { @@ -84,7 +97,7 @@ enum yahoo_log_level {  	YAHOO_LOG_DEBUG  }; -#define YAHOO_PROTO_VER 0x000b +#define YAHOO_PROTO_VER 0x0010  /* Yahoo style/color directives */  #define YAHOO_COLOR_BLACK "\033[30m" @@ -114,7 +127,8 @@ enum yahoo_connection_type {  	YAHOO_CONNECTION_WEBCAM_MASTER,  	YAHOO_CONNECTION_WEBCAM,  	YAHOO_CONNECTION_CHATCAT, -	YAHOO_CONNECTION_SEARCH +	YAHOO_CONNECTION_SEARCH, +	YAHOO_CONNECTION_AUTH,  };  enum yahoo_webcam_direction_type { @@ -131,7 +145,6 @@ enum yahoo_stealth_visibility_type {  /* chat member attribs */  #define YAHOO_CHAT_MALE 0x8000  #define YAHOO_CHAT_FEMALE 0x10000 -#define YAHOO_CHAT_FEMALE 0x10000  #define YAHOO_CHAT_DUNNO 0x400  #define YAHOO_CHAT_WEBCAM 0x10 @@ -182,6 +195,8 @@ struct yahoo_data {  	char  *ignorelist;  	void  *server_settings; +	 +	struct yahoo_process_status_entry *half_user;  };  struct yab { @@ -247,6 +262,27 @@ struct yahoo_chat_member {  	char *location;  }; +struct yahoo_process_status_entry { +	char *name;	/* 7      name */ +	int state;	/* 10     state */ +	int flags;	/* 13     flags, bit 0 = pager, bit 1 = chat, bit 2 = game */ +	int mobile;	/* 60     mobile */ +	char *msg;	/* 19     custom status message */ +	int away;	/* 47     away (or invisible) */ +	int buddy_session; /* 11  state */ +	int f17;	/* 17     in chat? then what about flags? */ +	int idle;	/* 137    seconds idle */ +	int f138;	/* 138    state */ +	char *f184;	/* 184    state */ +	int f192;	/* 192    state */ +	int f10001;	/* 10001  state */ +	int f10002;	/* 10002  state */ +	int f198;	/* 198    state */ +	char *f197;	/* 197    state */ +	char *f205;	/* 205    state */ +	int f213;	/* 213    state */ +}; +  #ifdef __cplusplus  }  #endif | 
