Ignore:
Timestamp:
2008-04-02T14:22:57Z (16 years ago)
Author:
Jelmer Vernooij <jelmer@…>
Branches:
master
Children:
f9dbc99
Parents:
875ad42 (diff), dd34575 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge trunk.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • protocols/yahoo/libyahoo2.c

    r875ad42 r85d7b85  
    7474#include <ctype.h>
    7575
    76 #include "sha.h"
     76#include "sha1.h"
    7777#include "md5.h"
    7878#include "yahoo2.h"
     
    8888#endif
    8989
     90#include "base64.h"
     91
    9092#ifdef USE_STRUCT_CALLBACKS
    9193struct yahoo_callbacks *yc=NULL;
     
    100102#define YAHOO_CALLBACK(x)       x
    101103#endif
     104
     105static int yahoo_send_data(int fd, void *data, int len);
    102106
    103107int yahoo_log_message(char * fmt, ...)
     
    200204        YAHOO_SERVICE_CHATLOGOUT = 0xa0,
    201205        YAHOO_SERVICE_CHATPING,
    202         YAHOO_SERVICE_COMMENT = 0xa8
     206        YAHOO_SERVICE_COMMENT = 0xa8,
     207        YAHOO_SERVICE_STEALTH = 0xb9,
     208        YAHOO_SERVICE_PICTURE_CHECKSUM = 0xbd,
     209        YAHOO_SERVICE_PICTURE = 0xbe,
     210        YAHOO_SERVICE_PICTURE_UPDATE = 0xc1,
     211        YAHOO_SERVICE_PICTURE_UPLOAD = 0xc2
    203212};
    204213
     
    693702}
    694703
    695 static char base64digits[] =    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    696                                 "abcdefghijklmnopqrstuvwxyz"
    697                                 "0123456789._";
     704/* raw bytes in quasi-big-endian order to base 64 string (NUL-terminated) */
    698705static void to_y64(unsigned char *out, const unsigned char *in, int inlen)
    699 /* raw bytes in quasi-big-endian order to base 64 string (NUL-terminated) */
    700 {
    701         for (; inlen >= 3; inlen -= 3)
    702                 {
    703                         *out++ = base64digits[in[0] >> 2];
    704                         *out++ = base64digits[((in[0]<<4) & 0x30) | (in[1]>>4)];
    705                         *out++ = base64digits[((in[1]<<2) & 0x3c) | (in[2]>>6)];
    706                         *out++ = base64digits[in[2] & 0x3f];
    707                         in += 3;
    708                 }
    709         if (inlen > 0)
    710                 {
    711                         unsigned char fragment;
    712 
    713                         *out++ = base64digits[in[0] >> 2];
    714                         fragment = (in[0] << 4) & 0x30;
    715                         if (inlen > 1)
    716                                 fragment |= in[1] >> 4;
    717                         *out++ = base64digits[fragment];
    718                         *out++ = (inlen < 2) ? '-'
    719                                         : base64digits[(in[1] << 2) & 0x3c];
    720                         *out++ = '-';
    721                 }
    722         *out = '\0';
     706{
     707        base64_encode_real(in, inlen, out, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._-");
    723708}
    724709
     
    750735
    751736        memcpy(data + pos, "YMSG", 4); pos += 4;
    752         pos += yahoo_put16(data + pos, 0x0a00);
     737        pos += yahoo_put16(data + pos, 0x000c);
    753738        pos += yahoo_put16(data + pos, 0x0000);
    754739        pos += yahoo_put16(data + pos, pktlen + extra_pad);
     
    761746        yahoo_packet_dump(data, len);
    762747       
     748        if( yid->type == YAHOO_CONNECTION_FT )
     749                yahoo_send_data(yid->fd, data, len);
     750        else
    763751        yahoo_add_to_send_queue(yid, data, len);
    764752        FREE(data);
     
    946934        char *msg = NULL;
    947935        char *from = NULL;
     936        char *to = NULL;
    948937        int stat = 0;
    949938        int accept = 0;
     
    954943                if (pair->key == 4)
    955944                        from = pair->value;
     945                if (pair->key == 5)
     946                        to = pair->value;
    956947                if (pair->key == 49)
    957948                        msg = pair->value;
     
    971962       
    972963        if (!strncasecmp(msg, "TYPING", strlen("TYPING")))
    973                 YAHOO_CALLBACK(ext_yahoo_typing_notify)(yd->client_id, from, stat);
     964                YAHOO_CALLBACK(ext_yahoo_typing_notify)(yd->client_id, to, from, stat);
    974965        else if (!strncasecmp(msg, "GAME", strlen("GAME")))
    975                 YAHOO_CALLBACK(ext_yahoo_game_notify)(yd->client_id, from, stat);
     966                YAHOO_CALLBACK(ext_yahoo_game_notify)(yd->client_id, to, from, stat);
    976967        else if (!strncasecmp(msg, "WEBCAMINVITE", strlen("WEBCAMINVITE")))
    977968        {
    978969                if (!strcmp(ind, " ")) {
    979                         YAHOO_CALLBACK(ext_yahoo_webcam_invite)(yd->client_id, from);
     970                        YAHOO_CALLBACK(ext_yahoo_webcam_invite)(yd->client_id, to, from);
    980971                } else {
    981972                        accept = atoi(ind);
     
    983974                        if (accept < 0)
    984975                                accept = 0;
    985                         YAHOO_CALLBACK(ext_yahoo_webcam_invite_reply)(yd->client_id, from, accept);
     976                        YAHOO_CALLBACK(ext_yahoo_webcam_invite_reply)(yd->client_id, to, from, accept);
    986977                }
    987978        }
     
    10421033        }
    10431034        if(url && from)
    1044                 YAHOO_CALLBACK(ext_yahoo_got_file)(yd->client_id, from, url, expires, msg, filename, filesize);
     1035                YAHOO_CALLBACK(ext_yahoo_got_file)(yd->client_id, to, from, url, expires, msg, filename, filesize);
    10451036
    10461037}
     
    11161107                        ;
    11171108                else if(members)
    1118                         YAHOO_CALLBACK(ext_yahoo_got_conf_invite)(yd->client_id, host, room, msg, members);
     1109                        YAHOO_CALLBACK(ext_yahoo_got_conf_invite)(yd->client_id, id, host, room, msg, members);
    11191110                else if(msg)
    1120                         YAHOO_CALLBACK(ext_yahoo_error)(yd->client_id, msg, 0);
     1111                        YAHOO_CALLBACK(ext_yahoo_error)(yd->client_id, msg, 0, E_CONFNOTAVAIL);
    11211112                break;
    11221113        case YAHOO_SERVICE_CONFADDINVITE:
     
    11241115                        ;
    11251116                else
    1126                         YAHOO_CALLBACK(ext_yahoo_got_conf_invite)(yd->client_id, host, room, msg, members);
     1117                        YAHOO_CALLBACK(ext_yahoo_got_conf_invite)(yd->client_id, id, host, room, msg, members);
    11271118                break;
    11281119        case YAHOO_SERVICE_CONFDECLINE:
    11291120                if(who)
    1130                         YAHOO_CALLBACK(ext_yahoo_conf_userdecline)(yd->client_id, who, room, msg);
     1121                        YAHOO_CALLBACK(ext_yahoo_conf_userdecline)(yd->client_id, id, who, room, msg);
    11311122                break;
    11321123        case YAHOO_SERVICE_CONFLOGON:
    11331124                if(who)
    1134                         YAHOO_CALLBACK(ext_yahoo_conf_userjoin)(yd->client_id, who, room);
     1125                        YAHOO_CALLBACK(ext_yahoo_conf_userjoin)(yd->client_id, id, who, room);
    11351126                break;
    11361127        case YAHOO_SERVICE_CONFLOGOFF:
    11371128                if(who)
    1138                         YAHOO_CALLBACK(ext_yahoo_conf_userleave)(yd->client_id, who, room);
     1129                        YAHOO_CALLBACK(ext_yahoo_conf_userleave)(yd->client_id, id, who, room);
    11391130                break;
    11401131        case YAHOO_SERVICE_CONFMSG:
    11411132                if(who)
    1142                         YAHOO_CALLBACK(ext_yahoo_conf_message)(yd->client_id, who, room, msg, utf8);
     1133                        YAHOO_CALLBACK(ext_yahoo_conf_message)(yd->client_id, id, who, room, msg, utf8);
    11431134                break;
    11441135        }
     
    11481139{
    11491140        char *msg = NULL;
     1141        char *id = NULL;
    11501142        char *who = NULL;
    11511143        char *room = NULL;
     
    11641156                struct yahoo_pair *pair = l->data;
    11651157
     1158                if (pair->key == 1) {
     1159                        /* My identity */
     1160                        id = pair->value;
     1161                }
     1162
    11661163                if (pair->key == 104) {
    11671164                        /* Room name */
     
    12381235        if(!room) {
    12391236                if (pkt->service == YAHOO_SERVICE_CHATLOGOUT) { /* yahoo originated chat logout */
    1240                         YAHOO_CALLBACK(ext_yahoo_chat_yahoologout)(yid->yd->client_id);
     1237                        YAHOO_CALLBACK(ext_yahoo_chat_yahoologout)(yid->yd->client_id, id);
    12411238                        return ;
    12421239                }
    12431240                if (pkt->service == YAHOO_SERVICE_COMMENT && chaterr)  {
    1244                         YAHOO_CALLBACK(ext_yahoo_chat_yahooerror)(yid->yd->client_id);
    1245                         return ;
     1241                        YAHOO_CALLBACK(ext_yahoo_chat_yahooerror)(yid->yd->client_id, id);
     1242                        return;
    12461243                }
    12471244
     
    12561253                }
    12571254                if(firstjoin && members) {
    1258                         YAHOO_CALLBACK(ext_yahoo_chat_join)(yid->yd->client_id, room, topic, members, yid->fd);
     1255                        YAHOO_CALLBACK(ext_yahoo_chat_join)(yid->yd->client_id, id, room, topic, members, yid->fd);
    12591256                } else if(who) {
    12601257                        if(y_list_length(members) != 1) {
     
    12651262                                YList *n = members->next;
    12661263                                currentmember = members->data;
    1267                                 YAHOO_CALLBACK(ext_yahoo_chat_userjoin)(yid->yd->client_id, room, currentmember);
     1264                                YAHOO_CALLBACK(ext_yahoo_chat_userjoin)(yid->yd->client_id, id, room, currentmember);
    12681265                                y_list_free_1(members);
    12691266                                members=n;
     
    12731270        case YAHOO_SERVICE_CHATEXIT:
    12741271                if(who) {
    1275                         YAHOO_CALLBACK(ext_yahoo_chat_userleave)(yid->yd->client_id, room, who);
     1272                        YAHOO_CALLBACK(ext_yahoo_chat_userleave)(yid->yd->client_id, id, room, who);
    12761273                }
    12771274                break;
    12781275        case YAHOO_SERVICE_COMMENT:
    12791276                if(who) {
    1280                         YAHOO_CALLBACK(ext_yahoo_chat_message)(yid->yd->client_id, who, room, msg, msgtype, utf8);
     1277                        YAHOO_CALLBACK(ext_yahoo_chat_message)(yid->yd->client_id, id, who, room, msg, msgtype, utf8);
    12811278                }
    12821279                break;
     
    13371334                        YAHOO_CALLBACK(ext_yahoo_system_message)(yd->client_id, message->msg);
    13381335                } else if (pkt->status <= 2 || pkt->status == 5) {
    1339                         YAHOO_CALLBACK(ext_yahoo_got_im)(yd->client_id, message->from, message->msg, message->tm, pkt->status, message->utf8);
     1336                        YAHOO_CALLBACK(ext_yahoo_got_im)(yd->client_id, message->to, message->from, message->msg, message->tm, pkt->status, message->utf8);
    13401337                } else if (pkt->status == 0xffffffff) {
    1341                         YAHOO_CALLBACK(ext_yahoo_error)(yd->client_id, message->msg, 0);
     1338                        YAHOO_CALLBACK(ext_yahoo_error)(yd->client_id, message->msg, 0, E_SYSTEM);
    13421339                }
    13431340                free(message);
     
    13521349        YList *l;
    13531350        struct yahoo_data *yd = yid->yd;
    1354         char *name = NULL;
    1355         int state = 0;
    1356         int away = 0;
    1357         int idle = 0;
    1358         char *msg = NULL;
     1351
     1352        struct user
     1353        {
     1354                char *name;     /* 7    name */
     1355                int   state;    /* 10   state */
     1356                int   flags;    /* 13   flags, bit 0 = pager, bit 1 = chat, bit 2 = game */
     1357                int   mobile;   /* 60   mobile */
     1358                char *msg;      /* 19   custom status message */
     1359                int   away;     /* 47   away (or invisible)*/
     1360                int   buddy_session;    /* 11   state */
     1361                int   f17;      /* 17   in chat? then what about flags? */
     1362                int   idle;     /* 137  seconds idle */
     1363                int   f138;     /* 138  state */
     1364                char *f184;     /* 184  state */
     1365                int   f192;     /* 192  state */
     1366                int   f10001;   /* 10001        state */
     1367                int   f10002;   /* 10002        state */
     1368                int   f198;     /* 198  state */
     1369                char *f197;     /* 197  state */
     1370                char *f205;     /* 205  state */
     1371                int   f213;     /* 213  state */
     1372        } *u;
     1373
     1374        YList *users = 0;
    13591375       
    1360         if(pkt->service == YAHOO_SERVICE_LOGOFF && pkt->status == -1) {
     1376        if (pkt->service == YAHOO_SERVICE_LOGOFF && pkt->status == -1) {
    13611377                YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, YAHOO_LOGIN_DUPL, NULL);
    13621378                return;
     
    13821398                        break;
    13831399                case 7: /* the current buddy */
    1384                         name = pair->value;
     1400                        u = y_new0(struct user, 1);
     1401                        u->name = pair->value;
     1402                        users = y_list_prepend(users, u);
    13851403                        break;
    13861404                case 10: /* state */
    1387                         state = strtol(pair->value, NULL, 10);
     1405                        ((struct user*)users->data)->state = strtol(pair->value, NULL, 10);
    13881406                        break;
    13891407                case 19: /* custom status message */
    1390                         msg = pair->value;
     1408                        ((struct user*)users->data)->msg = pair->value;
    13911409                        break;
    13921410                case 47: /* is it an away message or not */
    1393                         away = atoi(pair->value);
     1411                        ((struct user*)users->data)->away = atoi(pair->value);
    13941412                        break;
    13951413                case 137: /* seconds idle */
    1396                         idle = atoi(pair->value);
    1397                         break;
    1398                 case 11: /* what is this? */
    1399                         NOTICE(("key %d:%s", pair->key, pair->value));
     1414                        ((struct user*)users->data)->idle = atoi(pair->value);
     1415                        break;
     1416                case 11: /* this is the buddy's session id */
     1417                        ((struct user*)users->data)->buddy_session = atoi(pair->value);
    14001418                        break;
    14011419                case 17: /* in chat? */
    1402                         break;
    1403                 case 13: /* in pager? */
    1404                         if (pkt->service == YAHOO_SERVICE_LOGOFF || strtol(pair->value, NULL, 10) == 0) {
    1405                                 YAHOO_CALLBACK(ext_yahoo_status_changed)(yd->client_id, name, YAHOO_STATUS_OFFLINE, NULL, 1);
    1406                                 break;
    1407                         }
    1408                         if (state == YAHOO_STATUS_AVAILABLE) {
    1409                                 YAHOO_CALLBACK(ext_yahoo_status_changed)(yd->client_id, name, state, NULL, 0);
    1410                         } else if (state == YAHOO_STATUS_CUSTOM) {
    1411                                 YAHOO_CALLBACK(ext_yahoo_status_changed)(yd->client_id, name, state, msg, away);
    1412                         } else {
    1413                                 YAHOO_CALLBACK(ext_yahoo_status_changed)(yd->client_id, name, state, NULL, idle);
    1414                         }
    1415 
    1416                         break;
    1417                 case 60:
     1420                        ((struct user*)users->data)->f17 = atoi(pair->value);
     1421                        break;
     1422                case 13: /* bitmask, bit 0 = pager, bit 1 = chat, bit 2 = game */
     1423                        ((struct user*)users->data)->flags = atoi(pair->value);
     1424                        break;
     1425                case 60: /* SMS -> 1 MOBILE USER */
    14181426                        /* sometimes going offline makes this 2, but invisible never sends it */
    1419                         NOTICE(("key %d:%s", pair->key, pair->value));
    1420                          break;
     1427                        ((struct user*)users->data)->mobile = atoi(pair->value);
     1428                        break;
     1429                case 138:
     1430                        ((struct user*)users->data)->f138 = atoi(pair->value);
     1431                        break;
     1432                case 184:
     1433                        ((struct user*)users->data)->f184 = pair->value;
     1434                        break;
     1435                case 192:
     1436                        ((struct user*)users->data)->f192 = atoi(pair->value);
     1437                        break;
     1438                case 10001:
     1439                        ((struct user*)users->data)->f10001 = atoi(pair->value);
     1440                        break;
     1441                case 10002:
     1442                        ((struct user*)users->data)->f10002 = atoi(pair->value);
     1443                        break;
     1444                case 198:
     1445                        ((struct user*)users->data)->f198 = atoi(pair->value);
     1446                        break;
     1447                case 197:
     1448                        ((struct user*)users->data)->f197 = pair->value;
     1449                        break;
     1450                case 205:
     1451                        ((struct user*)users->data)->f205 = pair->value;
     1452                        break;
     1453                case 213:
     1454                        ((struct user*)users->data)->f213 = atoi(pair->value);
     1455                        break;
    14211456                case 16: /* Custom error message */
    1422                         YAHOO_CALLBACK(ext_yahoo_error)(yd->client_id, pair->value, 0);
     1457                        YAHOO_CALLBACK(ext_yahoo_error)(yd->client_id, pair->value, 0, E_CUSTOM);
    14231458                        break;
    14241459                default:
     
    14261461                        break;
    14271462                }
     1463        }
     1464       
     1465        while (users) {
     1466                YList *t = users;
     1467                struct user *u = users->data;
     1468
     1469                if (u->name != NULL) {
     1470                        if (pkt->service == YAHOO_SERVICE_LOGOFF || u->flags == 0) {
     1471                                YAHOO_CALLBACK(ext_yahoo_status_changed)(yd->client_id, u->name, YAHOO_STATUS_OFFLINE, NULL, 1, 0, 0);
     1472                        } else {
     1473                                YAHOO_CALLBACK(ext_yahoo_status_changed)(yd->client_id, u->name, u->state, u->msg, u->away, u->idle, u->mobile);
     1474                        }
     1475                }
     1476
     1477                users = y_list_remove_link(users, users);
     1478                y_list_free_1(t);
     1479                FREE(u);
    14281480        }
    14291481}
     
    15301582        yahoo_packet_free(pkt);
    15311583
     1584}
     1585
     1586static void yahoo_process_picture_checksum( struct yahoo_input_data *yid, struct yahoo_packet *pkt)
     1587{
     1588        struct yahoo_data *yd = yid->yd;
     1589        char *from = NULL;
     1590        char *to = NULL;
     1591        int checksum = 0;
     1592        YList *l;
     1593
     1594        for(l = pkt->hash; l; l = l->next)
     1595        {
     1596                struct yahoo_pair *pair = l->data;
     1597
     1598                switch(pair->key)
     1599                {
     1600                        case 1:
     1601                        case 4:
     1602                                from = pair->value;
     1603                        case 5:
     1604                                to = pair->value;
     1605                                break;
     1606                        case 212:
     1607                                break;
     1608                        case 192:
     1609                                checksum = atoi( pair->value );
     1610                                break;
     1611                }
     1612        }
     1613
     1614        YAHOO_CALLBACK(ext_yahoo_got_buddyicon_checksum)(yd->client_id,to,from,checksum);
     1615}
     1616
     1617static void yahoo_process_picture(struct yahoo_input_data *yid, struct yahoo_packet *pkt)
     1618{
     1619        struct yahoo_data *yd = yid->yd;
     1620        char *url = NULL;
     1621        char *from = NULL;
     1622        char *to = NULL;
     1623        int status = 0;
     1624        int checksum = 0;
     1625        YList *l;
     1626       
     1627        for(l = pkt->hash; l; l = l->next)
     1628        {
     1629                struct yahoo_pair *pair = l->data;
     1630
     1631                switch(pair->key)
     1632                {
     1633                case 1:
     1634                case 4:         /* sender */
     1635                        from = pair->value;
     1636                        break;
     1637                case 5:         /* we */
     1638                        to = pair->value;
     1639                        break;
     1640                case 13:                /* request / sending */
     1641                        status = atoi( pair->value );
     1642                        break;
     1643                case 20:                /* url */
     1644                        url = pair->value;
     1645                        break;
     1646                case 192:       /*checksum */
     1647                        checksum = atoi( pair->value );
     1648                        break;
     1649                }
     1650        }
     1651
     1652        switch( status )
     1653        {
     1654                case 1: /* this is a request, ignore for now */
     1655                        YAHOO_CALLBACK(ext_yahoo_got_buddyicon_request)(yd->client_id, to, from);
     1656                        break;
     1657                case 2: /* this is cool - we get a picture :) */
     1658                        YAHOO_CALLBACK(ext_yahoo_got_buddyicon)(yd->client_id,to, from, url, checksum);
     1659                        break;
     1660        }
     1661}
     1662
     1663static void yahoo_process_picture_upload(struct yahoo_input_data *yid, struct yahoo_packet *pkt)
     1664{
     1665        struct yahoo_data *yd = yid->yd;
     1666        YList *l;
     1667        char *url = NULL;
     1668
     1669        if ( pkt->status != 1 )
     1670                return;         /* something went wrong */
     1671       
     1672        for(l = pkt->hash; l; l = l->next)
     1673        {
     1674                struct yahoo_pair *pair = l->data;
     1675
     1676                switch(pair->key)
     1677                {
     1678                        case 5:         /* we */
     1679                                break;
     1680                        case 20:                /* url */
     1681                                url = pair->value;
     1682                                break;
     1683                        case 27:                /* local filename */
     1684                                break;
     1685                        case 38:                /* time */
     1686                                break;
     1687                }
     1688        }
     1689
     1690        YAHOO_CALLBACK(ext_yahoo_buddyicon_uploaded)(yd->client_id, url);
    15321691}
    15331692
     
    16591818        md5_state_t        ctx;
    16601819
    1661         SHA_CTX            ctx1;
    1662         SHA_CTX            ctx2;
     1820        sha1_state_t       ctx1;
     1821        sha1_state_t       ctx2;
    16631822
    16641823        char *alphabet1 = "FBZDWAGHrJTLMNOPpRSKUVEXYChImkwQ";
     
    17161875        magic_ptr = (unsigned char *)seed;
    17171876
    1718         while (*magic_ptr != (int)NULL) {
     1877        while (*magic_ptr != 0) {
    17191878                char *loc;
    17201879
     
    18952054                memset(&(pass_hash_xor2[cnt]), 0x5c, 64-cnt);
    18962055
    1897         shaInit(&ctx1);
    1898         shaInit(&ctx2);
     2056        sha1_init(&ctx1);
     2057        sha1_init(&ctx2);
    18992058
    19002059        /* The first context gets the password hash XORed
     
    19032062         * challenge. */
    19042063
    1905         shaUpdate(&ctx1, pass_hash_xor1, 64);
     2064        sha1_append(&ctx1, pass_hash_xor1, 64);
    19062065        if (j >= 3 )
    1907                 ctx1.sizeLo = 0x1ff;
    1908         shaUpdate(&ctx1, magic_key_char, 4);
    1909         shaFinal(&ctx1, digest1);
     2066                ctx1.Length_Low = 0x1ff;
     2067        sha1_append(&ctx1, magic_key_char, 4);
     2068        sha1_finish(&ctx1, digest1);
    19102069
    19112070         /* The second context gets the password hash XORed
     
    19132072          * of the first context. */
    19142073
    1915         shaUpdate(&ctx2, pass_hash_xor2, 64);
    1916         shaUpdate(&ctx2, digest1, 20);
    1917         shaFinal(&ctx2, digest2);
     2074        sha1_append(&ctx2, pass_hash_xor2, 64);
     2075        sha1_append(&ctx2, digest1, 20);
     2076        sha1_finish(&ctx2, digest2);
    19182077
    19192078        /* Now that we have digest2, use it to fetch
     
    19862145                memset(&(crypt_hash_xor2[cnt]), 0x5c, 64-cnt);
    19872146
    1988         shaInit(&ctx1);
    1989         shaInit(&ctx2);
     2147        sha1_init(&ctx1);
     2148        sha1_init(&ctx2);
    19902149
    19912150        /* The first context gets the password hash XORed
     
    19942153         * challenge. */
    19952154
    1996         shaUpdate(&ctx1, crypt_hash_xor1, 64);
     2155        sha1_append(&ctx1, crypt_hash_xor1, 64);
    19972156        if (j >= 3 )
    1998                 ctx1.sizeLo = 0x1ff;
    1999         shaUpdate(&ctx1, magic_key_char, 4);
    2000         shaFinal(&ctx1, digest1);
     2157                ctx1.Length_Low = 0x1ff;
     2158        sha1_append(&ctx1, magic_key_char, 4);
     2159        sha1_finish(&ctx1, digest1);
    20012160
    20022161        /* The second context gets the password hash XORed
     
    20042163         * of the first context. */
    20052164
    2006         shaUpdate(&ctx2, crypt_hash_xor2, 64);
    2007         shaUpdate(&ctx2, digest1, 20);
    2008         shaFinal(&ctx2, digest2);
     2165        sha1_append(&ctx2, crypt_hash_xor2, 64);
     2166        sha1_append(&ctx2, digest1, 20);
     2167        sha1_finish(&ctx2, digest2);
    20092168
    20102169        /* Now that we have digest2, use it to fetch
     
    21742333        int online = FALSE;
    21752334        int away = 0;
     2335        int idle = 0;
     2336        int mobile = 0;
    21762337
    21772338        YList *l;
     
    21952356                else if (pair->key == 47)
    21962357                        away = strtol(pair->value, NULL, 10);
     2358                else if (pair->key == 137)
     2359                        idle = strtol(pair->value, NULL, 10);
     2360                else if (pair->key == 60)
     2361                        mobile = strtol(pair->value, NULL, 10);
     2362               
    21972363        }
    21982364
     
    22002366                YAHOO_CALLBACK(ext_yahoo_contact_added)(yd->client_id, id, who, msg);
    22012367        else if (name)
    2202                 YAHOO_CALLBACK(ext_yahoo_status_changed)(yd->client_id, name, state, msg, away);
     2368                YAHOO_CALLBACK(ext_yahoo_status_changed)(yd->client_id, name, state, msg, away, idle, mobile);
    22032369        else if(pkt->status == 0x07)
    22042370                YAHOO_CALLBACK(ext_yahoo_rejected)(yd->client_id, who, msg);
     
    22352401                where = "Unknown";
    22362402
    2237         bud = y_new0(struct yahoo_buddy, 1);
    2238         bud->id = strdup(who);
    2239         bud->group = strdup(where);
    2240         bud->real_name = NULL;
    2241 
    2242         yd->buddies = y_list_append(yd->buddies, bud);
     2403        /* status: 0 == Successful, 1 == Error (does not exist), 2 == Already in list */
     2404        if( status == 0 ) {
     2405                bud = y_new0(struct yahoo_buddy, 1);
     2406                bud->id = strdup(who);
     2407                bud->group = strdup(where);
     2408                bud->real_name = NULL;
     2409               
     2410                yd->buddies = y_list_append(yd->buddies, bud);
     2411               
     2412                /* Possibly called already, but at least the call above doesn't
     2413                   seem to happen every time (not anytime I tried). */
     2414                YAHOO_CALLBACK(ext_yahoo_contact_added)(yd->client_id, me, who, NULL);
     2415        }
    22432416
    22442417/*      YAHOO_CALLBACK(ext_yahoo_status_changed)(yd->client_id, who, status, NULL, (status==YAHOO_STATUS_AVAILABLE?0:1)); */
     
    23282501
    23292502/*      if(status)
    2330                 YAHOO_CALLBACK(ext_yahoo_error)(yd->client_id, status, who, 0);
     2503                YAHOO_CALLBACK(ext_yahoo_error)(yd->client_id, who, 0, status);
    23312504*/     
    23322505}
     
    23522525        }
    23532526
    2354         NOTICE(("got voice chat invite from %s in %s", who, room));
     2527        NOTICE(("got voice chat invite from %s in %s to identity %s", who, room, me));
    23552528        /*
    23562529         * send: s:0 1:me 5:who 57:room 13:1
     
    23622535         * rejr: s:4 5:who 10:99 19:-1617114599
    23632536         */
     2537}
     2538
     2539static void yahoo_process_ping(struct yahoo_input_data *yid, struct yahoo_packet *pkt)
     2540{
     2541        char *errormsg = NULL;
     2542       
     2543        YList *l;
     2544        for (l = pkt->hash; l; l = l->next) {
     2545                struct yahoo_pair *pair = l->data;
     2546                if (pair->key == 16)
     2547                        errormsg = pair->value;
     2548        }
     2549       
     2550        NOTICE(("got ping packet"));
     2551        YAHOO_CALLBACK(ext_yahoo_got_ping)(yid->yd->client_id, errormsg);
    23642552}
    23652553
     
    25392727                yahoo_process_webcam_key(yid, pkt);
    25402728                break;
     2729        case YAHOO_SERVICE_PING:
     2730                yahoo_process_ping(yid, pkt);
     2731                break;
    25412732        case YAHOO_SERVICE_IDLE:
    25422733        case YAHOO_SERVICE_MAILSTAT:
     
    25462737        case YAHOO_SERVICE_ADDIDENT:
    25472738        case YAHOO_SERVICE_ADDIGNORE:
    2548         case YAHOO_SERVICE_PING:
    25492739        case YAHOO_SERVICE_GOTGROUPRENAME:
    25502740        case YAHOO_SERVICE_GROUPRENAME:
     
    25582748                yahoo_dump_unhandled(pkt);
    25592749                break;
     2750        case YAHOO_SERVICE_PICTURE:
     2751                yahoo_process_picture(yid, pkt);
     2752                break;
     2753        case YAHOO_SERVICE_PICTURE_CHECKSUM:
     2754                yahoo_process_picture_checksum(yid, pkt);
     2755                break;
     2756        case YAHOO_SERVICE_PICTURE_UPLOAD:
     2757                yahoo_process_picture_upload(yid, pkt);
     2758                break; 
    25602759        default:
    25612760                WARNING(("unknown service 0x%02x", pkt->service));
     
    31503349                                        break;
    31513350                                case 5:
    3152                                         if(cp != "\005")
     3351                                        if(strcmp(cp, "5") != 0)
    31533352                                                yct->location = cp;
    31543353                                        k = 0;
     
    33673566
    33683567                if(yid->type == YAHOO_CONNECTION_PAGER) {
    3369                         YAHOO_CALLBACK(ext_yahoo_login_response)(yid->yd->client_id, YAHOO_LOGIN_SOCK, NULL);
     3568                        YAHOO_CALLBACK(ext_yahoo_error)(yid->yd->client_id, "Connection closed by server", 1, E_CONNECTION);
    33703569                }
    33713570
     
    35153714}
    35163715
    3517 void yahoo_send_im(int id, const char *from, const char *who, const char *what, int utf8)
     3716void yahoo_send_im(int id, const char *from, const char *who, const char *what, int utf8, int picture)
    35183717{
    35193718        struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
    35203719        struct yahoo_packet *pkt = NULL;
    35213720        struct yahoo_data *yd;
     3721        char pic_str[10];
    35223722
    35233723        if(!yid)
     
    35283728        pkt = yahoo_packet_new(YAHOO_SERVICE_MESSAGE, YAHOO_STATUS_OFFLINE, yd->session_id);
    35293729
     3730        snprintf(pic_str, sizeof(pic_str), "%d", picture);
     3731       
    35303732        if(from && strcmp(from, yd->user))
    35313733                yahoo_packet_hash(pkt, 0, yd->user);
     
    35393741        yahoo_packet_hash(pkt, 63, ";0");       /* imvironment name; or ;0 */
    35403742        yahoo_packet_hash(pkt, 64, "0");
     3743        yahoo_packet_hash(pkt, 206, pic_str);
    35413744
    35423745
     
    35913794        else
    35923795                service = YAHOO_SERVICE_ISAWAY;
    3593         pkt = yahoo_packet_new(service, yd->current_status, yd->session_id);
    3594         snprintf(s, sizeof(s), "%d", yd->current_status);
    3595         yahoo_packet_hash(pkt, 10, s);
    3596         if (yd->current_status == YAHOO_STATUS_CUSTOM) {
    3597                 yahoo_packet_hash(pkt, 19, msg);
    3598                 yahoo_packet_hash(pkt, 47, away?"1":"0");
     3796         
     3797        if ((away == 2) && (yd->current_status == YAHOO_STATUS_AVAILABLE)) {
     3798                pkt = yahoo_packet_new(YAHOO_SERVICE_ISAWAY, YAHOO_STATUS_BRB, yd->session_id);
     3799                yahoo_packet_hash(pkt, 10, "999");
     3800                yahoo_packet_hash(pkt, 47, "2");
     3801        }else {
     3802                pkt = yahoo_packet_new(service, YAHOO_STATUS_AVAILABLE, yd->session_id);
     3803                snprintf(s, sizeof(s), "%d", yd->current_status);
     3804                yahoo_packet_hash(pkt, 10, s);
     3805                if (yd->current_status == YAHOO_STATUS_CUSTOM) {
     3806                        yahoo_packet_hash(pkt, 19, msg);
     3807                        yahoo_packet_hash(pkt, 47, (away == 2)? "2": (away) ?"1":"0");
     3808                } else {
     3809                        yahoo_packet_hash(pkt, 47, (away == 2)? "2": (away) ?"1":"0");
     3810                }
     3811               
     3812               
     3813               
    35993814        }
    36003815
     
    38374052}
    38384053
    3839 void yahoo_add_buddy(int id, const char *who, const char *group)
     4054void yahoo_add_buddy(int id, const char *who, const char *group, const char *msg)
    38404055{
    38414056        struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
     
    38544069        yahoo_packet_hash(pkt, 7, who);
    38554070        yahoo_packet_hash(pkt, 65, group);
     4071        if (msg != NULL) /* add message/request "it's me add me" */
     4072                yahoo_packet_hash(pkt, 14, msg);
    38564073        yahoo_send_packet(yid, pkt, 0);
    38574074        yahoo_packet_free(pkt);
     
    39154132        yahoo_packet_hash(pkt, 7, who);
    39164133        yahoo_packet_hash(pkt, 13, unignore?"2":"1");
     4134        yahoo_send_packet(yid, pkt, 0);
     4135        yahoo_packet_free(pkt);
     4136}
     4137
     4138void yahoo_stealth_buddy(int id, const char *who, int unstealth)
     4139{
     4140        struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
     4141        struct yahoo_data *yd;
     4142        struct yahoo_packet *pkt;
     4143
     4144        if(!yid)
     4145                return;
     4146        yd = yid->yd;
     4147
     4148        if (!yd->logged_in)
     4149                return;
     4150
     4151        pkt = yahoo_packet_new(YAHOO_SERVICE_STEALTH, YAHOO_STATUS_AVAILABLE, yd->session_id);
     4152        yahoo_packet_hash(pkt, 1, yd->user);
     4153        yahoo_packet_hash(pkt, 7, who);
     4154        yahoo_packet_hash(pkt, 31, unstealth?"2":"1");
     4155        yahoo_packet_hash(pkt, 13, "2");
    39174156        yahoo_send_packet(yid, pkt, 0);
    39184157        yahoo_packet_free(pkt);
     
    42224461        yahoo_packet_hash(pkt, 1, (from?from:yd->user));
    42234462
     4463        yahoo_send_packet(yid, pkt, 0);
     4464
     4465        yahoo_packet_free(pkt);
     4466}
     4467
     4468void yahoo_buddyicon_request(int id, const char *who)
     4469{
     4470        struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
     4471        struct yahoo_data *yd;
     4472        struct yahoo_packet *pkt;
     4473
     4474        if( !yid )
     4475                return;
     4476
     4477        yd = yid->yd;
     4478       
     4479        pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE, YAHOO_STATUS_AVAILABLE, 0);
     4480        yahoo_packet_hash(pkt, 4, yd->user);
     4481        yahoo_packet_hash(pkt, 5, who);
     4482        yahoo_packet_hash(pkt, 13, "1");
     4483        yahoo_send_packet(yid, pkt, 0);
     4484
     4485        yahoo_packet_free(pkt);
     4486}
     4487
     4488void yahoo_send_picture_info(int id, const char *who, const char *url, int checksum)
     4489{
     4490        struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
     4491        struct yahoo_data *yd;
     4492        struct yahoo_packet *pkt;
     4493        char checksum_str[10];
     4494
     4495        if( !yid )
     4496                return;
     4497
     4498        yd = yid->yd;
     4499
     4500        snprintf(checksum_str, sizeof(checksum_str), "%d", checksum);
     4501
     4502        pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE, YAHOO_STATUS_AVAILABLE, 0);
     4503        yahoo_packet_hash(pkt, 1, yd->user);
     4504        yahoo_packet_hash(pkt, 4, yd->user);
     4505        yahoo_packet_hash(pkt, 5, who);
     4506        yahoo_packet_hash(pkt, 13, "2");
     4507        yahoo_packet_hash(pkt, 20, url);
     4508        yahoo_packet_hash(pkt, 192, checksum_str);
     4509        yahoo_send_packet(yid, pkt, 0);
     4510
     4511        yahoo_packet_free(pkt);
     4512}
     4513
     4514void yahoo_send_picture_update(int id, const char *who, int type)
     4515{
     4516        struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
     4517        struct yahoo_data *yd;
     4518        struct yahoo_packet *pkt;
     4519        char type_str[10];
     4520
     4521        if( !yid )
     4522                return;
     4523
     4524        yd = yid->yd;
     4525
     4526        snprintf(type_str, sizeof(type_str), "%d", type);
     4527
     4528        pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE_UPDATE, YAHOO_STATUS_AVAILABLE, 0);
     4529        yahoo_packet_hash(pkt, 1, yd->user);
     4530        yahoo_packet_hash(pkt, 5, who);
     4531        yahoo_packet_hash(pkt, 206, type_str);
     4532        yahoo_send_packet(yid, pkt, 0);
     4533
     4534        yahoo_packet_free(pkt);
     4535}
     4536
     4537void yahoo_send_picture_checksum(int id, const char *who, int checksum)
     4538{
     4539        struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_PAGER);
     4540        struct yahoo_data *yd;
     4541        struct yahoo_packet *pkt;
     4542        char checksum_str[10];
     4543
     4544        if( !yid )
     4545                return;
     4546
     4547        yd = yid->yd;
     4548       
     4549        snprintf(checksum_str, sizeof(checksum_str), "%d", checksum);
     4550
     4551        pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE_CHECKSUM, YAHOO_STATUS_AVAILABLE, 0);
     4552        yahoo_packet_hash(pkt, 1, yd->user);
     4553        if( who != 0 )
     4554                yahoo_packet_hash(pkt, 5, who);
     4555        yahoo_packet_hash(pkt, 192, checksum_str);
     4556        yahoo_packet_hash(pkt, 212, "1");
    42244557        yahoo_send_packet(yid, pkt, 0);
    42254558
     
    44304763};
    44314764
     4765static void _yahoo_send_picture_connected(int id, int fd, int error, void *data)
     4766{
     4767        struct yahoo_input_data *yid = find_input_by_id_and_type(id, YAHOO_CONNECTION_FT);
     4768        struct send_file_data *sfd = data;
     4769        struct yahoo_packet *pkt = sfd->pkt;
     4770        unsigned char buff[1024];
     4771
     4772        if(fd <= 0) {
     4773                sfd->callback(id, fd, error, sfd->user_data);
     4774                FREE(sfd);
     4775                yahoo_packet_free(pkt);
     4776                inputs = y_list_remove(inputs, yid);
     4777                FREE(yid);
     4778                return;
     4779        }
     4780
     4781        yid->fd = fd;
     4782        yahoo_send_packet(yid, pkt, 8);
     4783        yahoo_packet_free(pkt);
     4784
     4785        snprintf((char *)buff, sizeof(buff), "29");
     4786        buff[2] = 0xc0;
     4787        buff[3] = 0x80;
     4788       
     4789        write(yid->fd, buff, 4);
     4790
     4791        /*      YAHOO_CALLBACK(ext_yahoo_add_handler)(nyd->fd, YAHOO_INPUT_READ); */
     4792
     4793        sfd->callback(id, fd, error, sfd->user_data);
     4794        FREE(sfd);
     4795        inputs = y_list_remove(inputs, yid);
     4796        /*
     4797        while(yahoo_tcp_readline(buff, sizeof(buff), nyd->fd) > 0) {
     4798        if(!strcmp(buff, ""))
     4799        break;
     4800}
     4801
     4802        */
     4803        yahoo_input_close(yid);
     4804}
     4805
     4806void yahoo_send_picture(int id, const char *name, unsigned long size,
     4807                                                        yahoo_get_fd_callback callback, void *data)
     4808{
     4809        struct yahoo_data *yd = find_conn_by_id(id);
     4810        struct yahoo_input_data *yid;
     4811        struct yahoo_server_settings *yss;
     4812        struct yahoo_packet *pkt = NULL;
     4813        char size_str[10];
     4814        char expire_str[10];
     4815        long content_length=0;
     4816        unsigned char buff[1024];
     4817        char url[255];
     4818        struct send_file_data *sfd;
     4819
     4820        if(!yd)
     4821                return;
     4822
     4823        yss = yd->server_settings;
     4824
     4825        yid = y_new0(struct yahoo_input_data, 1);
     4826        yid->yd = yd;
     4827        yid->type = YAHOO_CONNECTION_FT;
     4828
     4829        pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE_UPLOAD, YAHOO_STATUS_AVAILABLE, yd->session_id);
     4830
     4831        snprintf(size_str, sizeof(size_str), "%ld", size);
     4832        snprintf(expire_str, sizeof(expire_str), "%ld", (long)604800);
     4833
     4834        yahoo_packet_hash(pkt, 0, yd->user);
     4835        yahoo_packet_hash(pkt, 1, yd->user);
     4836        yahoo_packet_hash(pkt, 14, "");
     4837        yahoo_packet_hash(pkt, 27, name);
     4838        yahoo_packet_hash(pkt, 28, size_str);
     4839        yahoo_packet_hash(pkt, 38, expire_str);
     4840       
     4841
     4842        content_length = YAHOO_PACKET_HDRLEN + yahoo_packet_length(pkt);
     4843
     4844        snprintf(url, sizeof(url), "http://%s:%d/notifyft",
     4845                                yss->filetransfer_host, yss->filetransfer_port);
     4846        snprintf((char *)buff, sizeof(buff), "Y=%s; T=%s",
     4847                                 yd->cookie_y, yd->cookie_t);
     4848        inputs = y_list_prepend(inputs, yid);
     4849
     4850        sfd = y_new0(struct send_file_data, 1);
     4851        sfd->pkt = pkt;
     4852        sfd->callback = callback;
     4853        sfd->user_data = data;
     4854        yahoo_http_post(yid->yd->client_id, url, (char *)buff, content_length+4+size,
     4855                                                _yahoo_send_picture_connected, sfd);
     4856}
     4857
    44324858static void _yahoo_send_file_connected(int id, int fd, int error, void *data)
    44334859{
Note: See TracChangeset for help on using the changeset viewer.