aboutsummaryrefslogtreecommitdiffstats
path: root/protocols/yahoo/libyahoo2.c
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/yahoo/libyahoo2.c')
-rw-r--r--protocols/yahoo/libyahoo2.c725
1 files changed, 516 insertions, 209 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);