# HG changeset patch # User Tim Ringenbach # Date 1086746099 0 # Node ID a9151be6fe1a047d02e3b29f88e10b14dbe96015 # Parent fb517adf49725a31872327fcb437cf09d6e7dc4a [gaim-migrate @ 10042] wing went and improved msn's get info stuff too. Both it and yahoo should now be showing all the info that the tooltips show. He wrote: This brings the msn profile code in sync with the proposed yahoo profile code patches. This likely will require patches 967849 and 968555 to work properly. (note: i committed the two above mentioned patches already) committer: Tailor Script diff -r fb517adf4972 -r a9151be6fe1a ChangeLog --- a/ChangeLog Wed Jun 09 01:40:56 2004 +0000 +++ b/ChangeLog Wed Jun 09 01:54:59 2004 +0000 @@ -6,6 +6,7 @@ (Robert Mibus) * Get Info on Yahoo! now works for nonenglish profiles. (Ambrose Li) + * General "Get Info" improvements on Yahoo! and MSN (Ambrose Li) * Yahoo! Japan support. Click More Options and check Yahoo Japan in the account editor, to use your Yahoo! Japan account. * Gtk themes can now theme the Gaim buddy list independently of diff -r fb517adf4972 -r a9151be6fe1a src/protocols/msn/msn.c --- a/src/protocols/msn/msn.c Wed Jun 09 01:40:56 2004 +0000 +++ b/src/protocols/msn/msn.c Wed Jun 09 01:54:59 2004 +0000 @@ -21,6 +21,8 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#define PHOTO_SUPPORT 1 + #include #include "msn.h" @@ -40,6 +42,10 @@ #include "sync.h" #include "slplink.h" +#if PHOTO_SUPPORT +#include "imgstore.h" +#endif + #define BUDDY_ALIAS_MAXLEN 387 static GaimPlugin *my_protocol = NULL; @@ -58,6 +64,18 @@ } MsnGetInfoData; +typedef struct +{ + MsnGetInfoData *info_data; + char *stripped; + char *url_buffer; + GString *s; + char *photo_url_text; + char *tooltip_text; + gboolean has_info; + +} MsnGetInfoStepTwoData; + static const char * msn_normalize(const GaimAccount *account, const char *str) { @@ -1089,28 +1107,102 @@ } } +static char * +msn_tooltip_info_text(MsnGetInfoData *info_data) { + GString *s = g_string_sized_new(80); /* wild guess */ + GaimBuddy *b; + + g_string_printf(s, _("%s: %s
"), _("MSN ID"), info_data->name); + b = gaim_find_buddy(gaim_connection_get_account(info_data->gc), + info_data->name); + + if (b) { + char *statustext = msn_tooltip_text(b); + if(b->alias && b->alias[0]) { + char *aliastext = g_markup_escape_text(b->alias, -1); + g_string_append_printf(s, _("Alias: %s
"), aliastext); + g_free(aliastext); + } + if(b->server_alias) { + char *nicktext = g_markup_escape_text(b->server_alias, -1); + g_string_append_printf(s, _("%s: %s
"), _("Nickname"), + nicktext); + g_free(nicktext); + } + if (b->idle > 0) { + char *idletime = gaim_str_seconds_to_string(time(NULL) - b->idle); + g_string_append_printf(s, _("%s: %s
"), _("Idle"), + idletime); + g_free(idletime); + } + if (statustext) { + g_string_append_printf(s, "%s
", statustext); + g_free(statustext); + } + } + + return g_string_free(s, FALSE); +} + +#if PHOTO_SUPPORT + +static char *msn_get_photo_url(const char *url_text) { + char *p; + char *it = NULL; + + p = strstr(url_text, " title=\"Click to see the full-size photo.\">"); + + if (p) { + /* Search backwards for "http://". This is stupid, but it works. */ + for (; !it && p > url_text; p -= 1) { + if (strncmp(p, "\"http://", 8) == 0) { + char *q; + p += 1; /* skip only the " */ + q = strchr(p, '"'); + if (q) { + it = g_strndup(p, q - p); + } + } + } + } + return it; +} + +static void msn_got_photo(void *data, const char *url_text, size_t len); + +#endif + static void msn_got_info(void *data, const char *url_text, size_t len) { MsnGetInfoData *info_data = (MsnGetInfoData *)data; char *stripped, *p, *q; char buf[1024]; + char *tooltip_text = NULL; char *user_url = NULL; gboolean found; gboolean has_info = FALSE; char *url_buffer; GString *s; int stripped_len; +#if PHOTO_SUPPORT + char *photo_url_text = NULL; + MsnGetInfoStepTwoData *info2_data = NULL; +#endif gaim_debug_info("msn", "In msn_got_info\n"); + tooltip_text = msn_tooltip_info_text(info_data); + if (url_text == NULL || strcmp(url_text, "") == 0) { + g_snprintf(buf, 1024, "%s%s", + tooltip_text, _("Error retrieving profile")); + gaim_notify_formatted(info_data->gc, NULL, - _("Buddy Information"), NULL, - _("Error retrieving profile"), - NULL, NULL); + _("Buddy Information"), NULL, buf, NULL, NULL); + g_free(tooltip_text); return; } @@ -1133,8 +1225,10 @@ */ while ((p = strstr(url_buffer, " ")) != NULL) { - memmove(p, p + 6, strlen(p + 6)); - url_buffer[strlen(url_text) - 6] = '\0'; + *p = ' '; /* Turn  's into ordinary blanks */ + p += 1; + memmove(p, p + 5, strlen(p + 5)); + url_buffer[strlen(url_buffer) - 5] = '\0'; } while ((p = strstr(url_buffer, "·")) != NULL) @@ -1144,11 +1238,7 @@ } /* Nuke the nasty \r's that just get in the way */ - while ((p = strchr(url_buffer, '\r')) != NULL) - { - memmove(p, p + 1, strlen(p + 1)); - url_buffer[strlen(url_buffer) - 1] = '\0'; - } + gaim_str_strip_cr(url_buffer); /* MSN always puts in ' for apostrophes...replace them */ while ((p = strstr(url_buffer, "'")) != NULL) @@ -1171,21 +1261,21 @@ /* Extract their Name and put it in */ found = gaim_markup_extract_info_field(stripped, stripped_len, s, - "\tName", 0, "\t", '\n', "Undisclosed", _("Name"), 0, NULL); + "\tName\n", 0, "\t", 0, "Undisclosed", _("Name"), 0, NULL); if (found) has_info = TRUE; /* Extract their Age and put it in */ found = gaim_markup_extract_info_field(stripped, stripped_len, s, - "\tAge", 0, "\t", '\n', "Undisclosed", _("Age"), 0, NULL); + "\tAge\n", 0, "\n", 0, "Undisclosed", _("Age"), 0, NULL); if (found) has_info = TRUE; /* Extract their Gender and put it in */ found = gaim_markup_extract_info_field(stripped, stripped_len, s, - "\tGender", 6, "\t", '\n', "Undisclosed", _("Gender"), 0, + "\nGender\n", 0, "\t", 0, "Undisclosed", _("Gender"), 0, NULL); if (found) @@ -1193,7 +1283,7 @@ /* Extract their MaritalStatus and put it in */ found = gaim_markup_extract_info_field(stripped, stripped_len, s, - "\tMaritalStatus", 0, "\t", '\n', "Undisclosed", + "\tMarital Status\n", 0, "\n", 0, "Undisclosed", _("Marital Status"), 0, NULL); if (found) @@ -1201,7 +1291,7 @@ /* Extract their Location and put it in */ found = gaim_markup_extract_info_field(stripped, stripped_len, s, - "\tLocation", 0, "\t", '\n', "Undisclosed", _("Location"), 0, + "\nLocation\n", 0, "\n", 0, "Undisclosed", _("Location"), 0, NULL); if (found) @@ -1209,7 +1299,7 @@ /* Extract their Occupation and put it in */ found = gaim_markup_extract_info_field(stripped, stripped_len, s, - "\t Occupation", 6, "\t", '\n', "Undisclosed", _("Occupation"), + " Occupation\n", 6, "\n", 0, "Undisclosed", _("Occupation"), 0, NULL); if (found) @@ -1225,34 +1315,35 @@ /* Check if they have A Little About Me */ found = gaim_markup_extract_info_field(stripped, stripped_len, s, - "\tA Little About Me", 1, "Favorite Things", '\n', NULL, + " A Little About Me \n\n", 0, "Favorite Things", '\n', NULL, _("A Little About Me"), 0, NULL); if (!found) { found = gaim_markup_extract_info_field(stripped, stripped_len, s, - "\tA Little About Me", 1, "Hobbies and Interests", '\n', + " A Little About Me \n\n", 0, "Hobbies and Interests", '\n', NULL, _("A Little About Me"), 0, NULL); } if (!found) { found = gaim_markup_extract_info_field(stripped, stripped_len, s, - "\tA Little About Me", 1, "Favorite Quote", '\n', NULL, + " A Little About Me \n\n", 0, "Favorite Quote", '\n', NULL, _("A Little About Me"), 0, NULL); } if (!found) { found = gaim_markup_extract_info_field(stripped, stripped_len, s, - "\tA Little About Me", 1, "My Homepage\tTake a look", '\n', + " A Little About Me \n\n", 0, "My Homepage \n\nTake a look", + '\n', NULL, _("A Little About Me"), 0, NULL); } if (!found) { gaim_markup_extract_info_field(stripped, stripped_len, s, - "\tA Little About Me", 1, "last updated", '\n', NULL, + " A Little About Me \n\n", 0, "last updated", '\n', NULL, _("A Little About Me"), 0, NULL); } @@ -1261,27 +1352,27 @@ /* Check if they have Favorite Things */ found = gaim_markup_extract_info_field(stripped, stripped_len, s, - "Favorite Things", 1, "Hobbies and Interests", '\n', NULL, + " Favorite Things \n\n", 0, "Hobbies and Interests", '\n', NULL, _("Favorite Things"), 0, NULL); if (!found) { found = gaim_markup_extract_info_field(stripped, stripped_len, s, - "Favorite Things", 1, "Favorite Quote", '\n', NULL, - "Favorite Things", 0, NULL); + " Favorite Things \n\n", 0, "Favorite Quote", '\n', NULL, + _("Favorite Things"), 0, NULL); } if (!found) { found = gaim_markup_extract_info_field(stripped, stripped_len, s, - "Favorite Things", 1, "My Homepage\tTake a look", '\n', + " Favorite Things \n\n", 0, "My Homepage \n\nTake a look", '\n', NULL, _("Favorite Things"), 0, NULL); } if (!found) { gaim_markup_extract_info_field(stripped, stripped_len, s, - "Favorite Things", 1, "last updated", '\n', NULL, + " Favorite Things \n\n", 0, "last updated", '\n', NULL, _("Favorite Things"), 0, NULL); } @@ -1290,20 +1381,20 @@ /* Check if they have Hobbies and Interests */ found = gaim_markup_extract_info_field(stripped, stripped_len, s, - "Hobbies and Interests", 1, "Favorite Quote", '\n', NULL, + " Hobbies and Interests \n\n", 0, "Favorite Quote", '\n', NULL, _("Hobbies and Interests"), 0, NULL); if (!found) { found = gaim_markup_extract_info_field(stripped, stripped_len, s, - "Hobbies and Interests", 1, "My Homepage\tTake a look", + " Hobbies and Interests \n\n", 0, "My Homepage \n\nTake a look", '\n', NULL, _("Hobbies and Interests"), 0, NULL); } if (!found) { gaim_markup_extract_info_field(stripped, stripped_len, s, - "Hobbies and Interests", 1, "last updated", '\n', NULL, + " Hobbies and Interests \n\n", 0, "last updated", '\n', NULL, _("Hobbies and Interests"), 0, NULL); } @@ -1312,13 +1403,13 @@ /* Check if they have Favorite Quote */ found = gaim_markup_extract_info_field(stripped, stripped_len, s, - "Favorite Quote", 1, "My Homepage\tTake a look", '\n', NULL, + "Favorite Quote \n\n", 0, "My Homepage \n\nTake a look", '\n', NULL, _("Favorite Quote"), 0, NULL); if (!found) { gaim_markup_extract_info_field(stripped, stripped_len, s, - "Favorite Quote", 1, "last updated", '\n', NULL, + "Favorite Quote \n\n", 0, "last updated", '\n', NULL, _("Favorite Quote"), 0, NULL); } @@ -1327,7 +1418,7 @@ /* Extract the last updated date and put it in */ found = gaim_markup_extract_info_field(stripped, stripped_len, s, - "\tlast updated:", 1, "\n", '\n', NULL, _("Last Updated"), 0, + " last updated:", 1, "\n", 0, NULL, _("Last Updated"), 0, NULL); if (found) @@ -1347,30 +1438,108 @@ has_info = TRUE; } + if (found) { + /* put a link to the actual profile URL */ + g_string_append_printf(s, _("%s: "), _("Profile URL")); + g_string_append_printf(s, "
%s%s
", + PROFILE_URL, info_data->name, PROFILE_URL, info_data->name); + } + /* Finish it off, and show it to them */ g_string_append(s, "\n"); +#if PHOTO_SUPPORT + + /* Marshall the existing state */ + info2_data = g_malloc0(sizeof(MsnGetInfoStepTwoData)); + info2_data->info_data = info_data; + info2_data->stripped = stripped; + info2_data->url_buffer = url_buffer; + info2_data->s = s; + info2_data->photo_url_text = photo_url_text; + info2_data->tooltip_text = tooltip_text; + info2_data->has_info = has_info; + + /* Try to put the photo in there too, if there's one */ + photo_url_text = msn_get_photo_url(url_text); + if (photo_url_text) { + gaim_url_fetch(photo_url_text, FALSE, NULL, FALSE, msn_got_photo, + info2_data); + } else { + /* Emulate a callback */ + msn_got_photo(info2_data, NULL, 0); + } +} + +static void msn_got_photo(void *data, const char *url_text, size_t len) +{ + MsnGetInfoStepTwoData *info2_data = (MsnGetInfoStepTwoData *)data; + int id = -1; + + /* Unmarshall the saved state */ + MsnGetInfoData *info_data = info2_data->info_data; + char *stripped = info2_data->stripped; + char *url_buffer = info2_data->url_buffer; + GString *s = info2_data->s; + char *photo_url_text = info2_data->photo_url_text; + char *tooltip_text = info2_data->tooltip_text; + gboolean has_info = info2_data->has_info; + + /* Try to put the photo in there too, if there's one and is readable */ + if (data && url_text && len != 0) { + if (strstr(url_text, "400 Bad Request") + || strstr(url_text, "403 Forbidden") + || strstr(url_text, "404 Not Found")) { + + gaim_debug_info("msn", "Error getting %s: %s\n", + photo_url_text, url_text); + } else { + char buf[1024]; + gaim_debug_info("msn", "%s is %d bytes\n", photo_url_text, len); + id = gaim_imgstore_add(url_text, len, NULL); + g_snprintf(buf, sizeof(buf), "
", id); + g_string_prepend(s, buf); + } + } + + /* We continue here from msn_got_info, as if nothing has happened */ +#endif + if (has_info) { + g_string_prepend(s, tooltip_text); gaim_notify_formatted(info_data->gc, NULL, _("Buddy Information"), NULL, s->str, NULL, NULL); } else { - char primary[256]; + char *p = strstr(url_buffer, "Unknown Member "); - g_snprintf(primary, sizeof(primary), - _("User information for %s unavailable"), - info_data->name); - gaim_notify_error(info_data->gc, NULL, primary, - _("The user's profile is empty.")); + /* MSN doesn't actually distinguish between "unknown member" and + * a known member with an empty profile. But if we say unknown + * member, it is at least not worse than reading the actual page. + */ + g_string_printf(s, "%s%s
", + tooltip_text, + (p ? _("Error retrieving profile") + : _("The user's profile is empty."))); + + gaim_notify_formatted(info_data->gc, NULL, _("Buddy Information"), NULL, + s->str, NULL, NULL); } g_free(stripped); g_free(url_buffer); g_string_free(s, TRUE); + g_free(tooltip_text); g_free(info_data->name); g_free(info_data); +#if PHOTO_SUPPORT + g_free(photo_url_text); + g_free(info2_data); + if (id != -1) + gaim_imgstore_unref(id); +#endif } static void