Mercurial > pidgin
comparison libpurple/protocols/oscar/oscar.c @ 25947:4b8c4870b13a
propagate from branch 'im.pidgin.pidgin.next.minor' (head 7305b29db7bd00d3261f348c71674c93aa31b327)
to branch 'im.pidgin.pidgin' (head d8c03c68d591d9392607d954942ee58b8618d946)
author | Elliott Sales de Andrade <qulogic@pidgin.im> |
---|---|
date | Mon, 02 Mar 2009 04:18:40 +0000 |
parents | 8c8948b9f602 937d832f4d7f |
children | cc9fb95cede5 |
comparison
equal
deleted
inserted
replaced
25946:8998ca47e6d0 | 25947:4b8c4870b13a |
---|---|
2075 g_free(host); | 2075 g_free(host); |
2076 | 2076 |
2077 return 1; | 2077 return 1; |
2078 } | 2078 } |
2079 | 2079 |
2080 static gboolean purple_requesticqstatusnote(gpointer data) | |
2081 { | |
2082 PurpleConnection *gc = data; | |
2083 OscarData *od = purple_connection_get_protocol_data(gc); | |
2084 | |
2085 while (od->statusnotes_queue != NULL) | |
2086 { | |
2087 char *bn; | |
2088 struct aim_ssi_item *ssi_item; | |
2089 aim_tlv_t *note_hash; | |
2090 | |
2091 bn = od->statusnotes_queue->data; | |
2092 | |
2093 ssi_item = aim_ssi_itemlist_finditem(od->ssi.local, | |
2094 NULL, bn, AIM_SSI_TYPE_BUDDY); | |
2095 if (ssi_item != NULL) | |
2096 { | |
2097 note_hash = aim_tlv_gettlv(ssi_item->data, 0x015c, 1); | |
2098 if (note_hash != NULL) { | |
2099 aim_icq_getstatusnote(od, bn, note_hash->value, note_hash->length); | |
2100 } | |
2101 } | |
2102 | |
2103 od->statusnotes_queue = g_slist_remove(od->statusnotes_queue, bn); | |
2104 g_free(bn); | |
2105 } | |
2106 | |
2107 od->statusnotes_queue_timer = 0; | |
2108 return FALSE; | |
2109 } | |
2110 | |
2111 | 2080 |
2112 static int purple_parse_oncoming(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) | 2081 static int purple_parse_oncoming(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) |
2113 { | 2082 { |
2114 PurpleConnection *gc; | 2083 PurpleConnection *gc; |
2115 PurpleAccount *account; | 2084 PurpleAccount *account; |
2118 int type = 0; | 2087 int type = 0; |
2119 gboolean buddy_is_away = FALSE; | 2088 gboolean buddy_is_away = FALSE; |
2120 const char *status_id; | 2089 const char *status_id; |
2121 va_list ap; | 2090 va_list ap; |
2122 aim_userinfo_t *info; | 2091 aim_userinfo_t *info; |
2092 char *message = NULL; | |
2093 char *itmsurl = NULL; | |
2094 char *tmp; | |
2095 const char *tmp2; | |
2123 | 2096 |
2124 gc = od->gc; | 2097 gc = od->gc; |
2125 account = purple_connection_get_account(gc); | 2098 account = purple_connection_get_account(gc); |
2126 | 2099 |
2127 va_start(ap, fr); | 2100 va_start(ap, fr); |
2172 purple_prpl_got_user_status(account, info->bn, OSCAR_STATUS_ID_MOBILE, NULL); | 2145 purple_prpl_got_user_status(account, info->bn, OSCAR_STATUS_ID_MOBILE, NULL); |
2173 } else { | 2146 } else { |
2174 purple_prpl_got_user_status_deactive(account, info->bn, OSCAR_STATUS_ID_MOBILE); | 2147 purple_prpl_got_user_status_deactive(account, info->bn, OSCAR_STATUS_ID_MOBILE); |
2175 } | 2148 } |
2176 | 2149 |
2177 if (strcmp(status_id, OSCAR_STATUS_ID_AVAILABLE) == 0) | 2150 if (info->status != NULL && info->status[0] != '\0') |
2178 { | 2151 /* Grab the available message */ |
2179 char *message = NULL; | 2152 message = oscar_encoding_to_utf8(account, info->status_encoding, |
2180 char *itmsurl = NULL; | 2153 info->status, info->status_len); |
2181 char *tmp; | 2154 |
2182 const char *tmp2; | 2155 tmp2 = tmp = (message ? g_markup_escape_text(message, -1) : NULL); |
2183 | 2156 |
2184 if (info->status != NULL && info->status[0] != '\0') | 2157 if (strcmp(status_id, OSCAR_STATUS_ID_AVAILABLE) == 0) { |
2185 /* Grab the available message */ | |
2186 message = oscar_encoding_to_utf8(account, info->status_encoding, | |
2187 info->status, info->status_len); | |
2188 | |
2189 if (info->itmsurl_encoding && info->itmsurl && info->itmsurl_len) | 2158 if (info->itmsurl_encoding && info->itmsurl && info->itmsurl_len) |
2190 /* Grab the iTunes Music Store URL */ | 2159 /* Grab the iTunes Music Store URL */ |
2191 itmsurl = oscar_encoding_to_utf8(account, info->itmsurl_encoding, | 2160 itmsurl = oscar_encoding_to_utf8(account, info->itmsurl_encoding, |
2192 info->itmsurl, info->itmsurl_len); | 2161 info->itmsurl, info->itmsurl_len); |
2193 | |
2194 tmp2 = tmp = (message ? g_markup_escape_text(message, -1) : NULL); | |
2195 | 2162 |
2196 if (tmp2 == NULL && itmsurl != NULL) | 2163 if (tmp2 == NULL && itmsurl != NULL) |
2164 /* | |
2165 * The message can't be NULL because NULL means it was the | |
2166 * last attribute, so the itmsurl would get ignored below. | |
2167 */ | |
2197 tmp2 = ""; | 2168 tmp2 = ""; |
2198 | 2169 |
2199 purple_prpl_got_user_status(account, info->bn, status_id, | 2170 purple_prpl_got_user_status(account, info->bn, status_id, |
2200 "message", tmp2, "itmsurl", itmsurl, NULL); | 2171 "message", tmp2, "itmsurl", itmsurl, NULL); |
2201 g_free(tmp); | |
2202 | |
2203 g_free(message); | |
2204 g_free(itmsurl); | |
2205 } | 2172 } |
2206 else | 2173 else |
2207 { | 2174 purple_prpl_got_user_status(account, info->bn, status_id, "message", tmp2, NULL); |
2208 PurpleBuddy *b = purple_find_buddy(account, info->bn); | 2175 |
2209 PurplePresence *presence = purple_buddy_get_presence(b); | 2176 g_free(tmp); |
2210 PurpleStatus *old_status = purple_presence_get_active_status(presence); | 2177 |
2211 PurpleStatus *new_status = purple_presence_get_status(presence, status_id); | 2178 g_free(message); |
2212 | 2179 g_free(itmsurl); |
2213 /* If our status_id would change with this update, pass it to the core. | |
2214 * However, if our status_id would not change, do nothing, as we would clear out any existing | |
2215 * attributes on the status prematurely. purple_got_infoblock() will update the message as needed. | |
2216 */ | |
2217 if (old_status != new_status) | |
2218 purple_prpl_got_user_status(account, info->bn, status_id, NULL); | |
2219 } | |
2220 | 2180 |
2221 /* Login time stuff */ | 2181 /* Login time stuff */ |
2222 if (info->present & AIM_USERINFO_PRESENT_ONLINESINCE) | 2182 if (info->present & AIM_USERINFO_PRESENT_ONLINESINCE) |
2223 signon = info->onlinesince; | 2183 signon = info->onlinesince; |
2224 else if (info->present & AIM_USERINFO_PRESENT_SESSIONLEN) | 2184 else if (info->present & AIM_USERINFO_PRESENT_SESSIONLEN) |
2267 g_strdup(purple_normalize(account, info->bn))); | 2227 g_strdup(purple_normalize(account, info->bn))); |
2268 purple_icons_fetch(gc); | 2228 purple_icons_fetch(gc); |
2269 } | 2229 } |
2270 } | 2230 } |
2271 g_free(b16); | 2231 g_free(b16); |
2272 } | |
2273 | |
2274 /* | |
2275 * If we didn't receive a status message with the status change, | |
2276 * or if the message is empty, and we have a note hash, then | |
2277 * query the ICQ6 status note. | |
2278 * | |
2279 * TODO: We should probably always query the status note regardless | |
2280 * of whether they have a status message set, and we should | |
2281 * figure out a way to display both the status note and the | |
2282 * status message at the same time. | |
2283 */ | |
2284 if (info->status == NULL || info->status[0] == '\0') | |
2285 { | |
2286 struct aim_ssi_item *ssi_item; | |
2287 aim_tlv_t *note_hash; | |
2288 | |
2289 ssi_item = aim_ssi_itemlist_finditem(od->ssi.local, | |
2290 NULL, info->bn, AIM_SSI_TYPE_BUDDY); | |
2291 if (ssi_item != NULL) | |
2292 { | |
2293 note_hash = aim_tlv_gettlv(ssi_item->data, 0x015c, 1); | |
2294 if (note_hash != NULL) { | |
2295 /* We do automatic rate limiting at the FLAP level, so | |
2296 * a flood of requests won't disconnect us. However, | |
2297 * it WOULD mean that we would have to wait a | |
2298 * potentially long time to be able to message in real | |
2299 * time again. Also, since we're requesting with every | |
2300 * purple_parse_oncoming() call, which often come in | |
2301 * groups, we should coalesce to do only one lookup per | |
2302 * buddy. | |
2303 */ | |
2304 if (od->statusnotes_queue == NULL || | |
2305 g_slist_find_custom(od->statusnotes_queue, info->bn, (GCompareFunc)strcmp) == NULL) | |
2306 { | |
2307 od->statusnotes_queue = g_slist_prepend(od->statusnotes_queue, | |
2308 g_strdup(info->bn)); | |
2309 | |
2310 if (od->statusnotes_queue_timer > 0) | |
2311 purple_timeout_remove(od->statusnotes_queue_timer); | |
2312 od->statusnotes_queue_timer = purple_timeout_add_seconds(3, | |
2313 purple_requesticqstatusnote, gc); | |
2314 } | |
2315 } | |
2316 } | |
2317 } | 2232 } |
2318 | 2233 |
2319 return 1; | 2234 return 1; |
2320 } | 2235 } |
2321 | 2236 |
4516 msg = g_string_append_len(msg, data->str, data->len); | 4431 msg = g_string_append_len(msg, data->str, data->len); |
4517 msg = g_string_append(msg, "</BINARY>"); | 4432 msg = g_string_append(msg, "</BINARY>"); |
4518 } | 4433 } |
4519 g_string_free(data, TRUE); | 4434 g_string_free(data, TRUE); |
4520 | 4435 |
4521 peer_odc_send_im(conn, msg->str, msg->len, charset, imflags); | 4436 peer_odc_send_im(conn, msg->str, msg->len, charset, (imflags & PURPLE_MESSAGE_AUTO_RESP)); |
4522 g_string_free(msg, TRUE); | 4437 g_string_free(msg, TRUE); |
4523 } | 4438 } |
4524 | 4439 |
4525 int | 4440 int |
4526 oscar_send_im(PurpleConnection *gc, const char *name, const char *message, PurpleMessageFlags imflags) | 4441 oscar_send_im(PurpleConnection *gc, const char *name, const char *message, PurpleMessageFlags imflags) |
4556 | 4471 |
4557 conn = peer_connection_find_by_type(od, name, OSCAR_CAPABILITY_DIRECTIM); | 4472 conn = peer_connection_find_by_type(od, name, OSCAR_CAPABILITY_DIRECTIM); |
4558 if ((conn != NULL) && (conn->ready)) | 4473 if ((conn != NULL) && (conn->ready)) |
4559 { | 4474 { |
4560 /* If we're directly connected, send a direct IM */ | 4475 /* If we're directly connected, send a direct IM */ |
4476 purple_debug_info("oscar", "Sending direct IM with flags %i", imflags); | |
4561 purple_odc_send_im(conn, tmp1, imflags); | 4477 purple_odc_send_im(conn, tmp1, imflags); |
4562 } else { | 4478 } else { |
4563 struct buddyinfo *bi; | 4479 struct buddyinfo *bi; |
4564 struct aim_sendimext_args args; | 4480 struct aim_sendimext_args args; |
4565 PurpleConversation *conv; | 4481 PurpleConversation *conv; |
4877 | 4793 |
4878 status_html = purple_status_get_attr_string(status, "message"); | 4794 status_html = purple_status_get_attr_string(status, "message"); |
4879 if (status_html != NULL) | 4795 if (status_html != NULL) |
4880 { | 4796 { |
4881 status_text = purple_markup_strip_html(status_html); | 4797 status_text = purple_markup_strip_html(status_html); |
4882 /* If the status_text is longer than 60 character then truncate it */ | 4798 /* If the status_text is longer than 251 characters then truncate it */ |
4883 if (strlen(status_text) > MAXAVAILMSGLEN) | 4799 if (strlen(status_text) > MAXAVAILMSGLEN) |
4884 { | 4800 { |
4885 char *tmp = g_utf8_find_prev_char(status_text, &status_text[MAXAVAILMSGLEN - 2]); | 4801 char *tmp = g_utf8_find_prev_char(status_text, &status_text[MAXAVAILMSGLEN - 2]); |
4886 strcpy(tmp, "..."); | 4802 strcpy(tmp, "..."); |
4887 } | 4803 } |
4894 /* This is needed for us to un-set any previous away message. */ | 4810 /* This is needed for us to un-set any previous away message. */ |
4895 away = g_strdup(""); | 4811 away = g_strdup(""); |
4896 } | 4812 } |
4897 else | 4813 else |
4898 { | 4814 { |
4815 char *status_text = NULL; | |
4816 | |
4899 htmlaway = purple_status_get_attr_string(status, "message"); | 4817 htmlaway = purple_status_get_attr_string(status, "message"); |
4900 if ((htmlaway == NULL) || (*htmlaway == '\0')) | 4818 if ((htmlaway == NULL) || (*htmlaway == '\0')) |
4901 htmlaway = purple_status_type_get_name(status_type); | 4819 htmlaway = purple_status_type_get_name(status_type); |
4820 | |
4821 /* ICQ 6.x seems to use an available message for all statuses so set one */ | |
4822 if (od->icq) | |
4823 { | |
4824 status_text = purple_markup_strip_html(htmlaway); | |
4825 /* If the status_text is longer than 251 characters then truncate it */ | |
4826 if (strlen(status_text) > MAXAVAILMSGLEN) | |
4827 { | |
4828 char *tmp = g_utf8_find_prev_char(status_text, &status_text[MAXAVAILMSGLEN - 2]); | |
4829 strcpy(tmp, "..."); | |
4830 } | |
4831 aim_srv_setextrainfo(od, FALSE, 0, TRUE, status_text, NULL); | |
4832 } | |
4833 g_free(status_text); | |
4834 | |
4835 /* Set a proper away message for icq too so that they work for old third party clients */ | |
4836 | |
4902 away = purple_prpl_oscar_convert_to_infotext(htmlaway, &awaylen, &away_encoding); | 4837 away = purple_prpl_oscar_convert_to_infotext(htmlaway, &awaylen, &away_encoding); |
4903 | 4838 |
4904 if (awaylen > od->rights.maxawaymsglen) | 4839 if (awaylen > od->rights.maxawaymsglen) |
4905 { | 4840 { |
4906 gchar *errstr; | 4841 gchar *errstr; |
5505 PurpleAccount *account; | 5440 PurpleAccount *account; |
5506 char *gname, *gname_utf8, *alias, *alias_utf8; | 5441 char *gname, *gname_utf8, *alias, *alias_utf8; |
5507 PurpleBuddy *b; | 5442 PurpleBuddy *b; |
5508 PurpleGroup *g; | 5443 PurpleGroup *g; |
5509 struct aim_ssi_item *ssi_item; | 5444 struct aim_ssi_item *ssi_item; |
5510 aim_tlv_t *note_hash; | |
5511 va_list ap; | 5445 va_list ap; |
5512 guint16 snac_subtype, type; | 5446 guint16 snac_subtype, type; |
5513 const char *name; | 5447 const char *name; |
5514 | 5448 |
5515 gc = od->gc; | 5449 gc = od->gc; |
5573 | 5507 |
5574 } | 5508 } |
5575 | 5509 |
5576 ssi_item = aim_ssi_itemlist_finditem(od->ssi.local, | 5510 ssi_item = aim_ssi_itemlist_finditem(od->ssi.local, |
5577 gname, name, AIM_SSI_TYPE_BUDDY); | 5511 gname, name, AIM_SSI_TYPE_BUDDY); |
5578 if (ssi_item != NULL) | 5512 if (ssi_item == NULL) |
5579 { | |
5580 note_hash = aim_tlv_gettlv(ssi_item->data, 0x015c, 1); | |
5581 if (note_hash != NULL) | |
5582 aim_icq_getstatusnote(od, name, note_hash->value, note_hash->length); | |
5583 } | |
5584 else | |
5585 { | 5513 { |
5586 purple_debug_error("oscar", "purple_ssi_parseaddmod: " | 5514 purple_debug_error("oscar", "purple_ssi_parseaddmod: " |
5587 "Could not find ssi item for oncoming buddy %s, " | 5515 "Could not find ssi item for oncoming buddy %s, " |
5588 "group %s\n", name, gname); | 5516 "group %s\n", name, gname); |
5589 } | 5517 } |
6028 if (aim_ssi_waitingforauth(od->ssi.local, gname, name)) | 5956 if (aim_ssi_waitingforauth(od->ssi.local, gname, name)) |
6029 ret = g_strdup(_("Not Authorized")); | 5957 ret = g_strdup(_("Not Authorized")); |
6030 else | 5958 else |
6031 ret = g_strdup(_("Offline")); | 5959 ret = g_strdup(_("Offline")); |
6032 } | 5960 } |
6033 else if (purple_status_is_available(status) && !strcmp(id, OSCAR_STATUS_ID_AVAILABLE)) | 5961 else |
6034 { | 5962 { |
6035 /* Available */ | |
6036 message = purple_status_get_attr_string(status, "message"); | |
6037 if (message != NULL) | |
6038 { | |
6039 ret = g_strdup(message); | |
6040 purple_util_chrreplace(ret, '\n', ' '); | |
6041 } | |
6042 } | |
6043 else if (!purple_status_is_available(status) && !strcmp(id, OSCAR_STATUS_ID_AWAY)) | |
6044 { | |
6045 /* Away */ | |
6046 message = purple_status_get_attr_string(status, "message"); | 5963 message = purple_status_get_attr_string(status, "message"); |
6047 if (message != NULL) | 5964 if (message != NULL) |
6048 { | 5965 { |
6049 gchar *tmp1, *tmp2; | 5966 gchar *tmp1, *tmp2; |
6050 tmp1 = purple_markup_strip_html(message); | 5967 tmp1 = purple_markup_strip_html(message); |
6052 tmp2 = g_markup_escape_text(tmp1, -1); | 5969 tmp2 = g_markup_escape_text(tmp1, -1); |
6053 ret = purple_str_sub_away_formatters(tmp2, purple_account_get_username(account)); | 5970 ret = purple_str_sub_away_formatters(tmp2, purple_account_get_username(account)); |
6054 g_free(tmp1); | 5971 g_free(tmp1); |
6055 g_free(tmp2); | 5972 g_free(tmp2); |
6056 } | 5973 } |
5974 else if (purple_status_is_available(status)) | |
5975 { | |
5976 /* Don't show "Available" as status message in case buddy doesn't have a status message */ | |
5977 } | |
6057 else | 5978 else |
6058 { | 5979 { |
6059 ret = g_strdup(_("Away")); | 5980 ret = g_strdup(purple_status_get_name(status)); |
6060 } | 5981 } |
6061 } | 5982 } |
6062 else | |
6063 ret = g_strdup(purple_status_get_name(status)); | |
6064 | 5983 |
6065 return ret; | 5984 return ret; |
6066 } | 5985 } |
6067 | 5986 |
6068 | 5987 |
6965 int i, j; | 6884 int i, j; |
6966 | 6885 |
6967 g_return_val_if_fail(str != NULL, NULL); | 6886 g_return_val_if_fail(str != NULL, NULL); |
6968 | 6887 |
6969 /* copy str to buf and skip all blanks */ | 6888 /* copy str to buf and skip all blanks */ |
6970 for (i=0, j=0; str[j] && i < BUF_LEN - 1; i++, j++) | 6889 i = 0; |
6971 { | 6890 for (j = 0; str[j]; j++) { |
6972 while (str[j] == ' ') | 6891 if (str[j] != ' ') { |
6973 j++; | 6892 buf[i++] = str[j]; |
6974 buf[i] = str[j]; | 6893 if (i >= BUF_LEN - 1) |
6894 break; | |
6895 } | |
6975 } | 6896 } |
6976 buf[i] = '\0'; | 6897 buf[i] = '\0'; |
6977 | 6898 |
6978 tmp1 = g_utf8_strdown(buf, -1); | 6899 tmp1 = g_utf8_strdown(buf, -1); |
6979 tmp2 = g_utf8_normalize(tmp1, -1, G_NORMALIZE_DEFAULT); | 6900 tmp2 = g_utf8_normalize(tmp1, -1, G_NORMALIZE_DEFAULT); |