comparison src/protocols/oscar/oscar.c @ 4738:34fdf9e313d5

[gaim-migrate @ 5053] I combined some hash tables in oscar.c to make things a bit neater. Funtionality-wise, I made "online since" show up in the oscar per-buddy tooltip thing, fixed the buddy selection file browser dialog thing so the default file is blank and it puts you in the correct directory (it is more similar to how gtkft.c does it), and I made it so buddy icons will only be requested/advertised when needed, rather than for every single message. Hopefully this will make it so the icon is not re-sent for every message. And hopefully I didn't break anything. HEY YOU Find out why "Capabilities" is not indeded like "Online Since" in the tooltip. committer: Tailor Script <tailor@pidgin.im>
author Mark Doliner <mark@kingant.net>
date Thu, 13 Mar 2003 08:42:06 +0000
parents ece4045eebff
children 5c720bc4c23d
comparison
equal deleted inserted replaced
4737:da3c96faa167 4738:34fdf9e313d5
107 char *newp; 107 char *newp;
108 108
109 GSList *oscar_chats; 109 GSList *oscar_chats;
110 GSList *direct_ims; 110 GSList *direct_ims;
111 GSList *file_transfers; 111 GSList *file_transfers;
112 GSList *hasicons; 112 GHashTable *buddyinfo;
113 GHashTable *supports_tn;
114 GHashTable *buddy_caps;
115 113
116 gboolean killme; 114 gboolean killme;
117 gboolean icq; 115 gboolean icq;
118 GSList *evilhack; 116 GSList *evilhack;
119 117
173 aim_conn_t *conn; 171 aim_conn_t *conn;
174 struct gaim_xfer *xfer; 172 struct gaim_xfer *xfer;
175 struct gaim_connection *gc; 173 struct gaim_connection *gc;
176 }; 174 };
177 175
178 struct icon_req { 176 /* Various PRPL-specific buddy info that we want to keep track of */
179 char *user; 177 struct buddyinfo {
180 time_t timestamp; 178 time_t signon;
181 unsigned long length; 179 int caps;
182 unsigned long checksum; 180 gboolean typingnot;
183 gboolean request; 181
182 unsigned long ico_len;
183 unsigned long ico_csum;
184 time_t ico_time;
185 gboolean ico_need;
186
187 unsigned long ico_me_len;
188 unsigned long ico_me_csum;
189 time_t ico_me_time;
190 gboolean ico_informed;
184 }; 191 };
185 192
186 struct name_data { 193 struct name_data {
187 struct gaim_connection *gc; 194 struct gaim_connection *gc;
188 gchar *name; 195 gchar *name;
547 gc->password[8] = 0; 554 gc->password[8] = 0;
548 } else { 555 } else {
549 gc->flags |= OPT_CONN_HTML; 556 gc->flags |= OPT_CONN_HTML;
550 gc->flags |= OPT_CONN_AUTO_RESP; 557 gc->flags |= OPT_CONN_AUTO_RESP;
551 } 558 }
552 od->supports_tn = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); 559 od->buddyinfo = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
553 od->buddy_caps = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
554 560
555 sess = g_new0(aim_session_t, 1); 561 sess = g_new0(aim_session_t, 1);
556 562
557 aim_session_init(sess, AIM_SESS_FLAGS_NONBLOCKCONNECT, 0); 563 aim_session_init(sess, AIM_SESS_FLAGS_NONBLOCKCONNECT, 0);
558 aim_setdebuggingcb(sess, oscar_debug); 564 aim_setdebuggingcb(sess, oscar_debug);
616 struct gaim_xfer *xfer; 622 struct gaim_xfer *xfer;
617 xfer = (struct gaim_xfer *)od->file_transfers->data; 623 xfer = (struct gaim_xfer *)od->file_transfers->data;
618 gaim_xfer_destroy(xfer); 624 gaim_xfer_destroy(xfer);
619 } 625 }
620 626
621 while (od->hasicons) { 627 g_hash_table_destroy(od->buddyinfo);
622 struct icon_req *n = od->hasicons->data;
623 g_free(n->user);
624 od->hasicons = g_slist_remove(od->hasicons, n);
625 g_free(n);
626 }
627 g_hash_table_destroy(od->supports_tn);
628 g_hash_table_destroy(od->buddy_caps);
629 while (od->evilhack) { 628 while (od->evilhack) {
630 g_free(od->evilhack->data); 629 g_free(od->evilhack->data);
631 od->evilhack = g_slist_remove(od->evilhack, od->evilhack->data); 630 od->evilhack = g_slist_remove(od->evilhack, od->evilhack->data);
632 } 631 }
633 while (od->create_rooms) { 632 while (od->create_rooms) {
1579 } 1578 }
1580 1579
1581 static int gaim_parse_oncoming(aim_session_t *sess, aim_frame_t *fr, ...) { 1580 static int gaim_parse_oncoming(aim_session_t *sess, aim_frame_t *fr, ...) {
1582 struct gaim_connection *gc = sess->aux_data; 1581 struct gaim_connection *gc = sess->aux_data;
1583 struct oscar_data *od = gc->proto_data; 1582 struct oscar_data *od = gc->proto_data;
1584 aim_userinfo_t *info; 1583 struct buddyinfo *bi;
1585 time_t time_idle = 0, signon = 0; 1584 time_t time_idle = 0, signon = 0;
1586 int type = 0; 1585 int type = 0;
1587 int caps = 0; 1586 int caps = 0;
1588 va_list ap; 1587 va_list ap;
1588 aim_userinfo_t *info;
1589 1589
1590 va_start(ap, fr); 1590 va_start(ap, fr);
1591 info = va_arg(ap, aim_userinfo_t *); 1591 info = va_arg(ap, aim_userinfo_t *);
1592 va_end(ap); 1592 va_end(ap);
1593 1593
1630 signon = time(NULL) - info->sessionlen; 1630 signon = time(NULL) - info->sessionlen;
1631 1631
1632 if (!aim_sncmp(gc->username, info->sn)) 1632 if (!aim_sncmp(gc->username, info->sn))
1633 g_snprintf(gc->displayname, sizeof(gc->displayname), "%s", info->sn); 1633 g_snprintf(gc->displayname, sizeof(gc->displayname), "%s", info->sn);
1634 1634
1635 g_hash_table_replace(od->buddy_caps, g_strdup(normalize(info->sn)), 1635 bi = g_hash_table_lookup(od->buddyinfo, normalize(info->sn));
1636 GINT_TO_POINTER(caps)); 1636 if (!bi) {
1637 bi = g_new0(struct buddyinfo, 1);
1638 g_hash_table_insert(od->buddyinfo, g_strdup(normalize(info->sn)), bi);
1639 }
1640 bi->signon = info->onlinesince ? info->onlinesince : (info->sessionlen + time(NULL));
1641 bi->caps = caps;
1637 1642
1638 serv_got_update(gc, info->sn, 1, info->warnlevel/10, signon, 1643 serv_got_update(gc, info->sn, 1, info->warnlevel/10, signon,
1639 time_idle, type); 1644 time_idle, type);
1640 1645
1641 return 1; 1646 return 1;
1934 1939
1935 return; 1940 return;
1936 } 1941 }
1937 1942
1938 static int incomingim_chan1(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch1_args *args) { 1943 static int incomingim_chan1(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch1_args *args) {
1939 char *tmp;
1940 struct gaim_connection *gc = sess->aux_data; 1944 struct gaim_connection *gc = sess->aux_data;
1941 struct oscar_data *od = gc->proto_data; 1945 struct oscar_data *od = gc->proto_data;
1946 char *tmp;
1942 int flags = 0; 1947 int flags = 0;
1943 int convlen; 1948 int convlen;
1944 GError *err = NULL; 1949 GError *err = NULL;
1950 struct buddyinfo *bi;
1951
1952 bi = g_hash_table_lookup(od->buddyinfo, normalize(userinfo->sn));
1953 if (!bi) {
1954 bi = g_new0(struct buddyinfo, 1);
1955 g_hash_table_insert(od->buddyinfo, g_strdup(normalize(userinfo->sn)), bi);
1956 }
1945 1957
1946 if (args->icbmflags & AIM_IMFLAGS_AWAY) 1958 if (args->icbmflags & AIM_IMFLAGS_AWAY)
1947 flags |= IM_FLAG_AWAY; 1959 flags |= IM_FLAG_AWAY;
1948 1960
1961 if (args->icbmflags & AIM_IMFLAGS_TYPINGNOT)
1962 bi->typingnot = TRUE;
1963 else
1964 bi->typingnot = FALSE;
1965
1949 if ((args->icbmflags & AIM_IMFLAGS_HASICON) && (args->iconlen) && (args->iconsum) && (args->iconstamp)) { 1966 if ((args->icbmflags & AIM_IMFLAGS_HASICON) && (args->iconlen) && (args->iconsum) && (args->iconstamp)) {
1950 struct icon_req *ir = NULL;
1951 GSList *h = od->hasicons;
1952
1953 debug_printf("%s has an icon\n", userinfo->sn); 1967 debug_printf("%s has an icon\n", userinfo->sn);
1954 while (h) { 1968 if ((args->iconlen != bi->ico_len) || (args->iconsum != bi->ico_csum) || (args->iconstamp != bi->ico_time)) {
1955 ir = h->data; 1969 bi->ico_need = TRUE;
1956 if (!aim_sncmp(userinfo->sn, ir->user)) 1970 bi->ico_len = args->iconlen;
1957 break; 1971 bi->ico_csum = args->iconsum;
1958 h = h->next; 1972 bi->ico_time = args->iconstamp;
1959 } 1973 }
1960 if (!h) {
1961 ir = g_new0(struct icon_req, 1);
1962 ir->user = g_strdup(normalize(userinfo->sn));
1963 od->hasicons = g_slist_append(od->hasicons, ir);
1964 }
1965 if ((args->iconlen != ir->length) ||
1966 (args->iconsum != ir->checksum) ||
1967 (args->iconstamp != ir->timestamp))
1968 ir->request = TRUE;
1969 ir->length = args->iconlen;
1970 ir->checksum = args->iconsum;
1971 ir->timestamp = args->iconstamp;
1972 } 1974 }
1973 1975
1974 if (gc->account->iconfile[0] && (args->icbmflags & AIM_IMFLAGS_BUDDYREQ)) { 1976 if (gc->account->iconfile[0] && (args->icbmflags & AIM_IMFLAGS_BUDDYREQ)) {
1975 FILE *file; 1977 FILE *file;
1976 struct stat st; 1978 struct stat st;
2028 tmp = g_convert(args->msg, args->msglen, "UTF-8", "ISO-8859-1", NULL, &convlen, &err); 2030 tmp = g_convert(args->msg, args->msglen, "UTF-8", "ISO-8859-1", NULL, &convlen, &err);
2029 if (err) { 2031 if (err) {
2030 debug_printf("ISO-8859-1 IM conversion: %s\n", err->message); 2032 debug_printf("ISO-8859-1 IM conversion: %s\n", err->message);
2031 tmp = strdup(_("(There was an error receiving this message)")); 2033 tmp = strdup(_("(There was an error receiving this message)"));
2032 } 2034 }
2033 }
2034
2035 if (args->icbmflags & AIM_IMFLAGS_TYPINGNOT) {
2036 char *who = g_strdup(normalize(userinfo->sn));
2037 if (!g_hash_table_lookup(od->supports_tn, who))
2038 g_hash_table_insert(od->supports_tn, who, (gpointer)1);
2039 } 2035 }
2040 2036
2041 /* strip_linefeed(tmp); */ 2037 /* strip_linefeed(tmp); */
2042 serv_got_im(gc, userinfo->sn, tmp, flags, time(NULL), -1); 2038 serv_got_im(gc, userinfo->sn, tmp, flags, time(NULL), -1);
2043 g_free(tmp); 2039 g_free(tmp);
2855 } 2851 }
2856 return buf; 2852 return buf;
2857 } 2853 }
2858 2854
2859 static char *oscar_tooltip_text(struct buddy *b) { 2855 static char *oscar_tooltip_text(struct buddy *b) {
2860 struct oscar_data *od = b->account->gc->proto_data; 2856 struct gaim_connection *gc = b->account->gc;
2861 guint caps = GPOINTER_TO_INT(g_hash_table_lookup(od->buddy_caps, 2857 struct oscar_data *od = gc->proto_data;
2862 normalize(b->name))); 2858 struct buddyinfo *bi = g_hash_table_lookup(od->buddyinfo, normalize(b->name));
2863 2859
2864 return g_strdup_printf(_("<b>Capabilities:</b> %s"), caps_string(caps)); 2860 if (bi)
2861 return g_strdup_printf(_("<b>Online Since</b> %s<b>Capabilities:</b> %s"), asctime(localtime(&bi->signon)), caps_string(bi->caps));
2862 else
2863 return NULL;
2865 } 2864 }
2866 2865
2867 static int gaim_parse_user_info(aim_session_t *sess, aim_frame_t *fr, ...) { 2866 static int gaim_parse_user_info(aim_session_t *sess, aim_frame_t *fr, ...) {
2868 aim_userinfo_t *info; 2867 aim_userinfo_t *info;
2869 char *text_enc = NULL, *text = NULL, *utf8 = NULL; 2868 char *text_enc = NULL, *text = NULL, *utf8 = NULL;
3802 struct oscar_data *od = (struct oscar_data *)gc->proto_data; 3801 struct oscar_data *od = (struct oscar_data *)gc->proto_data;
3803 struct direct_im *dim = find_direct_im(od, name); 3802 struct direct_im *dim = find_direct_im(od, name);
3804 if (dim) 3803 if (dim)
3805 aim_odc_send_typing(od->sess, dim->conn, typing); 3804 aim_odc_send_typing(od->sess, dim->conn, typing);
3806 else { 3805 else {
3807 if (g_hash_table_lookup(od->supports_tn, normalize(name))) { 3806 struct buddyinfo *bi = g_hash_table_lookup(od->buddyinfo, normalize(name));
3807 if (bi && bi->typingnot) {
3808 if (typing == TYPING) 3808 if (typing == TYPING)
3809 aim_im_sendmtn(od->sess, 0x0001, name, 0x0002); 3809 aim_im_sendmtn(od->sess, 0x0001, name, 0x0002);
3810 else if (typing == TYPED) 3810 else if (typing == TYPED)
3811 aim_im_sendmtn(od->sess, 0x0001, name, 0x0001); 3811 aim_im_sendmtn(od->sess, 0x0001, name, 0x0001);
3812 else 3812 else
3835 } else if (len != -1) { 3835 } else if (len != -1) {
3836 /* Trying to send an IM image outside of a direct connection. */ 3836 /* Trying to send an IM image outside of a direct connection. */
3837 oscar_ask_direct_im(gc, name); 3837 oscar_ask_direct_im(gc, name);
3838 return -ENOTCONN; 3838 return -ENOTCONN;
3839 } 3839 }
3840
3840 if (imflags & IM_FLAG_AWAY) { 3841 if (imflags & IM_FLAG_AWAY) {
3841 ret = aim_im_sendch1(od->sess, name, AIM_IMFLAGS_AWAY, message); 3842 ret = aim_im_sendch1(od->sess, name, AIM_IMFLAGS_AWAY, message);
3842 } else { 3843 } else {
3844 struct buddyinfo *bi;
3843 struct aim_sendimext_args args; 3845 struct aim_sendimext_args args;
3844 GSList *h = od->hasicons;
3845 struct icon_req *ir = NULL;
3846 char *who = normalize(name);
3847 struct stat st; 3846 struct stat st;
3848 int len; 3847 int len;
3848
3849 bi = g_hash_table_lookup(od->buddyinfo, normalize(name));
3850 if (!bi) {
3851 bi = g_new0(struct buddyinfo, 1);
3852 g_hash_table_insert(od->buddyinfo, g_strdup(normalize(name)), bi);
3853 }
3849 3854
3850 args.flags = AIM_IMFLAGS_ACK | AIM_IMFLAGS_CUSTOMFEATURES; 3855 args.flags = AIM_IMFLAGS_ACK | AIM_IMFLAGS_CUSTOMFEATURES;
3851 if (od->icq) { 3856 if (od->icq) {
3852 args.features = features_icq; 3857 args.features = features_icq;
3853 args.featureslen = sizeof(features_icq); 3858 args.featureslen = sizeof(features_icq);
3855 } else { 3860 } else {
3856 args.features = features_aim; 3861 args.features = features_aim;
3857 args.featureslen = sizeof(features_aim); 3862 args.featureslen = sizeof(features_aim);
3858 } 3863 }
3859 3864
3860 while (h) { 3865 if (bi->ico_need) {
3861 ir = h->data; 3866 debug_printf("Sending buddy icon request with message\n");
3862 if (ir->request && !strcmp(who, ir->user))
3863 break;
3864 h = h->next;
3865 }
3866 if (h) {
3867 ir->request = FALSE;
3868 args.flags |= AIM_IMFLAGS_BUDDYREQ; 3867 args.flags |= AIM_IMFLAGS_BUDDYREQ;
3869 debug_printf("sending buddy icon request with message\n"); 3868 bi->ico_need = FALSE;
3870 } 3869 }
3871 3870
3872 if (gc->account->iconfile[0] && !stat(gc->account->iconfile, &st)) { 3871 if (gc->account->iconfile[0] && !stat(gc->account->iconfile, &st)) {
3873 FILE *file = fopen(gc->account->iconfile, "r"); 3872 FILE *file = fopen(gc->account->iconfile, "r");
3874 if (file) { 3873 if (file) {
3877 3876
3878 args.iconlen = st.st_size; 3877 args.iconlen = st.st_size;
3879 args.iconsum = aimutil_iconsum(buf, st.st_size); 3878 args.iconsum = aimutil_iconsum(buf, st.st_size);
3880 args.iconstamp = st.st_mtime; 3879 args.iconstamp = st.st_mtime;
3881 3880
3882 args.flags |= AIM_IMFLAGS_HASICON; 3881 if ((args.iconlen != bi->ico_me_len) || (args.iconsum != bi->ico_me_csum) || (args.iconstamp != bi->ico_me_time))
3883 debug_printf("Claiming to have an icon.\n"); 3882 bi->ico_informed = FALSE;
3883
3884 if (!bi->ico_informed) {
3885 debug_printf("Claiming to have a buddy icon\n");
3886 args.flags |= AIM_IMFLAGS_HASICON;
3887 bi->ico_me_len = args.iconlen;
3888 bi->ico_me_csum = args.iconsum;
3889 bi->ico_me_time = args.iconstamp;
3890 bi->ico_informed = TRUE;
3891 }
3892
3884 3893
3885 fclose(file); 3894 fclose(file);
3886 g_free(buf); 3895 g_free(buf);
3887 } 3896 }
3888 } 3897 }