From: Rob F. <rob...@us...> - 2002-03-02 04:52:25
|
Update of /cvsroot/gaim/gaim/src/protocols/oscar In directory usw-pr-cvs1:/tmp/cvs-serv16032/src/protocols/oscar Modified Files: aim.h aim_cbtypes.h ft.c info.c oscar.c Log Message: 0.53 :) Index: aim.h =================================================================== RCS file: /cvsroot/gaim/gaim/src/protocols/oscar/aim.h,v retrieving revision 1.31 retrieving revision 1.32 diff -u -d -r1.31 -r1.32 --- aim.h 2 Mar 2002 01:36:01 -0000 1.31 +++ aim.h 2 Mar 2002 04:52:21 -0000 1.32 @@ -390,15 +390,25 @@ fu32_t membersince; fu32_t onlinesince; fu32_t sessionlen; - int capspresent; fu32_t capabilities; struct { fu32_t status; fu32_t ipaddr; fu8_t crap[0x25]; /* until we figure it out... */ } icqinfo; + fu32_t present; } aim_userinfo_t; +#define AIM_USERINFO_PRESENT_FLAGS 0x00000001 +#define AIM_USERINFO_PRESENT_MEMBERSINCE 0x00000002 +#define AIM_USERINFO_PRESENT_ONLINESINCE 0x00000004 +#define AIM_USERINFO_PRESENT_IDLE 0x00000008 +#define AIM_USERINFO_PRESENT_ICQEXTSTATUS 0x00000010 +#define AIM_USERINFO_PRESENT_ICQIPADDR 0x00000020 +#define AIM_USERINFO_PRESENT_ICQDATA 0x00000040 +#define AIM_USERINFO_PRESENT_CAPABILITIES 0x00000080 +#define AIM_USERINFO_PRESENT_SESSIONLEN 0x00000100 + faim_export const char *aim_userinfo_sn(aim_userinfo_t *ui); faim_export fu16_t aim_userinfo_flags(aim_userinfo_t *ui); faim_export fu16_t aim_userinfo_idle(aim_userinfo_t *ui); @@ -827,6 +837,7 @@ faim_export int aim_send_im(aim_session_t *, const char *destsn, unsigned short flags, const char *msg); faim_export int aim_send_icon(aim_session_t *sess, const char *sn, const fu8_t *icon, int iconlen, time_t stamp, fu16_t iconsum); faim_export fu16_t aim_iconsum(const fu8_t *buf, int buflen); +faim_export int aim_send_typing(aim_session_t *sess, aim_conn_t *conn, int typing); faim_export int aim_send_im_direct(aim_session_t *, aim_conn_t *, const char *msg); faim_export const char *aim_directim_getsn(aim_conn_t *conn); faim_export aim_conn_t *aim_directim_initiate(aim_session_t *, const char *destsn); Index: aim_cbtypes.h =================================================================== RCS file: /cvsroot/gaim/gaim/src/protocols/oscar/aim_cbtypes.h,v retrieving revision 1.6 retrieving revision 1.7 diff -u -d -r1.6 -r1.7 --- aim_cbtypes.h 2 Mar 2002 01:36:01 -0000 1.6 +++ aim_cbtypes.h 2 Mar 2002 04:52:21 -0000 1.7 @@ -254,6 +254,7 @@ #define AIM_CB_SPECIAL_CONNCOMPLETE 0x0004 #define AIM_CB_SPECIAL_FLAPVER 0x0005 #define AIM_CB_SPECIAL_CONNINITDONE 0x0006 +#define AIM_CB_SPECIAL_DOWNLOADIMAGE 0x007 #define AIM_CB_SPECIAL_UNKNOWN 0xffff #define AIM_CB_SPECIAL_DEFAULT AIM_CB_SPECIAL_UNKNOWN Index: ft.c =================================================================== RCS file: /cvsroot/gaim/gaim/src/protocols/oscar/ft.c,v retrieving revision 1.13 retrieving revision 1.14 diff -u -d -r1.13 -r1.14 --- ft.c 15 Jan 2002 04:07:08 -0000 1.13 +++ ft.c 2 Mar 2002 04:52:21 -0000 1.14 @@ -109,24 +109,24 @@ } /** - * aim_send_im_direct - send IM client-to-client over established connection + * aim_send_typing - send client-to-client typing notification over established connection * @sess: session to conn * @conn: directim connection - * @msg: null-terminated string to send; if this is NULL, it will send a "typing" notice. + * @typing: If true, notify user has started typing; if false, notify user has stopped. * - * Call this just like you would aim_send_im, to send a directim. You - * _must_ have previously established the directim connection. + * The connection must have been previously established. */ -faim_export int aim_send_im_direct(aim_session_t *sess, aim_conn_t *conn, const char *msg) +faim_export int aim_send_typing(aim_session_t *sess, aim_conn_t *conn, int typing) { - struct aim_directim_intdata *intdata = (struct aim_directim_intdata *)conn->internal; + +struct aim_directim_intdata *intdata = (struct aim_directim_intdata *)conn->internal; aim_frame_t *fr; aim_bstream_t hdrbs; /* XXX this should be within aim_frame_t */ if (!sess || !conn || (conn->type != AIM_CONN_TYPE_RENDEZVOUS)) return -EINVAL; - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, 0x01, strlen(msg)))) + if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, 0x01, 0))) return -ENOMEM; memcpy(fr->hdr.oft.magic, "ODC2", 4); @@ -147,18 +147,18 @@ aimbs_put16(&hdrbs, 0x0000); aimbs_put16(&hdrbs, 0x0000); aimbs_put16(&hdrbs, 0x0000); - aimbs_put32(&hdrbs, strlen(msg)); + aimbs_put32(&hdrbs, 0x00000000); aimbs_put16(&hdrbs, 0x0000); aimbs_put16(&hdrbs, 0x0000); aimbs_put16(&hdrbs, 0x0000); - /* flags -- 0x000e for "typing", 0x0000 for message */ - aimbs_put16(&hdrbs, msg ? 0x0000 : 0x000e); + /* flags -- 0x000e for "started typing", 0x0002 for "stopped typing */ + aimbs_put16(&hdrbs, ( typing ? 0x000e : 0x0002)); aimbs_put16(&hdrbs, 0x0000); aimbs_put16(&hdrbs, 0x0000); aimbs_putraw(&hdrbs, sess->sn, strlen(sess->sn)); - + aim_bstream_setpos(&hdrbs, 52); /* bleeehh */ aimbs_put8(&hdrbs, 0x00); @@ -172,22 +172,89 @@ /* end of hdr2 */ - if (msg) { + aim_tx_enqueue(sess, fr); + + return 0; +} + +/** + * aim_send_im_direct - send IM client-to-client over established connection + * @sess: session to conn + * @conn: directim connection + * @msg: null-terminated string to send. + * + * Call this just like you would aim_send_im, to send a directim. You + * _must_ have previously established the directim connection. + */ +faim_export int aim_send_im_direct(aim_session_t *sess, aim_conn_t *conn, const char *msg) +{ + struct aim_directim_intdata *intdata = (struct aim_directim_intdata *)conn->internal; + aim_frame_t *fr; + aim_bstream_t hdrbs; /* XXX this should be within aim_frame_t */ + + if (!sess || !conn || !msg || (conn->type != AIM_CONN_TYPE_RENDEZVOUS)) + return -EINVAL; + + if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, 0x01, strlen(msg)))) + return -ENOMEM; + + memcpy(fr->hdr.oft.magic, "ODC2", 4); + + fr->hdr.oft.hdr2len = 0x44; + + if (!(fr->hdr.oft.hdr2 = calloc(1, fr->hdr.oft.hdr2len))) { + aim_frame_destroy(fr); + return -ENOMEM; + } + + aim_bstream_init(&hdrbs, fr->hdr.oft.hdr2, fr->hdr.oft.hdr2len); + + aimbs_put16(&hdrbs, 0x0006); + aimbs_put16(&hdrbs, 0x0000); + aimbs_putraw(&hdrbs, intdata->cookie, 8); + aimbs_put16(&hdrbs, 0x0000); + aimbs_put16(&hdrbs, 0x0000); + aimbs_put16(&hdrbs, 0x0000); + aimbs_put16(&hdrbs, 0x0000); + aimbs_put32(&hdrbs, strlen(msg)); + aimbs_put16(&hdrbs, 0x0000); + aimbs_put16(&hdrbs, 0x0000); + aimbs_put16(&hdrbs, 0x0000); + + /* flags -- 0x000e for "started typing", 0x0002 for "stopped typing, 0x0000 for message */ + aimbs_put16(&hdrbs, 0x0000); + + aimbs_put16(&hdrbs, 0x0000); + aimbs_put16(&hdrbs, 0x0000); + aimbs_putraw(&hdrbs, sess->sn, strlen(sess->sn)); + + aim_bstream_setpos(&hdrbs, 52); /* bleeehh */ + + aimbs_put8(&hdrbs, 0x00); + aimbs_put16(&hdrbs, 0x0000); + aimbs_put16(&hdrbs, 0x0000); + aimbs_put16(&hdrbs, 0x0000); + aimbs_put16(&hdrbs, 0x0000); + aimbs_put16(&hdrbs, 0x0000); + aimbs_put16(&hdrbs, 0x0000); + aimbs_put16(&hdrbs, 0x0000); + + /* end of hdr2 */ + #if 0 /* XXX this is how you send buddy icon info... */ - i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0008); - i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x000c); - i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000); - i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x1466); - i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0001); - i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x2e0f); - i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x393e); - i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0xcac8); + i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0008); + i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x000c); + i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000); + i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x1466); + i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0001); + i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x2e0f); + i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x393e); + i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0xcac8); #endif - aimbs_putraw(&fr->data, msg, strlen(msg)); - } - + aimbs_putraw(&fr->data, msg, strlen(msg)); + aim_tx_enqueue(sess, fr); - + return 0; } @@ -1021,26 +1088,45 @@ int ret = 0; if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING))) - ret = userfunc(sess, &fr, snptr); + ret = userfunc(sess, &fr, snptr, 1); + + return ret; + + } else if (flags == 0x0002) { + int ret = 0; + + if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING))) + ret = userfunc(sess, &fr, snptr, 0); return ret; } else if ((flags == 0x0000) && payloadlength) { - char *msg; + char *msg, *msg2; int ret = 0; + int recvd = 0; + int i; if (!(msg = calloc(1, payloadlength+1))) return -1; - - if (aim_recv(conn->fd, msg, payloadlength) < payloadlength) { - free(msg); - return -1; + msg2 = msg; + + while (payloadlength - recvd) { + if (payloadlength - recvd >= 1024) + i = aim_recv(conn->fd, msg2, 1024); + else + i = aim_recv(conn->fd, msg2, payloadlength - recvd); + if (i == 0) { + free(msg); + return -1; + } + recvd = recvd + i; + msg2 = msg2 + i; + if ((userfunc=aim_callhandler(sess, conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_DOWNLOADIMAGE))) + userfunc(sess, &fr, snptr, (double)recvd / payloadlength); } - - msg[payloadlength] = '\0'; - + if ( (userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING)) ) - ret = userfunc(sess, &fr, snptr, msg); + ret = userfunc(sess, &fr, snptr, msg, payloadlength); free(msg); Index: info.c =================================================================== RCS file: /cvsroot/gaim/gaim/src/protocols/oscar/info.c,v retrieving revision 1.13 retrieving revision 1.14 diff -u -d -r1.13 -r1.14 --- info.c 23 Feb 2002 22:50:43 -0000 1.13 +++ info.c 2 Mar 2002 04:52:21 -0000 1.14 @@ -106,7 +106,7 @@ faim_export int aim_userinfo_hascap(aim_userinfo_t *ui, fu32_t cap) { - if (!ui || !ui->capspresent) + if (!ui || !(ui->present & AIM_USERINFO_PRESENT_CAPABILITIES)) return -1; return !!(ui->capabilities & cap); @@ -338,6 +338,7 @@ * */ outinfo->flags = aimbs_get16(bs); + outinfo->present |= AIM_USERINFO_PRESENT_FLAGS; } else if (type == 0x0002) { /* @@ -347,6 +348,7 @@ * the service, stored in time_t format. */ outinfo->membersince = aimbs_get32(bs); + outinfo->present |= AIM_USERINFO_PRESENT_MEMBERSINCE; } else if (type == 0x0003) { /* @@ -356,6 +358,7 @@ * session, stored in time_t format. */ outinfo->onlinesince = aimbs_get32(bs); + outinfo->present |= AIM_USERINFO_PRESENT_ONLINESINCE; } else if (type == 0x0004) { /* @@ -369,6 +372,7 @@ * related to reality. */ outinfo->idletime = aimbs_get16(bs); + outinfo->present |= AIM_USERINFO_PRESENT_IDLE; } else if (type == 0x0006) { /* @@ -379,6 +383,7 @@ */ aimbs_get16(bs); outinfo->icqinfo.status = aimbs_get16(bs); + outinfo->present |= AIM_USERINFO_PRESENT_ICQEXTSTATUS; } else if (type == 0x000a) { /* @@ -388,6 +393,7 @@ * Ahh, the joy of ICQ security. */ outinfo->icqinfo.ipaddr = aimbs_get32(bs); + outinfo->present |= AIM_USERINFO_PRESENT_ICQIPADDR; } else if (type == 0x000c) { /* @@ -398,6 +404,7 @@ * */ aimbs_getrawbuf(bs, outinfo->icqinfo.crap, 0x25); + outinfo->present |= AIM_USERINFO_PRESENT_ICQDATA; } else if (type == 0x000d) { /* @@ -407,7 +414,7 @@ * */ outinfo->capabilities = aim_getcap(sess, bs, length); - outinfo->capspresent = 1; + outinfo->present |= AIM_USERINFO_PRESENT_CAPABILITIES; } else if (type == 0x000e) { /* @@ -433,6 +440,7 @@ * */ outinfo->sessionlen = aimbs_get32(bs); + outinfo->present |= AIM_USERINFO_PRESENT_SESSIONLEN; } else { @@ -644,7 +652,7 @@ aim_bstream_init(&cbs, ct->value, ct->length); userinfo.capabilities = aim_getcap(sess, &cbs, ct->length); - userinfo.capspresent = 1; + userinfo.present = AIM_USERINFO_PRESENT_CAPABILITIES; } } Index: oscar.c =================================================================== RCS file: /cvsroot/gaim/gaim/src/protocols/oscar/oscar.c,v retrieving revision 1.100 retrieving revision 1.101 diff -u -d -r1.100 -r1.101 --- oscar.c 2 Mar 2002 01:36:01 -0000 1.100 +++ oscar.c 2 Mar 2002 04:52:21 -0000 1.101 @@ -101,6 +101,15 @@ gboolean killme; gboolean icq; GSList *evilhack; + + struct { + guint maxbuddies; /* max users you can watch */ + guint maxwatchers; /* max users who can watch you */ + guint maxpermits; /* max users on permit list */ + guint maxdenies; /* max users on deny list */ + guint maxsiglen; /* max size (bytes) of profile */ + guint maxawaymsglen; /* max size (bytes) of posted away message */ + } rights; }; struct create_room { @@ -244,6 +253,7 @@ static int conninitdone_chat (aim_session_t *, aim_frame_t *, ...); static int conninitdone_chatnav (aim_session_t *, aim_frame_t *, ...); static int gaim_parse_msgerr (aim_session_t *, aim_frame_t *, ...); +static int gaim_parse_locaterights(aim_session_t *, aim_frame_t *, ...); static int gaim_parse_buddyrights(aim_session_t *, aim_frame_t *, ...); static int gaim_parse_locerr (aim_session_t *, aim_frame_t *, ...); static int gaim_icbm_param_info (aim_session_t *, aim_frame_t *, ...); @@ -260,6 +270,7 @@ static int gaim_directim_initiate(aim_session_t *, aim_frame_t *, ...); static int gaim_directim_incoming(aim_session_t *, aim_frame_t *, ...); static int gaim_directim_typing (aim_session_t *, aim_frame_t *, ...); +static int gaim_update_ui (aim_session_t *, aim_frame_t *, ...); static char *msgerrreason[] = { "Invalid error", @@ -309,6 +320,7 @@ g_snprintf(buf, sizeof buf, _("Direct IM with %s closed"), sn); if ((cnv = find_conversation(sn))) write_to_conv(cnv, buf, WFLAG_SYSTEM, NULL, time(NULL), -1); + update_progress(cnv, 100); g_free(dim); /* I guess? I don't see it anywhere else... -- mid */ g_free(sn); @@ -660,6 +672,7 @@ aim_conn_addhandler(sess, bosconn, 0x0009, 0x0003, gaim_bosrights, 0); aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_ACK, AIM_CB_ACK_ACK, NULL, 0); aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_REDIRECT, gaim_handle_redirect, 0); + aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_RIGHTSINFO, gaim_parse_locaterights, 0); aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_RIGHTSINFO, gaim_parse_buddyrights, 0); aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_ONCOMING, gaim_parse_oncoming, 0); aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_OFFGOING, gaim_parse_offgoing, 0); @@ -1108,22 +1121,23 @@ } static int gaim_parse_oncoming(aim_session_t *sess, aim_frame_t *fr, ...) { - aim_userinfo_t *info; - time_t time_idle; - int type = 0; struct gaim_connection *gc = sess->aux_data; struct oscar_data *od = gc->proto_data; + aim_userinfo_t *info; + time_t time_idle = 0, signon = 0; + int type = 0; + int caps = 0; char *tmp; - int caps; va_list ap; va_start(ap, fr); info = va_arg(ap, aim_userinfo_t *); va_end(ap); - caps = info->capabilities; + if (info->present & AIM_USERINFO_PRESENT_CAPABILITIES) + caps = info->capabilities; - if (!od->icq) { + if (!od->icq && (info->present & AIM_USERINFO_PRESENT_FLAGS)) { if (info->flags & AIM_FLAG_ACTIVEBUDDY) type |= UC_AB; if (info->flags & AIM_FLAG_UNCONFIRMED) @@ -1136,29 +1150,31 @@ type |= UC_NORMAL; if (info->flags & AIM_FLAG_AWAY) type |= UC_UNAVAILABLE; - } else { - if (info->icqinfo.status) { - type = (info->icqinfo.status << 6); - if (!(info->icqinfo.status & AIM_ICQ_STATE_CHAT)) - type |= UC_UNAVAILABLE; - } - if (caps & AIM_CAPS_ICQ) - caps ^= AIM_CAPS_ICQ; - debug_printf("icq status: %d\n", info->icqinfo.status); } - if (info->idletime) { + if (info->present & AIM_USERINFO_PRESENT_ICQEXTSTATUS) { + type = (info->icqinfo.status << 6); + if (!(info->icqinfo.status & AIM_ICQ_STATE_CHAT)) + type |= UC_UNAVAILABLE; + } + + if (caps & AIM_CAPS_ICQ) + caps ^= AIM_CAPS_ICQ; + + if (info->present & AIM_USERINFO_PRESENT_IDLE) { time(&time_idle); time_idle -= info->idletime*60; - } else - time_idle = 0; + } + + if (info->present & AIM_USERINFO_PRESENT_SESSIONLEN) + signon = time(NULL) - info->sessionlen; tmp = g_strdup(normalize(gc->username)); if (!strcmp(tmp, normalize(info->sn))) g_snprintf(gc->displayname, sizeof(gc->displayname), "%s", info->sn); g_free(tmp); - serv_got_update(gc, info->sn, 1, info->warnlevel/10, time(NULL) - info->sessionlen, + serv_got_update(gc, info->sn, 1, info->warnlevel/10, signon, time_idle, type, caps); return 1; @@ -1246,7 +1262,8 @@ gaim_directim_incoming, 0); aim_conn_addhandler(od->sess, dim->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING, gaim_directim_typing, 0); - + aim_conn_addhandler(od->sess, dim->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_DOWNLOADIMAGE, + gaim_update_ui, 0); for (i = 0; i < (int)strlen(d->ip); i++) { if (d->ip[i] == ':') { port = atoi(&(d->ip[i+1])); @@ -1668,7 +1685,7 @@ GSList *l = od->evilhack; gboolean evilhack = FALSE; va_list ap; - char *asc; + gchar *membersince = NULL, *onlinesince = NULL, *idle = NULL; va_start(ap, fr); info = va_arg(ap, aim_userinfo_t *); @@ -1685,23 +1702,38 @@ "<IMG SRC=\"admin_icon.gif\"> : Administrator <br>" "<IMG SRC=\"ab_icon.gif\"> : ActiveBuddy Interactive Agent<br>")); - if (info->membersince) - asc = g_strdup_printf("Member Since : <B>%s</B><BR>\n", - asctime(localtime(&info->membersince))); - else - asc = g_strdup(""); + if (info->present & AIM_USERINFO_PRESENT_ONLINESINCE) { + onlinesince = g_strdup_printf("Online Since : <B>%s</B><BR>\n", + asctime(localtime(&info->onlinesince))); + } + + if (info->present & AIM_USERINFO_PRESENT_MEMBERSINCE) { + membersince = g_strdup_printf("Member Since : <B>%s</B><BR>\n", + asctime(localtime(&info->membersince))); + } + + if (info->present & AIM_USERINFO_PRESENT_IDLE) { + idle = g_strdup_printf("Idle : <B>%d minutes</B>", + info->idletime); + } else + idle = g_strdup("Idle: <B>Active</B>"); + g_snprintf(header, sizeof header, _("Username : <B>%s</B> %s <BR>\n" - "%s" "Warning Level : <B>%d %%</B><BR>\n" - "Online Since : <B>%s</B><BR>\n" - "Idle Minutes : <B>%d</B>\n<BR>\n<HR><BR>\n"), + "%s" + "%s" + "%s<BR>\n" + "<HR><BR>\n"), info->sn, images(info->flags), - asc, info->warnlevel/10, - asctime(localtime(&info->onlinesince)), - info->idletime); - g_free(asc); + onlinesince ? onlinesince : "", + membersince ? membersince : "", + idle ? idle : ""); + + g_free(onlinesince); + g_free(membersince); + g_free(idle); while (l) { char *x = l->data; @@ -2040,21 +2072,11 @@ } static int conninitdone_bos(aim_session_t *sess, aim_frame_t *fr, ...) { - struct gaim_connection *gc = sess->aux_data; aim_reqpersonalinfo(sess, fr->conn); aim_bos_reqlocaterights(sess, fr->conn); - aim_bos_setprofile(sess, fr->conn, gc->user->user_info, NULL, gaim_caps); aim_bos_reqbuddyrights(sess, fr->conn); - account_online(gc); - serv_finish_login(gc); - - if (bud_list_cache_exists(gc)) - do_import(gc, NULL); - - debug_printf("buddy list loaded\n"); - aim_reqicbmparams(sess); aim_bos_reqrights(sess, fr->conn); @@ -2133,10 +2155,31 @@ return 1; } -/* XXX this is frivelous... do you really want to know this info? */ +static int gaim_parse_locaterights(aim_session_t *sess, aim_frame_t *fr, ...) +{ + va_list ap; + fu16_t maxsiglen; + struct gaim_connection *gc = sess->aux_data; + struct oscar_data *odata = (struct oscar_data *)gc->proto_data; + + va_start(ap, fr); + maxsiglen = va_arg(ap, int); + va_end(ap); + + debug_printf("locate rights: max sig len = %d\n", maxsiglen); + + odata->rights.maxsiglen = odata->rights.maxawaymsglen = (guint)maxsiglen; + + aim_bos_setprofile(sess, fr->conn, gc->user->user_info, NULL, gaim_caps); + + return 1; +} + static int gaim_parse_buddyrights(aim_session_t *sess, aim_frame_t *fr, ...) { va_list ap; fu16_t maxbuddies, maxwatchers; + struct gaim_connection *gc = sess->aux_data; + struct oscar_data *odata = (struct oscar_data *)gc->proto_data; va_start(ap, fr); maxbuddies = (fu16_t)va_arg(ap, unsigned int); @@ -2145,12 +2188,17 @@ debug_printf("buddy list rights: Max buddies = %d / Max watchers = %d\n", maxbuddies, maxwatchers); + odata->rights.maxbuddies = (guint)maxbuddies; + odata->rights.maxwatchers = (guint)maxwatchers; + return 1; } static int gaim_bosrights(aim_session_t *sess, aim_frame_t *fr, ...) { fu16_t maxpermits, maxdenies; va_list ap; + struct gaim_connection *gc = sess->aux_data; + struct oscar_data *odata = (struct oscar_data *)gc->proto_data; va_start(ap, fr); maxpermits = (fu16_t)va_arg(ap, unsigned int); @@ -2159,6 +2207,17 @@ debug_printf("BOS rights: Max permit = %d / Max deny = %d\n", maxpermits, maxdenies); + odata->rights.maxpermits = (guint)maxpermits; + odata->rights.maxdenies = (guint)maxdenies; + + account_online(gc); + serv_finish_login(gc); + + if (bud_list_cache_exists(gc)) + do_import(gc, NULL); + + debug_printf("buddy list loaded\n"); + aim_clientready(sess, fr->conn); aim_icq_reqofflinemsgs(sess); @@ -2344,6 +2403,23 @@ return "Oscar"; } +static void oscar_send_typing_stopped(struct gaim_connection *gc, char *name) { + struct oscar_data *odata = (struct oscar_data *)gc->proto_data; + struct direct_im *dim = find_direct_im(odata, name); + if (!dim) + return; + aim_send_typing(odata->sess, dim->conn, FALSE); +} + +static int oscar_send_typing(struct gaim_connection *gc, char *name) { + struct oscar_data *odata = (struct oscar_data *)gc->proto_data; + struct direct_im *dim = find_direct_im(odata, name); + if (!dim) + return; + aim_send_typing(odata->sess, dim->conn, TRUE); + return 0; +} + static int oscar_send_im(struct gaim_connection *gc, char *name, char *message, int imflags) { struct oscar_data *odata = (struct oscar_data *)gc->proto_data; struct direct_im *dim = find_direct_im(odata, name); @@ -2447,34 +2523,64 @@ static void oscar_set_info(struct gaim_connection *g, char *info) { struct oscar_data *odata = (struct oscar_data *)g->proto_data; - char inforeal[1025], away[1025]; - g_snprintf(inforeal, sizeof(inforeal), "%s", info); - if (g->away) - g_snprintf(away, sizeof(away), "%s", g->away); - if (strlen(info) > 1024) - do_error_dialog("Maximum info length (1024) exceeded, truncating", "Info Too Long"); - aim_bos_setprofile(odata->sess, odata->conn, inforeal, g->away ? NULL : "", gaim_caps); + gchar *inforeal; + + if (odata->rights.maxsiglen == 0) + do_error_dialog("oscar_set_info called before locate rights received", "Protocol Error"); + + if (strlen(info) > odata->rights.maxsiglen) { + gchar *errstr; + + errstr = g_strdup_printf("Maximum info length of %d bytes exceeded, truncating", odata->rights.maxsiglen); + + do_error_dialog(errstr, "Info Too Long"); + + g_free(errstr); + } + + inforeal = g_strndup(info, odata->rights.maxsiglen); + + aim_bos_setprofile(odata->sess, odata->conn, inforeal, NULL, gaim_caps); + + g_free(inforeal); + + return; } -static void oscar_set_away(struct gaim_connection *gc, char *state, char *message) { - struct oscar_data *od = (struct oscar_data *)gc->proto_data; - char away[1025]; - if (!od->icq) { - if (message) - g_snprintf(away, sizeof(away), "%s", message); - aim_bos_setprofile(od->sess, od->conn, NULL, message ? away : "", gaim_caps); - if (gc->away) - g_free (gc->away); - gc->away = NULL; - if (message) { - if (strlen(message) > sizeof(away)-1) - do_error_dialog("Maximum away length exceeded (1024), truncating", - "Info Too Long"); - gc->away = g_strdup (message); - } +static void oscar_set_away_aim(struct gaim_connection *gc, struct oscar_data *od, const char *message) +{ + + if (od->rights.maxawaymsglen == 0) + do_error_dialog("oscar_set_away_aim called before locate rights received", "Protocol Error"); + + if (gc->away) + g_free(gc->away); + gc->away = NULL; + + if (!message) { + aim_bos_setprofile(od->sess, od->conn, NULL, "", gaim_caps); return; } + if (strlen(message) > od->rights.maxawaymsglen) { + gchar *errstr; + + errstr = g_strdup_printf("Maximum away message length of %d bytes exceeded, truncating", od->rights.maxawaymsglen); + + do_error_dialog(errstr, "Away Message Too Long"); + + g_free(errstr); + } + + gc->away = g_strndup(message, od->rights.maxawaymsglen); + aim_bos_setprofile(od->sess, od->conn, NULL, gc->away, gaim_caps); + + return; +} + +static void oscar_set_away_icq(struct gaim_connection *gc, struct oscar_data *od, const char *state, const char *message) +{ + if (gc->away) gc->away = NULL; @@ -2506,6 +2612,20 @@ aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_NORMAL); } } + + return; +} + +static void oscar_set_away(struct gaim_connection *gc, char *state, char *message) +{ + struct oscar_data *od = (struct oscar_data *)gc->proto_data; + + if (od->icq) + oscar_set_away_icq(gc, od, state, message); + else + oscar_set_away_aim(gc, od, message); + + return; } static void oscar_warn(struct gaim_connection *g, char *name, int anon) { @@ -3002,6 +3122,31 @@ gaim_directim_incoming, 0); aim_conn_addhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING, gaim_directim_typing, 0); + aim_conn_addhandler(od->sess, dim->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_DOWNLOADIMAGE, + gaim_update_ui, 0); + return 1; +} + +static int gaim_update_ui(aim_session_t *sess, aim_frame_t *fr, ...) { + va_list ap; + char *sn; + double percent; + struct gaim_connection *gc = sess->aux_data; + struct oscar_data *od = (struct oscar_data *)gc->proto_data; + struct conversation *c; + struct direct_im *dim; + + va_start(ap, fr); + sn = va_arg(ap, char *); + percent = va_arg(ap, double); + va_end(ap); + + dim = find_direct_im(od, sn); + gaim_input_remove(dim->watcher); /* Otherwise, the callback will callback */ + if ((c = find_conversation(sn))) + update_progress(c, percent); + dim->watcher = gaim_input_add(dim->conn->fd, GAIM_INPUT_READ, + oscar_callback, dim->conn); return 1; } @@ -3009,16 +3154,18 @@ static int gaim_directim_incoming(aim_session_t *sess, aim_frame_t *fr, ...) { va_list ap; char *msg, *sn; + int len; struct gaim_connection *gc = sess->aux_data; va_start(ap, fr); sn = va_arg(ap, char *); msg = va_arg(ap, char *); + len = va_arg(ap, int); va_end(ap); debug_printf("Got DirectIM message from %s\n", sn); - serv_got_im(gc, sn, msg, 0, time(NULL), -1); + serv_got_im(gc, sn, msg, 0, time(NULL), len); return 1; } @@ -3026,14 +3173,20 @@ static int gaim_directim_typing(aim_session_t *sess, aim_frame_t *fr, ...) { va_list ap; char *sn; + int typing; + struct gaim_connection *gc = sess->aux_data; va_start(ap, fr); sn = va_arg(ap, char *); + typing = va_arg(ap, int); va_end(ap); - /* I had to leave this. It's just too funny. It reminds me of my sister. */ - debug_printf("ohmigod! %s has started typing (DirectIM). He's going to send you a message! *squeal*\n", sn); - + if (typing) { + /* I had to leave this. It's just too funny. It reminds me of my sister. */ + debug_printf("ohmigod! %s has started typing (DirectIM). He's going to send you a message! *squeal*\n", sn); + serv_got_typing(gc,sn,0); + } else + serv_got_typing_stopped(gc,sn); return 1; } @@ -3364,6 +3517,8 @@ ret->login = oscar_login; ret->close = oscar_close; ret->send_im = oscar_send_im; + ret->send_typing = oscar_send_typing; + ret->send_typing_stopped = oscar_send_typing_stopped; ret->set_info = oscar_set_info; ret->get_info = oscar_get_info; ret->set_away = oscar_set_away; |