Replace all CRLF line-endings with LF line endings (Unix-style). This fixes
some compilation errors on Solaris.
Closes #3096.
--- a/libpurple/protocols/myspace/markup.c Mon Sep 17 03:34:11 2007 +0000
+++ b/libpurple/protocols/myspace/markup.c Tue Sep 18 00:47:51 2007 +0000
@@ -1,698 +1,698 @@
-/* MySpaceIM Protocol Plugin - markup
- * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im>
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-typedef void (*MSIM_XMLNODE_CONVERT)(MsimSession *, xmlnode *, gchar **, gchar **);
-/* Internal functions */
-static guint msim_point_to_purple_size(MsimSession *session, guint point);
-static guint msim_purple_size_to_point(MsimSession *session, guint size);
-static guint msim_height_to_point(MsimSession *session, guint height);
-static guint msim_point_to_height(MsimSession *session, guint point);
-static void msim_markup_tag_to_html(MsimSession *, xmlnode *root, gchar **begin, gchar **end);
-static void html_tag_to_msim_markup(MsimSession *, xmlnode *root, gchar **begin, gchar **end);
-static gchar *msim_convert_xml(MsimSession *, const gchar *raw, MSIM_XMLNODE_CONVERT f);
-static gchar *msim_convert_smileys_to_markup(gchar *before);
-static double msim_round(double round);
-/* The names in in emoticon_names (for <i n=whatever>) map to corresponding
- * entries in emoticon_symbols (for the ASCII representation of the emoticon).
- * Multiple emoticon symbols in Pidgin can map to one name. List the
- * canonical form, as inserted by the "Smile!" dialog, first. For example,
- * :) comes before :-), because although both are recognized as 'happy',
- * the first is inserted by the smiley button (first symbol in theme).
- * Note that symbols are case-sensitive in Pidgin -- :-X is not :-x. */
-static struct MSIM_EMOTICON
- /* Unfortunately, this list duplicates much of the file
- * pidgin/pidgin/pixmaps/emotes/default/22/default.theme.in, because
- * that file is part of Pidgin, but we're part of libpurple.
- { "laugh", ":))" }, /* Must be before ':)' */
-/* Indexes of this array + 1 map HTML font size to scale of normal font size. *
- * Based on _point_sizes from libpurple/gtkimhtml.c
-static gdouble _font_scale[] = { .85, .95, 1, 1.2, 1.44, 1.728, 2.0736 };
-#define MAX_FONT_SIZE 7 /* Purple maximum font size */
-#define POINTS_PER_INCH 72 /* How many pt's in an inch */
-/* Text formatting bits for <f s=#> */
-#define MSIM_TEXT_BOLD 1
-#define MSIM_TEXT_ITALIC 2
-#define MSIM_TEXT_UNDERLINE 4
-/* Default baseline size of purple's fonts, in points. What is size 3 in points.
- * _font_scale specifies scaling factor relative to this point size. Note this
- * is only the default; it is configurable in account options. */
-#define MSIM_BASE_FONT_POINT_SIZE 8
-/* Default display's DPI. 96 is common but it can differ. Also configurable
- * in account options. */
-#define MSIM_DEFAULT_DPI 96
-/* round is part of C99, but sometimes is unavailable before then.
- * Based on http://forums.belution.com/en/cpp/000/050/13.shtml
-double msim_round(double value)
- return -(floor(-value + 0.5));
- return floor( value + 0.5);
-/** Convert typographical font point size to HTML font size.
- * Based on libpurple/gtkimhtml.c */
-msim_point_to_purple_size(MsimSession *session, guint point)
- guint size, this_point, base;
- base = purple_account_get_int(session->account, "base_font_size", MSIM_BASE_FONT_POINT_SIZE);
- size < sizeof(_font_scale) / sizeof(_font_scale[0]);
- scale = _font_scale[CLAMP(size, 1, MAX_FONT_SIZE) - 1];
- this_point = (guint)msim_round(scale * base);
- if (this_point >= point) {
- purple_debug_info("msim", "msim_point_to_purple_size: %d pt -> size=%d\n",
- /* No HTML font size was this big; return largest possible. */
-/** Convert HTML font size to point size. */
-msim_purple_size_to_point(MsimSession *session, guint size)
- scale = _font_scale[CLAMP(size, 1, MAX_FONT_SIZE) - 1];
- base = purple_account_get_int(session->account, "base_font_size", MSIM_BASE_FONT_POINT_SIZE);
- point = (guint)msim_round(scale * base);
- purple_debug_info("msim", "msim_purple_size_to_point: size=%d -> %d pt\n",
-/** Convert a msim markup font pixel height to the more usual point size, for incoming messages. */
-msim_height_to_point(MsimSession *session, guint height)
- dpi = purple_account_get_int(session->account, "port", MSIM_DEFAULT_DPI);
- return (guint)msim_round((POINTS_PER_INCH * 1. / dpi) * height);
- /* See also: libpurple/protocols/bonjour/jabber.c
- * _font_size_ichat_to_purple */
-/** Convert point size to msim pixel height font size specification, for outgoing messages. */
-msim_point_to_height(MsimSession *session, guint point)
- dpi = purple_account_get_int(session->account, "port", MSIM_DEFAULT_DPI);
- return (guint)msim_round((dpi * 1. / POINTS_PER_INCH) * point);
-/** Convert the msim markup <f> (font) tag into HTML. */
-msim_markup_f_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end)
- const gchar *face, *height_str, *decor_str;
- GString *gs_end, *gs_begin;
- face = xmlnode_get_attrib(root, "f");
- height_str = xmlnode_get_attrib(root, "h");
- decor_str = xmlnode_get_attrib(root, "s");
- height = atol(height_str);
- decor = atol(decor_str);
- gs_begin = g_string_new("");
- /* TODO: get font size working */
- g_string_printf(gs_begin, "<font size='%d'>",
- msim_point_to_purple_size(session, msim_height_to_point(session, height)));
- } else if (height && face) {
- g_string_printf(gs_begin, "<font face='%s' size='%d'>", face,
- msim_point_to_purple_size(session, msim_height_to_point(session, height)));
- g_string_printf(gs_begin, "<font>");
- /* No support for font-size CSS? */
- /* g_string_printf(gs_begin, "<span style='font-family: %s; font-size: %dpt'>", face,
- msim_height_to_point(height)); */
- gs_end = g_string_new("</font>");
- if (decor & MSIM_TEXT_BOLD) {
- g_string_append(gs_begin, "<b>");
- g_string_prepend(gs_end, "</b>");
- if (decor & MSIM_TEXT_ITALIC) {
- g_string_append(gs_begin, "<i>");
- g_string_append(gs_end, "</i>");
- if (decor & MSIM_TEXT_UNDERLINE) {
- g_string_append(gs_begin, "<u>");
- g_string_append(gs_end, "</u>");
- *begin = gs_begin->str;
-/** Convert a msim markup color to a color suitable for libpurple.
- * @param msim Either a color name, or an rgb(x,y,z) code.
- * @return A new string, either a color name or #rrggbb code. Must g_free().
-msim_color_to_purple(const char *msim)
- guint red, green, blue;
- return g_strdup("black");
- if (sscanf(msim, "rgb(%d,%d,%d)", &red, &green, &blue) != 3) {
- /* TODO: rgba (alpha). */
- return g_strdup_printf("#%.2x%.2x%.2x", red, green, blue);
-/** Convert the msim markup <a> (anchor) tag into HTML. */
-msim_markup_a_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end)
- href = xmlnode_get_attrib(root, "h");
- *begin = g_strdup_printf("<a href=\"%s\">%s", href, href);
- *end = g_strdup("</a>");
-/** Convert the msim markup <p> (paragraph) tag into HTML. */
-msim_markup_p_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end)
- /* Just pass through unchanged.
- * Note: attributes currently aren't passed, if there are any. */
- *begin = g_strdup("<p>");
- *end = g_strdup("</p>");
-/** Convert the msim markup <c> tag (text color) into HTML. TODO: Test */
-msim_markup_c_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end)
- color = xmlnode_get_attrib(root, "v");
- purple_debug_info("msim", "msim_markup_c_to_html: <c> tag w/o v attr");
- /* TODO: log as unrecognized */
- purple_color = msim_color_to_purple(color);
- *begin = g_strdup_printf("<font color='%s'>", purple_color);
- /* *begin = g_strdup_printf("<span style='color: %s'>", color); */
- *end = g_strdup("</font>");
-/** Convert the msim markup <b> tag (background color) into HTML. TODO: Test */
-msim_markup_b_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end)
- color = xmlnode_get_attrib(root, "v");
- purple_debug_info("msim", "msim_markup_b_to_html: <b> w/o v attr");
- /* TODO: log as unrecognized. */
- purple_color = msim_color_to_purple(color);
- /* TODO: find out how to set background color. */
- *begin = g_strdup_printf("<span style='background-color: %s'>",
- *end = g_strdup("</p>");
-/** Convert the msim markup <i> tag (emoticon image) into HTML. */
-msim_markup_i_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end)
- struct MSIM_EMOTICON *emote;
- name = xmlnode_get_attrib(root, "n");
- purple_debug_info("msim", "msim_markup_i_to_html: <i> w/o n");
- /* TODO: log as unrecognized */
- /* Find and use canonical form of smiley symbol. */
- for (i = 0; (emote = &msim_emoticons[i]) && emote->name != NULL; ++i) {
- if (g_str_equal(name, emote->name)) {
- *begin = g_strdup(emote->symbol);
- /* Couldn't find it, sorry. Try to degrade gracefully. */
- *begin = g_strdup_printf("**%s**", name);
-/** Convert an individual msim markup tag to HTML. */
-msim_markup_tag_to_html(MsimSession *session, xmlnode *root, gchar **begin,
- if (g_str_equal(root->name, "f")) {
- msim_markup_f_to_html(session, root, begin, end);
- } else if (g_str_equal(root->name, "a")) {
- msim_markup_a_to_html(session, root, begin, end);
- } else if (g_str_equal(root->name, "p")) {
- msim_markup_p_to_html(session, root, begin, end);
- } else if (g_str_equal(root->name, "c")) {
- msim_markup_c_to_html(session, root, begin, end);
- } else if (g_str_equal(root->name, "b")) {
- msim_markup_b_to_html(session, root, begin, end);
- } else if (g_str_equal(root->name, "i")) {
- msim_markup_i_to_html(session, root, begin, end);
- purple_debug_info("msim", "msim_markup_tag_to_html: "
- "unknown tag name=%s, ignoring",
- (root && root->name) ? root->name : "(NULL)");
-/** Convert an individual HTML tag to msim markup. */
-html_tag_to_msim_markup(MsimSession *session, xmlnode *root, gchar **begin,
- if (!purple_utf8_strcasecmp(root->name, "root") ||
- !purple_utf8_strcasecmp(root->name, "html")) {
- /* TODO: Coalesce nested tags into one <f> tag!
- * Currently, the 's' value will be overwritten when b/i/u is nested
- * within another one, and only the inner-most formatting will be
- * applied to the text. */
- } else if (!purple_utf8_strcasecmp(root->name, "b")) {
- *begin = g_strdup_printf("<f s='%d'>", MSIM_TEXT_BOLD);
- *end = g_strdup("</f>");
- } else if (!purple_utf8_strcasecmp(root->name, "i")) {
- *begin = g_strdup_printf("<f s='%d'>", MSIM_TEXT_ITALIC);
- *end = g_strdup("</f>");
- } else if (!purple_utf8_strcasecmp(root->name, "u")) {
- *begin = g_strdup_printf("<f s='%d'>", MSIM_TEXT_UNDERLINE);
- *end = g_strdup("</f>");
- } else if (!purple_utf8_strcasecmp(root->name, "a")) {
- const gchar *href, *link_text;
- href = xmlnode_get_attrib(root, "href");
- href = xmlnode_get_attrib(root, "HREF");
- link_text = xmlnode_get_data(root);
- if (g_str_equal(link_text, href)) {
- /* Purple gives us: <a href="URL">URL</a>
- * Translate to <a h='URL' />
- * Displayed as text of URL with link to URL
- *begin = g_strdup_printf("<a h='%s' />", href);
- /* But if we get: <a href="URL">text</a>
- * Translate to: text: <a h='URL' />
- * Because official client only supports self-closed <a>
- * tags; you can't change the link text.
- *begin = g_strdup_printf("%s: <a h='%s' />", link_text, href);
- *begin = g_strdup("<a />");
- /* Sorry, kid. MySpace doesn't support you within <a> tags. */
- xmlnode_free(root->child);
- } else if (!purple_utf8_strcasecmp(root->name, "font")) {
- size = xmlnode_get_attrib(root, "size");
- face = xmlnode_get_attrib(root, "face");
- *begin = g_strdup_printf("<f f='%s' h='%d'>", face,
- msim_point_to_height(session,
- msim_purple_size_to_point(session, atoi(size))));
- *begin = g_strdup_printf("<f f='%s'>", face);
- *begin = g_strdup_printf("<f h='%d'>",
- msim_point_to_height(session,
- msim_purple_size_to_point(session, atoi(size))));
- *begin = g_strdup("<f>");
- *end = g_strdup("</f>");
- /* TODO: color (bg uses <body>), emoticons */
-#ifdef MSIM_MARKUP_SHOW_UNKNOWN_TAGS
- *begin = g_strdup_printf("[%s]", root->name);
- *end = g_strdup_printf("[/%s]", root->name);
-/** Convert an xmlnode of msim markup or HTML to an HTML string or msim markup.
- * @param f Function to convert tags.
- * @return An HTML string. Caller frees.
-msim_convert_xmlnode(MsimSession *session, xmlnode *root, MSIM_XMLNODE_CONVERT f)
- gchar *begin, *inner, *end;
- if (!root || !root->name) {
- purple_debug_info("msim", "msim_convert_xmlnode: got root=%s\n",
- begin = inner = end = NULL;
- final = g_string_new("");
- f(session, root, &begin, &end);
- g_string_append(final, begin);
- /* Loop over all child nodes. */
- for (node = root->child; node != NULL; node = node->next) {
- case XMLNODE_TYPE_ATTRIB:
- /* Attributes handled above. */
- /* A tag or tag with attributes. Recursively descend. */
- inner = msim_convert_xmlnode(session, node, f);
- g_return_val_if_fail(inner != NULL, NULL);
- purple_debug_info("msim", " ** node name=%s\n",
- (node && node->name) ? node->name : "(NULL)");
- case XMLNODE_TYPE_DATA:
- inner = g_new0(char, node->data_sz + 1);
- strncpy(inner, node->data, node->data_sz);
- inner[node->data_sz] = 0;
- purple_debug_info("msim", " ** node data=%s\n",
- inner ? inner : "(NULL)");
- purple_debug_info("msim",
- "msim_convert_xmlnode: strange node\n");
- g_string_append(final, inner);
- /* TODO: Note that msim counts each piece of text enclosed by <f> as
- * a paragraph and will display each on its own line. You actually have
- * to _nest_ <f> tags to intersperse different text in one paragraph!
- * Comment out this line below to see. */
- g_string_append(final, end);
- purple_debug_info("msim", "msim_markup_xmlnode_to_gtkhtml: RETURNING %s\n",
- (final && final->str) ? final->str : "(NULL)");
-/** Convert XML to something based on MSIM_XMLNODE_CONVERT. */
-msim_convert_xml(MsimSession *session, const gchar *raw, MSIM_XMLNODE_CONVERT f)
- g_return_val_if_fail(raw != NULL, NULL);
- /* Enclose text in one root tag, to try to make it valid XML for parsing. */
- enclosed_raw = g_strconcat("<root>", raw, "</root>", NULL);
- root = xmlnode_from_str(enclosed_raw, -1);
- purple_debug_info("msim", "msim_markup_to_html: couldn't parse "
- "%s as XML, returning raw: %s\n", enclosed_raw, raw);
- /* TODO: msim_unrecognized */
- str = msim_convert_xmlnode(session, root, f);
- g_return_val_if_fail(str != NULL, NULL);
- purple_debug_info("msim", "msim_markup_to_html: returning %s\n", str);
-/** Convert plaintext smileys to <i> markup tags.
- * @param before Original text with ASCII smileys. Will be freed.
- * @return A new string with <i> tags, if applicable. Must be g_free()'d.
-msim_convert_smileys_to_markup(gchar *before)
- gchar *old, *new, *replacement;
- struct MSIM_EMOTICON *emote;
- for (i = 0; (emote = &msim_emoticons[i]) && emote->name != NULL; ++i) {
- symbol = emote->symbol;
- replacement = g_strdup_printf("<i n=\"%s\"/>", name);
- purple_debug_info("msim", "msim_convert_smileys_to_markup: %s->%s\n",
- symbol ? symbol : "(NULL)",
- replacement ? replacement : "(NULL)");
- new = purple_strreplace(old, symbol, replacement);
-/** High-level function to convert MySpaceIM markup to Purple (HTML) markup.
- * @return Purple markup string, must be g_free()'d. */
-msim_markup_to_html(MsimSession *session, const gchar *raw)
- return msim_convert_xml(session, raw,
- (MSIM_XMLNODE_CONVERT)(msim_markup_tag_to_html));
-/** High-level function to convert Purple (HTML) to MySpaceIM markup.
- * TODO: consider using purple_markup_html_to_xhtml() to make valid XML.
- * @return HTML markup string, must be g_free()'d. */
-html_to_msim_markup(MsimSession *session, const gchar *raw)
- markup = msim_convert_xml(session, raw,
- (MSIM_XMLNODE_CONVERT)(html_tag_to_msim_markup));
- if (purple_account_get_bool(session->account, "emoticons", TRUE)) {
- /* Frees markup and allocates a new one. */
- markup = msim_convert_smileys_to_markup(markup);
+/* MySpaceIM Protocol Plugin - markup + * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im> + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +typedef void (*MSIM_XMLNODE_CONVERT)(MsimSession *, xmlnode *, gchar **, gchar **); +/* Internal functions */ +static guint msim_point_to_purple_size(MsimSession *session, guint point); +static guint msim_purple_size_to_point(MsimSession *session, guint size); +static guint msim_height_to_point(MsimSession *session, guint height); +static guint msim_point_to_height(MsimSession *session, guint point); +static void msim_markup_tag_to_html(MsimSession *, xmlnode *root, gchar **begin, gchar **end); +static void html_tag_to_msim_markup(MsimSession *, xmlnode *root, gchar **begin, gchar **end); +static gchar *msim_convert_xml(MsimSession *, const gchar *raw, MSIM_XMLNODE_CONVERT f); +static gchar *msim_convert_smileys_to_markup(gchar *before); +static double msim_round(double round); +/* The names in in emoticon_names (for <i n=whatever>) map to corresponding + * entries in emoticon_symbols (for the ASCII representation of the emoticon). + * Multiple emoticon symbols in Pidgin can map to one name. List the + * canonical form, as inserted by the "Smile!" dialog, first. For example, + * :) comes before :-), because although both are recognized as 'happy', + * the first is inserted by the smiley button (first symbol in theme). + * Note that symbols are case-sensitive in Pidgin -- :-X is not :-x. */ +static struct MSIM_EMOTICON + /* Unfortunately, this list duplicates much of the file + * pidgin/pidgin/pixmaps/emotes/default/22/default.theme.in, because + * that file is part of Pidgin, but we're part of libpurple. + { "laugh", ":))" }, /* Must be before ':)' */ +/* Indexes of this array + 1 map HTML font size to scale of normal font size. * + * Based on _point_sizes from libpurple/gtkimhtml.c +static gdouble _font_scale[] = { .85, .95, 1, 1.2, 1.44, 1.728, 2.0736 }; +#define MAX_FONT_SIZE 7 /* Purple maximum font size */ +#define POINTS_PER_INCH 72 /* How many pt's in an inch */ +/* Text formatting bits for <f s=#> */ +#define MSIM_TEXT_BOLD 1 +#define MSIM_TEXT_ITALIC 2 +#define MSIM_TEXT_UNDERLINE 4 +/* Default baseline size of purple's fonts, in points. What is size 3 in points. + * _font_scale specifies scaling factor relative to this point size. Note this + * is only the default; it is configurable in account options. */ +#define MSIM_BASE_FONT_POINT_SIZE 8 +/* Default display's DPI. 96 is common but it can differ. Also configurable + * in account options. */ +#define MSIM_DEFAULT_DPI 96 +/* round is part of C99, but sometimes is unavailable before then. + * Based on http://forums.belution.com/en/cpp/000/050/13.shtml +double msim_round(double value) + return -(floor(-value + 0.5)); + return floor( value + 0.5); +/** Convert typographical font point size to HTML font size. + * Based on libpurple/gtkimhtml.c */ +msim_point_to_purple_size(MsimSession *session, guint point) + guint size, this_point, base; + base = purple_account_get_int(session->account, "base_font_size", MSIM_BASE_FONT_POINT_SIZE); + size < sizeof(_font_scale) / sizeof(_font_scale[0]); + scale = _font_scale[CLAMP(size, 1, MAX_FONT_SIZE) - 1]; + this_point = (guint)msim_round(scale * base); + if (this_point >= point) { + purple_debug_info("msim", "msim_point_to_purple_size: %d pt -> size=%d\n", + /* No HTML font size was this big; return largest possible. */ +/** Convert HTML font size to point size. */ +msim_purple_size_to_point(MsimSession *session, guint size) + scale = _font_scale[CLAMP(size, 1, MAX_FONT_SIZE) - 1]; + base = purple_account_get_int(session->account, "base_font_size", MSIM_BASE_FONT_POINT_SIZE); + point = (guint)msim_round(scale * base); + purple_debug_info("msim", "msim_purple_size_to_point: size=%d -> %d pt\n", +/** Convert a msim markup font pixel height to the more usual point size, for incoming messages. */ +msim_height_to_point(MsimSession *session, guint height) + dpi = purple_account_get_int(session->account, "port", MSIM_DEFAULT_DPI); + return (guint)msim_round((POINTS_PER_INCH * 1. / dpi) * height); + /* See also: libpurple/protocols/bonjour/jabber.c + * _font_size_ichat_to_purple */ +/** Convert point size to msim pixel height font size specification, for outgoing messages. */ +msim_point_to_height(MsimSession *session, guint point) + dpi = purple_account_get_int(session->account, "port", MSIM_DEFAULT_DPI); + return (guint)msim_round((dpi * 1. / POINTS_PER_INCH) * point); +/** Convert the msim markup <f> (font) tag into HTML. */ +msim_markup_f_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end) + const gchar *face, *height_str, *decor_str; + GString *gs_end, *gs_begin; + face = xmlnode_get_attrib(root, "f"); + height_str = xmlnode_get_attrib(root, "h"); + decor_str = xmlnode_get_attrib(root, "s"); + height = atol(height_str); + decor = atol(decor_str); + gs_begin = g_string_new(""); + /* TODO: get font size working */ + g_string_printf(gs_begin, "<font size='%d'>", + msim_point_to_purple_size(session, msim_height_to_point(session, height))); + } else if (height && face) { + g_string_printf(gs_begin, "<font face='%s' size='%d'>", face, + msim_point_to_purple_size(session, msim_height_to_point(session, height))); + g_string_printf(gs_begin, "<font>"); + /* No support for font-size CSS? */ + /* g_string_printf(gs_begin, "<span style='font-family: %s; font-size: %dpt'>", face, + msim_height_to_point(height)); */ + gs_end = g_string_new("</font>"); + if (decor & MSIM_TEXT_BOLD) { + g_string_append(gs_begin, "<b>"); + g_string_prepend(gs_end, "</b>"); + if (decor & MSIM_TEXT_ITALIC) { + g_string_append(gs_begin, "<i>"); + g_string_append(gs_end, "</i>"); + if (decor & MSIM_TEXT_UNDERLINE) { + g_string_append(gs_begin, "<u>"); + g_string_append(gs_end, "</u>"); + *begin = gs_begin->str; +/** Convert a msim markup color to a color suitable for libpurple. + * @param msim Either a color name, or an rgb(x,y,z) code. + * @return A new string, either a color name or #rrggbb code. Must g_free(). +msim_color_to_purple(const char *msim) + guint red, green, blue; + return g_strdup("black"); + if (sscanf(msim, "rgb(%d,%d,%d)", &red, &green, &blue) != 3) { + /* TODO: rgba (alpha). */ + return g_strdup_printf("#%.2x%.2x%.2x", red, green, blue); +/** Convert the msim markup <a> (anchor) tag into HTML. */ +msim_markup_a_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end) + href = xmlnode_get_attrib(root, "h"); + *begin = g_strdup_printf("<a href=\"%s\">%s", href, href); + *end = g_strdup("</a>"); +/** Convert the msim markup <p> (paragraph) tag into HTML. */ +msim_markup_p_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end) + /* Just pass through unchanged. + * Note: attributes currently aren't passed, if there are any. */ + *begin = g_strdup("<p>"); + *end = g_strdup("</p>"); +/** Convert the msim markup <c> tag (text color) into HTML. TODO: Test */ +msim_markup_c_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end) + color = xmlnode_get_attrib(root, "v"); + purple_debug_info("msim", "msim_markup_c_to_html: <c> tag w/o v attr"); + /* TODO: log as unrecognized */ + purple_color = msim_color_to_purple(color); + *begin = g_strdup_printf("<font color='%s'>", purple_color); + /* *begin = g_strdup_printf("<span style='color: %s'>", color); */ + *end = g_strdup("</font>"); +/** Convert the msim markup <b> tag (background color) into HTML. TODO: Test */ +msim_markup_b_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end) + color = xmlnode_get_attrib(root, "v"); + purple_debug_info("msim", "msim_markup_b_to_html: <b> w/o v attr"); + /* TODO: log as unrecognized. */ + purple_color = msim_color_to_purple(color); + /* TODO: find out how to set background color. */ + *begin = g_strdup_printf("<span style='background-color: %s'>", + *end = g_strdup("</p>"); +/** Convert the msim markup <i> tag (emoticon image) into HTML. */ +msim_markup_i_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end) + struct MSIM_EMOTICON *emote; + name = xmlnode_get_attrib(root, "n"); + purple_debug_info("msim", "msim_markup_i_to_html: <i> w/o n"); + /* TODO: log as unrecognized */ + /* Find and use canonical form of smiley symbol. */ + for (i = 0; (emote = &msim_emoticons[i]) && emote->name != NULL; ++i) { + if (g_str_equal(name, emote->name)) { + *begin = g_strdup(emote->symbol); + /* Couldn't find it, sorry. Try to degrade gracefully. */ + *begin = g_strdup_printf("**%s**", name); +/** Convert an individual msim markup tag to HTML. */ +msim_markup_tag_to_html(MsimSession *session, xmlnode *root, gchar **begin, + if (g_str_equal(root->name, "f")) { + msim_markup_f_to_html(session, root, begin, end); + } else if (g_str_equal(root->name, "a")) { + msim_markup_a_to_html(session, root, begin, end); + } else if (g_str_equal(root->name, "p")) { + msim_markup_p_to_html(session, root, begin, end); + } else if (g_str_equal(root->name, "c")) { + msim_markup_c_to_html(session, root, begin, end); + } else if (g_str_equal(root->name, "b")) { + msim_markup_b_to_html(session, root, begin, end); + } else if (g_str_equal(root->name, "i")) { + msim_markup_i_to_html(session, root, begin, end); + purple_debug_info("msim", "msim_markup_tag_to_html: " + "unknown tag name=%s, ignoring", + (root && root->name) ? root->name : "(NULL)"); +/** Convert an individual HTML tag to msim markup. */ +html_tag_to_msim_markup(MsimSession *session, xmlnode *root, gchar **begin, + if (!purple_utf8_strcasecmp(root->name, "root") || + !purple_utf8_strcasecmp(root->name, "html")) { + /* TODO: Coalesce nested tags into one <f> tag! + * Currently, the 's' value will be overwritten when b/i/u is nested + * within another one, and only the inner-most formatting will be + * applied to the text. */ + } else if (!purple_utf8_strcasecmp(root->name, "b")) { + *begin = g_strdup_printf("<f s='%d'>", MSIM_TEXT_BOLD); + *end = g_strdup("</f>"); + } else if (!purple_utf8_strcasecmp(root->name, "i")) { + *begin = g_strdup_printf("<f s='%d'>", MSIM_TEXT_ITALIC); + *end = g_strdup("</f>"); + } else if (!purple_utf8_strcasecmp(root->name, "u")) { + *begin = g_strdup_printf("<f s='%d'>", MSIM_TEXT_UNDERLINE); + *end = g_strdup("</f>"); + } else if (!purple_utf8_strcasecmp(root->name, "a")) { + const gchar *href, *link_text; + href = xmlnode_get_attrib(root, "href"); + href = xmlnode_get_attrib(root, "HREF"); + link_text = xmlnode_get_data(root); + if (g_str_equal(link_text, href)) { + /* Purple gives us: <a href="URL">URL</a> + * Translate to <a h='URL' /> + * Displayed as text of URL with link to URL + *begin = g_strdup_printf("<a h='%s' />", href); + /* But if we get: <a href="URL">text</a> + * Translate to: text: <a h='URL' /> + * Because official client only supports self-closed <a> + * tags; you can't change the link text. + *begin = g_strdup_printf("%s: <a h='%s' />", link_text, href); + *begin = g_strdup("<a />"); + /* Sorry, kid. MySpace doesn't support you within <a> tags. */ + xmlnode_free(root->child); + } else if (!purple_utf8_strcasecmp(root->name, "font")) { + size = xmlnode_get_attrib(root, "size"); + face = xmlnode_get_attrib(root, "face"); + *begin = g_strdup_printf("<f f='%s' h='%d'>", face, + msim_point_to_height(session, + msim_purple_size_to_point(session, atoi(size)))); + *begin = g_strdup_printf("<f f='%s'>", face); + *begin = g_strdup_printf("<f h='%d'>", + msim_point_to_height(session, + msim_purple_size_to_point(session, atoi(size)))); + *begin = g_strdup("<f>"); + *end = g_strdup("</f>"); + /* TODO: color (bg uses <body>), emoticons */ +#ifdef MSIM_MARKUP_SHOW_UNKNOWN_TAGS + *begin = g_strdup_printf("[%s]", root->name); + *end = g_strdup_printf("[/%s]", root->name); +/** Convert an xmlnode of msim markup or HTML to an HTML string or msim markup. + * @param f Function to convert tags. + * @return An HTML string. Caller frees. +msim_convert_xmlnode(MsimSession *session, xmlnode *root, MSIM_XMLNODE_CONVERT f) + gchar *begin, *inner, *end; + if (!root || !root->name) { + purple_debug_info("msim", "msim_convert_xmlnode: got root=%s\n", + begin = inner = end = NULL; + final = g_string_new(""); + f(session, root, &begin, &end); + g_string_append(final, begin); + /* Loop over all child nodes. */ + for (node = root->child; node != NULL; node = node->next) { + case XMLNODE_TYPE_ATTRIB: + /* Attributes handled above. */ + /* A tag or tag with attributes. Recursively descend. */ + inner = msim_convert_xmlnode(session, node, f); + g_return_val_if_fail(inner != NULL, NULL); + purple_debug_info("msim", " ** node name=%s\n", + (node && node->name) ? node->name : "(NULL)"); + case XMLNODE_TYPE_DATA: + inner = g_new0(char, node->data_sz + 1); + strncpy(inner, node->data, node->data_sz); + inner[node->data_sz] = 0; + purple_debug_info("msim", " ** node data=%s\n", + inner ? inner : "(NULL)"); + purple_debug_info("msim", + "msim_convert_xmlnode: strange node\n"); + g_string_append(final, inner); + /* TODO: Note that msim counts each piece of text enclosed by <f> as + * a paragraph and will display each on its own line. You actually have + * to _nest_ <f> tags to intersperse different text in one paragraph! + * Comment out this line below to see. */ + g_string_append(final, end); + purple_debug_info("msim", "msim_markup_xmlnode_to_gtkhtml: RETURNING %s\n", + (final && final->str) ? final->str : "(NULL)"); +/** Convert XML to something based on MSIM_XMLNODE_CONVERT. */ +msim_convert_xml(MsimSession *session, const gchar *raw, MSIM_XMLNODE_CONVERT f) + g_return_val_if_fail(raw != NULL, NULL); + /* Enclose text in one root tag, to try to make it valid XML for parsing. */ + enclosed_raw = g_strconcat("<root>", raw, "</root>", NULL); + root = xmlnode_from_str(enclosed_raw, -1); + purple_debug_info("msim", "msim_markup_to_html: couldn't parse " + "%s as XML, returning raw: %s\n", enclosed_raw, raw); + /* TODO: msim_unrecognized */ + str = msim_convert_xmlnode(session, root, f); + g_return_val_if_fail(str != NULL, NULL); + purple_debug_info("msim", "msim_markup_to_html: returning %s\n", str); +/** Convert plaintext smileys to <i> markup tags. + * @param before Original text with ASCII smileys. Will be freed. + * @return A new string with <i> tags, if applicable. Must be g_free()'d. +msim_convert_smileys_to_markup(gchar *before) + gchar *old, *new, *replacement; + struct MSIM_EMOTICON *emote; + for (i = 0; (emote = &msim_emoticons[i]) && emote->name != NULL; ++i) { + symbol = emote->symbol; + replacement = g_strdup_printf("<i n=\"%s\"/>", name); + purple_debug_info("msim", "msim_convert_smileys_to_markup: %s->%s\n", + symbol ? symbol : "(NULL)", + replacement ? replacement : "(NULL)"); + new = purple_strreplace(old, symbol, replacement); +/** High-level function to convert MySpaceIM markup to Purple (HTML) markup. + * @return Purple markup string, must be g_free()'d. */ +msim_markup_to_html(MsimSession *session, const gchar *raw) + return msim_convert_xml(session, raw, + (MSIM_XMLNODE_CONVERT)(msim_markup_tag_to_html)); +/** High-level function to convert Purple (HTML) to MySpaceIM markup. + * TODO: consider using purple_markup_html_to_xhtml() to make valid XML. + * @return HTML markup string, must be g_free()'d. */ +html_to_msim_markup(MsimSession *session, const gchar *raw) + markup = msim_convert_xml(session, raw, + (MSIM_XMLNODE_CONVERT)(html_tag_to_msim_markup)); + if (purple_account_get_bool(session->account, "emoticons", TRUE)) { + /* Frees markup and allocates a new one. */ + markup = msim_convert_smileys_to_markup(markup); --- a/libpurple/protocols/myspace/markup.h Mon Sep 17 03:34:11 2007 +0000
+++ b/libpurple/protocols/myspace/markup.h Tue Sep 18 00:47:51 2007 +0000
@@ -1,27 +1,27 @@
-/* MySpaceIM Protocol Plugin - markup
- * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im>
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#ifndef _MYSPACE_MARKUP_H
-#define _MYSPACE_MARKUP_H
-/* High-level msim markup <=> Purple html conversion functions. */
-gchar *msim_markup_to_html(MsimSession *, const gchar *raw);
-gchar *html_to_msim_markup(MsimSession *, const gchar *raw);
-#endif /* !_MYSPACE_MARKUP_H */
+/* MySpaceIM Protocol Plugin - markup + * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im> + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#ifndef _MYSPACE_MARKUP_H +#define _MYSPACE_MARKUP_H +/* High-level msim markup <=> Purple html conversion functions. */ +gchar *msim_markup_to_html(MsimSession *, const gchar *raw); +gchar *html_to_msim_markup(MsimSession *, const gchar *raw); +#endif /* !_MYSPACE_MARKUP_H */ --- a/libpurple/protocols/myspace/session.c Mon Sep 17 03:34:11 2007 +0000
+++ b/libpurple/protocols/myspace/session.c Tue Sep 18 00:47:51 2007 +0000
@@ -1,95 +1,95 @@
-/* MySpaceIM Protocol Plugin, session
- * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im>
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- * Create a new MSIM session.
- * @param acct The account to create the session from.
- * @return Pointer to a new session. Free with msim_session_destroy.
-msim_session_new(PurpleAccount *acct)
- g_return_val_if_fail(acct != NULL, NULL);
- session = g_new0(MsimSession, 1);
- session->magic = MSIM_SESSION_STRUCT_MAGIC;
- session->account = acct;
- session->gc = purple_account_get_connection(acct);
- session->username = NULL;
- session->user_lookup_cb = g_hash_table_new_full(g_direct_hash,
- g_direct_equal, NULL, NULL); /* do NOT free function pointers! (values) */
- session->user_lookup_cb_data = g_hash_table_new_full(g_direct_hash,
- g_direct_equal, NULL, NULL);/* TODO: we don't know what the values are,
- they could be integers inside gpointers
- or strings, so I don't freed them.
- Figure this out, once free cache. */
- /* Created in msim_process_server_info() */
- session->server_info = NULL;
- session->rxbuf = g_new0(gchar, MSIM_READ_BUF_SIZE);
- session->last_comm = time(NULL);
- session->inbox_status = 0;
- * @param session The session to destroy.
-msim_session_destroy(MsimSession *session)
- g_return_if_fail(MSIM_SESSION_VALID(session));
- g_free(session->rxbuf);
- g_free(session->username);
- g_hash_table_destroy(session->user_lookup_cb);
- g_hash_table_destroy(session->user_lookup_cb_data);
- if (session->server_info) {
- msim_msg_free(session->server_info);
+/* MySpaceIM Protocol Plugin, session + * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im> + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Create a new MSIM session. + * @param acct The account to create the session from. + * @return Pointer to a new session. Free with msim_session_destroy. +msim_session_new(PurpleAccount *acct) + g_return_val_if_fail(acct != NULL, NULL); + session = g_new0(MsimSession, 1); + session->magic = MSIM_SESSION_STRUCT_MAGIC; + session->account = acct; + session->gc = purple_account_get_connection(acct); + session->username = NULL; + session->user_lookup_cb = g_hash_table_new_full(g_direct_hash, + g_direct_equal, NULL, NULL); /* do NOT free function pointers! (values) */ + session->user_lookup_cb_data = g_hash_table_new_full(g_direct_hash, + g_direct_equal, NULL, NULL);/* TODO: we don't know what the values are, + they could be integers inside gpointers + or strings, so I don't freed them. + Figure this out, once free cache. */ + /* Created in msim_process_server_info() */ + session->server_info = NULL; + session->rxbuf = g_new0(gchar, MSIM_READ_BUF_SIZE); + session->last_comm = time(NULL); + session->inbox_status = 0; + * @param session The session to destroy. +msim_session_destroy(MsimSession *session) + g_return_if_fail(MSIM_SESSION_VALID(session)); + g_free(session->rxbuf); + g_free(session->username); + g_hash_table_destroy(session->user_lookup_cb); + g_hash_table_destroy(session->user_lookup_cb_data); + if (session->server_info) { + msim_msg_free(session->server_info); --- a/libpurple/protocols/myspace/session.h Mon Sep 17 03:34:11 2007 +0000
+++ b/libpurple/protocols/myspace/session.h Tue Sep 18 00:47:51 2007 +0000
@@ -1,57 +1,57 @@
-/* MySpaceIM Protocol Plugin, session
- * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im>
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#ifndef _MYSPACE_SESSION_H
-#define _MYSPACE_SESSION_H
-/* Random number in every MsimSession, to ensure it is valid. */
-#define MSIM_SESSION_STRUCT_MAGIC 0xe4a6752b
-/* Everything needed to keep track of a session (proto_data field in PurpleConnection) */
-typedef struct _MsimSession
- guint magic; /**< MSIM_SESSION_STRUCT_MAGIC */
- PurpleAccount *account;
- guint sesskey; /**< Session key from server */
- guint userid; /**< This user's numeric user ID */
- gchar *username; /**< This user's unique username */
- gint fd; /**< File descriptor to/from server */
- GHashTable *user_lookup_cb; /**< Username -> userid lookup callback */
- GHashTable *user_lookup_cb_data; /**< Username -> userid lookup callback data */
- MsimMessage *server_info; /**< Parameters from server */
- gchar *rxbuf; /**< Receive buffer */
- guint rxoff; /**< Receive buffer offset */
- guint next_rid; /**< Next request/response ID */
- time_t last_comm; /**< Time received last communication */
- guint inbox_status; /**< Bit field of inbox notifications */
-/* Check if an MsimSession is valid */
-#define MSIM_SESSION_VALID(s) (session != NULL && session->magic == MSIM_SESSION_STRUCT_MAGIC)
-MsimSession *msim_session_new(PurpleAccount *acct);
-void msim_session_destroy(MsimSession *session);
-#endif /* !_MYSPACE_SESSION_H */
+/* MySpaceIM Protocol Plugin, session + * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im> + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#ifndef _MYSPACE_SESSION_H +#define _MYSPACE_SESSION_H +/* Random number in every MsimSession, to ensure it is valid. */ +#define MSIM_SESSION_STRUCT_MAGIC 0xe4a6752b +/* Everything needed to keep track of a session (proto_data field in PurpleConnection) */ +typedef struct _MsimSession + guint magic; /**< MSIM_SESSION_STRUCT_MAGIC */ + PurpleAccount *account; + guint sesskey; /**< Session key from server */ + guint userid; /**< This user's numeric user ID */ + gchar *username; /**< This user's unique username */ + gint fd; /**< File descriptor to/from server */ + GHashTable *user_lookup_cb; /**< Username -> userid lookup callback */ + GHashTable *user_lookup_cb_data; /**< Username -> userid lookup callback data */ + MsimMessage *server_info; /**< Parameters from server */ + gchar *rxbuf; /**< Receive buffer */ + guint rxoff; /**< Receive buffer offset */ + guint next_rid; /**< Next request/response ID */ + time_t last_comm; /**< Time received last communication */ + guint inbox_status; /**< Bit field of inbox notifications */ +/* Check if an MsimSession is valid */ +#define MSIM_SESSION_VALID(s) (session != NULL && session->magic == MSIM_SESSION_STRUCT_MAGIC) +MsimSession *msim_session_new(PurpleAccount *acct); +void msim_session_destroy(MsimSession *session); +#endif /* !_MYSPACE_SESSION_H */ --- a/libpurple/protocols/myspace/user.c Mon Sep 17 03:34:11 2007 +0000
+++ b/libpurple/protocols/myspace/user.c Tue Sep 18 00:47:51 2007 +0000
@@ -1,437 +1,437 @@
-/* MySpaceIM Protocol Plugin, header file
- * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im>
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-static void msim_store_user_info_each(const gchar *key_str, gchar *value_str, MsimUser *user);
-static gchar *msim_format_now_playing(gchar *band, gchar *song);
-static void msim_downloaded_buddy_icon(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *url_text,
- gsize len, const gchar *error_message);
-/** Format the "now playing" indicator, showing the artist and song.
- * @return Return a new string (must be g_free()'d), or NULL.
-msim_format_now_playing(gchar *band, gchar *song)
- if ((band && strlen(band)) || (song && strlen(song))) {
- return g_strdup_printf("%s - %s",
- (band && strlen(band)) ? band : "Unknown Artist",
- (song && strlen(song)) ? song : "Unknown Song");
-/** Get the MsimUser from a PurpleBuddy, creating it if needed. */
-msim_get_user_from_buddy(PurpleBuddy *buddy)
- if (!buddy->proto_data) {
- /* No MsimUser for this buddy; make one. */
- /* TODO: where is this freed? */
- user = g_new0(MsimUser, 1);
- buddy->proto_data = (gpointer)user;
- user = (MsimUser *)(buddy->proto_data);
-/** Find and return an MsimUser * representing a user on the buddy list, or NULL. */
-msim_find_user(MsimSession *session, const gchar *username)
- buddy = purple_find_buddy(session->account, username);
- user = msim_get_user_from_buddy(buddy);
-/** Append user information to a PurpleNotifyUserInfo, given an MsimUser.
- * Used by msim_tooltip_text() and msim_get_info_cb() to show a user's profile.
-msim_append_user_info(MsimSession *session, PurpleNotifyUserInfo *user_info, MsimUser *user, gboolean full)
- /* Useful to identify the account the tooltip refers to.
- * Other prpls show this. */
- purple_notify_user_info_add_pair(user_info, _("User"), user->username);
- uid = purple_blist_node_get_int(&user->buddy->node, "UserID");
- /* TODO: link to username, if available */
- purple_notify_user_info_add_pair(user_info, _("Profile"),
- g_strdup_printf("<a href=\"http://myspace.com/%d\">http://myspace.com/%d</a>",
- /* a/s/l...the vitals */
- purple_notify_user_info_add_pair(user_info, _("Age"),
- g_strdup_printf("%d", user->age));
- if (user->gender && strlen(user->gender)) {
- purple_notify_user_info_add_pair(user_info, _("Gender"), user->gender);
- if (user->location && strlen(user->location)) {
- purple_notify_user_info_add_pair(user_info, _("Location"), user->location);
- /* Other information */
- if (user->headline && strlen(user->headline)) {
- purple_notify_user_info_add_pair(user_info, _("Headline"), user->headline);
- str = msim_format_now_playing(user->band_name, user->song_name);
- if (str && strlen(str)) {
- purple_notify_user_info_add_pair(user_info, _("Song"), str);
- /* Note: total friends only available if looked up by uid, not username. */
- if (user->total_friends) {
- purple_notify_user_info_add_pair(user_info, _("Total Friends"),
- g_strdup_printf("%d", user->total_friends));
- /* Client information */
- str = user->client_info;
- purple_notify_user_info_add_pair(user_info, _("Client Version"),
- g_strdup_printf("%s (build %d)", str, cv));
- purple_notify_user_info_add_pair(user_info, _("Client Version"),
- purple_notify_user_info_add_pair(user_info, _("Client Version"),
- g_strdup_printf("Build %d", cv));
-/** Store a field of information about a buddy. */
-msim_store_user_info_each(const gchar *key_str, gchar *value_str, MsimUser *user)
- if (g_str_equal(key_str, "UserID") || g_str_equal(key_str, "ContactID")) {
- /* Save to buddy list, if it exists, for quick cached uid lookup with msim_uid2username_from_blist(). */
- purple_debug_info("msim", "associating uid %s with username %s\n", key_str, user->buddy->name);
- purple_blist_node_set_int(&user->buddy->node, "UserID", atol(value_str));
- /* Need to store in MsimUser, too? What if not on blist? */
- } else if (g_str_equal(key_str, "Age")) {
- user->age = atol(value_str);
- } else if (g_str_equal(key_str, "Gender")) {
- user->gender = g_strdup(value_str);
- } else if (g_str_equal(key_str, "Location")) {
- user->location = g_strdup(value_str);
- } else if (g_str_equal(key_str, "TotalFriends")) {
- user->total_friends = atol(value_str);
- } else if (g_str_equal(key_str, "DisplayName")) {
- user->display_name = g_strdup(value_str);
- } else if (g_str_equal(key_str, "BandName")) {
- user->band_name = g_strdup(value_str);
- } else if (g_str_equal(key_str, "SongName")) {
- user->song_name = g_strdup(value_str);
- } else if (g_str_equal(key_str, "UserName") || g_str_equal(key_str, "IMName") || g_str_equal(key_str, "NickName")) {
- /* Ignore because PurpleBuddy knows this already */
- } else if (g_str_equal(key_str, "ImageURL") || g_str_equal(key_str, "AvatarURL")) {
- const gchar *previous_url;
- user->image_url = g_strdup(value_str);
- /* Instead of showing 'no photo' picture, show nothing. */
- if (g_str_equal(user->image_url, "http://x.myspace.com/images/no_pic.gif"))
- purple_buddy_icons_set_for_user(user->buddy->account,
- /* TODO: use ETag for checksum */
- previous_url = purple_buddy_icons_get_checksum_for_user(user->buddy);
- /* Only download if URL changed */
- if (!previous_url || !g_str_equal(previous_url, user->image_url)) {
- purple_util_fetch_url(user->image_url, TRUE, NULL, TRUE, msim_downloaded_buddy_icon, (gpointer)user);
- } else if (g_str_equal(key_str, "LastImageUpdated")) {
- /* TODO: use somewhere */
- user->last_image_updated = atol(value_str);
- } else if (g_str_equal(key_str, "Headline")) {
- user->headline = g_strdup(value_str);
- /* TODO: other fields in MsimUser */
- msg = g_strdup_printf("msim_store_user_info_each: unknown field %s=%s",
- msim_unrecognized(NULL, NULL, msg);
-/** Save buddy information to the buddy list from a user info reply message.
- * @param msg The user information reply, with any amount of information.
- * @param user The structure to save to, or NULL to save in PurpleBuddy->proto_data.
- * Variable information is saved to the passed MsimUser structure. Permanent
- * information (UserID) is stored in the blist node of the buddy list (and
- * ends up in blist.xml, persisted to disk) if it exists.
- * If the function has no buddy information, this function
- * is a no-op (and returns FALSE).
-msim_store_user_info(MsimSession *session, MsimMessage *msg, MsimUser *user)
- MsimMessage *body, *body_node;
- g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE);
- g_return_val_if_fail(msg != NULL, FALSE);
- body = msim_msg_get_dictionary(msg, "body");
- username = msim_msg_get_string(body, "UserName");
- purple_debug_info("msim",
- "msim_process_reply: not caching body, no UserName\n");
- /* Null user = find and store in PurpleBuddy's proto_data */
- user = msim_find_user(session, username);
- /* TODO: make looping over MsimMessage's easier. */
- body_node = msim_msg_get_next_element_node(body_node))
- MsimMessageElement *elem;
- elem = (MsimMessageElement *)body_node->data;
- value_str = msim_msg_get_string_from_element(elem);
- msim_store_user_info_each(key_str, value_str, user);
- if (msim_msg_get_integer(msg, "dsn") == MG_OWN_IM_INFO_DSN &&
- msim_msg_get_integer(msg, "lid") == MG_OWN_IM_INFO_LID) {
- /* TODO: do something with our own IM info, if we need it for some
- * specific purpose. Otherwise it is available on the buddy list,
- * if the user has themselves as their own buddy.
- * However, much of the info is already available in MsimSession,
- * stored in msim_we_are_logged_on(). */
- } else if (msim_msg_get_integer(msg, "dsn") == MG_OWN_MYSPACE_INFO_DSN &&
- msim_msg_get_integer(msg, "lid") == MG_OWN_MYSPACE_INFO_LID) {
- /* TODO: same as above, but for MySpace info. */
- * Asynchronously lookup user information, calling callback when receive result.
- * @param user The user id, email address, or username. Not freed.
- * @param cb Callback, called with user information when available.
- * @param data An arbitray data pointer passed to the callback.
-/* TODO: change to not use callbacks */
-msim_lookup_user(MsimSession *session, const gchar *user, MSIM_USER_LOOKUP_CB cb, gpointer data)
- guint rid, cmd, dsn, lid;
- g_return_if_fail(MSIM_SESSION_VALID(session));
- g_return_if_fail(user != NULL);
- /* Callback can be null to not call anything, just lookup & store information. */
- /*g_return_if_fail(cb != NULL);*/
- purple_debug_info("msim", "msim_lookup_userid: "
- "asynchronously looking up <%s>\n", user);
- msim_msg_dump("msim_lookup_user: data=%s\n", (MsimMessage *)data);
- /* Setup callback. Response will be associated with request using 'rid'. */
- rid = msim_new_reply_callback(session, cb, data);
- if (msim_is_userid(user)) {
- dsn = MG_MYSPACE_INFO_BY_ID_DSN;
- lid = MG_MYSPACE_INFO_BY_ID_LID;
- } else if (msim_is_email(user)) {
- dsn = MG_MYSPACE_INFO_BY_STRING_DSN;
- lid = MG_MYSPACE_INFO_BY_STRING_LID;
- field_name = "UserName";
- dsn = MG_MYSPACE_INFO_BY_STRING_DSN;
- lid = MG_MYSPACE_INFO_BY_STRING_LID;
- field_name, MSIM_TYPE_STRING, g_strdup(user),
- g_return_if_fail(msim_send(session,
- "persist", MSIM_TYPE_INTEGER, 1,
- "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
- "cmd", MSIM_TYPE_INTEGER, 1,
- "dsn", MSIM_TYPE_INTEGER, dsn,
- "uid", MSIM_TYPE_INTEGER, session->userid,
- "lid", MSIM_TYPE_INTEGER, lid,
- "rid", MSIM_TYPE_INTEGER, rid,
- "body", MSIM_TYPE_DICTIONARY, body,
- * Check if a string is a userid (all numeric).
- * @param user The user id, email, or name.
- * @return TRUE if is userid, FALSE if not.
-msim_is_userid(const gchar *user)
- g_return_val_if_fail(user != NULL, FALSE);
- return strspn(user, "0123456789") == strlen(user);
- * Check if a string is an email address (contains an @).
- * @param user The user id, email, or name.
- * @return TRUE if is an email, FALSE if not.
- * This function is not intended to be used as a generic
- * means of validating email addresses, but to distinguish
- * between a user represented by an email address from
- * other forms of identification.
-msim_is_email(const gchar *user)
- g_return_val_if_fail(user != NULL, FALSE);
- return strchr(user, '@') != NULL;
-/** Callback for when a buddy icon finished being downloaded. */
-msim_downloaded_buddy_icon(PurpleUtilFetchUrlData *url_data,
- const gchar *error_message)
- user = (MsimUser *)user_data;
- purple_debug_info("msim_downloaded_buddy_icon",
- "Downloaded %d bytes\n", len);
- purple_debug_info("msim_downloaded_buddy_icon",
- "failed to download icon for %s",
- purple_buddy_icons_set_for_user(user->buddy->account,
- g_memdup((gchar *)url_text, len), len,
- /* Use URL itself as buddy icon "checksum" (TODO: ETag) */
- user->image_url); /* checksum */
+/* MySpaceIM Protocol Plugin, header file + * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im> + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +static void msim_store_user_info_each(const gchar *key_str, gchar *value_str, MsimUser *user); +static gchar *msim_format_now_playing(gchar *band, gchar *song); +static void msim_downloaded_buddy_icon(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *url_text, + gsize len, const gchar *error_message); +/** Format the "now playing" indicator, showing the artist and song. + * @return Return a new string (must be g_free()'d), or NULL. +msim_format_now_playing(gchar *band, gchar *song) + if ((band && strlen(band)) || (song && strlen(song))) { + return g_strdup_printf("%s - %s", + (band && strlen(band)) ? band : "Unknown Artist", + (song && strlen(song)) ? song : "Unknown Song"); +/** Get the MsimUser from a PurpleBuddy, creating it if needed. */ +msim_get_user_from_buddy(PurpleBuddy *buddy) + if (!buddy->proto_data) { + /* No MsimUser for this buddy; make one. */ + /* TODO: where is this freed? */ + user = g_new0(MsimUser, 1); + buddy->proto_data = (gpointer)user; + user = (MsimUser *)(buddy->proto_data); +/** Find and return an MsimUser * representing a user on the buddy list, or NULL. */ +msim_find_user(MsimSession *session, const gchar *username) + buddy = purple_find_buddy(session->account, username); + user = msim_get_user_from_buddy(buddy); +/** Append user information to a PurpleNotifyUserInfo, given an MsimUser. + * Used by msim_tooltip_text() and msim_get_info_cb() to show a user's profile. +msim_append_user_info(MsimSession *session, PurpleNotifyUserInfo *user_info, MsimUser *user, gboolean full) + /* Useful to identify the account the tooltip refers to. + * Other prpls show this. */ + purple_notify_user_info_add_pair(user_info, _("User"), user->username); + uid = purple_blist_node_get_int(&user->buddy->node, "UserID"); + /* TODO: link to username, if available */ + purple_notify_user_info_add_pair(user_info, _("Profile"), + g_strdup_printf("<a href=\"http://myspace.com/%d\">http://myspace.com/%d</a>", + /* a/s/l...the vitals */ + purple_notify_user_info_add_pair(user_info, _("Age"), + g_strdup_printf("%d", user->age)); + if (user->gender && strlen(user->gender)) { + purple_notify_user_info_add_pair(user_info, _("Gender"), user->gender); + if (user->location && strlen(user->location)) { + purple_notify_user_info_add_pair(user_info, _("Location"), user->location); + /* Other information */ + if (user->headline && strlen(user->headline)) { + purple_notify_user_info_add_pair(user_info, _("Headline"), user->headline); + str = msim_format_now_playing(user->band_name, user->song_name); + if (str && strlen(str)) { + purple_notify_user_info_add_pair(user_info, _("Song"), str); + /* Note: total friends only available if looked up by uid, not username. */ + if (user->total_friends) { + purple_notify_user_info_add_pair(user_info, _("Total Friends"), + g_strdup_printf("%d", user->total_friends)); + /* Client information */ + str = user->client_info; + purple_notify_user_info_add_pair(user_info, _("Client Version"), + g_strdup_printf("%s (build %d)", str, cv)); + purple_notify_user_info_add_pair(user_info, _("Client Version"), + purple_notify_user_info_add_pair(user_info, _("Client Version"), + g_strdup_printf("Build %d", cv)); +/** Store a field of information about a buddy. */ +msim_store_user_info_each(const gchar *key_str, gchar *value_str, MsimUser *user) + if (g_str_equal(key_str, "UserID") || g_str_equal(key_str, "ContactID")) { + /* Save to buddy list, if it exists, for quick cached uid lookup with msim_uid2username_from_blist(). */ + purple_debug_info("msim", "associating uid %s with username %s\n", key_str, user->buddy->name); + purple_blist_node_set_int(&user->buddy->node, "UserID", atol(value_str)); + /* Need to store in MsimUser, too? What if not on blist? */ + } else if (g_str_equal(key_str, "Age")) { + user->age = atol(value_str); + } else if (g_str_equal(key_str, "Gender")) { + user->gender = g_strdup(value_str); + } else if (g_str_equal(key_str, "Location")) { + user->location = g_strdup(value_str); + } else if (g_str_equal(key_str, "TotalFriends")) { + user->total_friends = atol(value_str); + } else if (g_str_equal(key_str, "DisplayName")) { + user->display_name = g_strdup(value_str); + } else if (g_str_equal(key_str, "BandName")) { + user->band_name = g_strdup(value_str); + } else if (g_str_equal(key_str, "SongName")) { + user->song_name = g_strdup(value_str); + } else if (g_str_equal(key_str, "UserName") || g_str_equal(key_str, "IMName") || g_str_equal(key_str, "NickName")) { + /* Ignore because PurpleBuddy knows this already */ + } else if (g_str_equal(key_str, "ImageURL") || g_str_equal(key_str, "AvatarURL")) { + const gchar *previous_url; + user->image_url = g_strdup(value_str); + /* Instead of showing 'no photo' picture, show nothing. */ + if (g_str_equal(user->image_url, "http://x.myspace.com/images/no_pic.gif")) + purple_buddy_icons_set_for_user(user->buddy->account, + /* TODO: use ETag for checksum */ + previous_url = purple_buddy_icons_get_checksum_for_user(user->buddy); + /* Only download if URL changed */ + if (!previous_url || !g_str_equal(previous_url, user->image_url)) { + purple_util_fetch_url(user->image_url, TRUE, NULL, TRUE, msim_downloaded_buddy_icon, (gpointer)user); + } else if (g_str_equal(key_str, "LastImageUpdated")) { + /* TODO: use somewhere */ + user->last_image_updated = atol(value_str); + } else if (g_str_equal(key_str, "Headline")) { + user->headline = g_strdup(value_str); + /* TODO: other fields in MsimUser */ + msg = g_strdup_printf("msim_store_user_info_each: unknown field %s=%s", + msim_unrecognized(NULL, NULL, msg); +/** Save buddy information to the buddy list from a user info reply message. + * @param msg The user information reply, with any amount of information. + * @param user The structure to save to, or NULL to save in PurpleBuddy->proto_data. + * Variable information is saved to the passed MsimUser structure. Permanent + * information (UserID) is stored in the blist node of the buddy list (and + * ends up in blist.xml, persisted to disk) if it exists. + * If the function has no buddy information, this function + * is a no-op (and returns FALSE). +msim_store_user_info(MsimSession *session, MsimMessage *msg, MsimUser *user) + MsimMessage *body, *body_node; + g_return_val_if_fail(MSIM_SESSION_VALID(session), FALSE); + g_return_val_if_fail(msg != NULL, FALSE); + body = msim_msg_get_dictionary(msg, "body"); + username = msim_msg_get_string(body, "UserName"); + purple_debug_info("msim", + "msim_process_reply: not caching body, no UserName\n"); + /* Null user = find and store in PurpleBuddy's proto_data */ + user = msim_find_user(session, username); + /* TODO: make looping over MsimMessage's easier. */ + body_node = msim_msg_get_next_element_node(body_node)) + MsimMessageElement *elem; + elem = (MsimMessageElement *)body_node->data; + value_str = msim_msg_get_string_from_element(elem); + msim_store_user_info_each(key_str, value_str, user); + if (msim_msg_get_integer(msg, "dsn") == MG_OWN_IM_INFO_DSN && + msim_msg_get_integer(msg, "lid") == MG_OWN_IM_INFO_LID) { + /* TODO: do something with our own IM info, if we need it for some + * specific purpose. Otherwise it is available on the buddy list, + * if the user has themselves as their own buddy. + * However, much of the info is already available in MsimSession, + * stored in msim_we_are_logged_on(). */ + } else if (msim_msg_get_integer(msg, "dsn") == MG_OWN_MYSPACE_INFO_DSN && + msim_msg_get_integer(msg, "lid") == MG_OWN_MYSPACE_INFO_LID) { + /* TODO: same as above, but for MySpace info. */ + * Asynchronously lookup user information, calling callback when receive result. + * @param user The user id, email address, or username. Not freed. + * @param cb Callback, called with user information when available. + * @param data An arbitray data pointer passed to the callback. +/* TODO: change to not use callbacks */ +msim_lookup_user(MsimSession *session, const gchar *user, MSIM_USER_LOOKUP_CB cb, gpointer data) + guint rid, cmd, dsn, lid; + g_return_if_fail(MSIM_SESSION_VALID(session)); + g_return_if_fail(user != NULL); + /* Callback can be null to not call anything, just lookup & store information. */ + /*g_return_if_fail(cb != NULL);*/ + purple_debug_info("msim", "msim_lookup_userid: " + "asynchronously looking up <%s>\n", user); + msim_msg_dump("msim_lookup_user: data=%s\n", (MsimMessage *)data); + /* Setup callback. Response will be associated with request using 'rid'. */ + rid = msim_new_reply_callback(session, cb, data); + if (msim_is_userid(user)) { + dsn = MG_MYSPACE_INFO_BY_ID_DSN; + lid = MG_MYSPACE_INFO_BY_ID_LID; + } else if (msim_is_email(user)) { + dsn = MG_MYSPACE_INFO_BY_STRING_DSN; + lid = MG_MYSPACE_INFO_BY_STRING_LID; + field_name = "UserName"; + dsn = MG_MYSPACE_INFO_BY_STRING_DSN; + lid = MG_MYSPACE_INFO_BY_STRING_LID; + field_name, MSIM_TYPE_STRING, g_strdup(user), + g_return_if_fail(msim_send(session, + "persist", MSIM_TYPE_INTEGER, 1, + "sesskey", MSIM_TYPE_INTEGER, session->sesskey, + "cmd", MSIM_TYPE_INTEGER, 1, + "dsn", MSIM_TYPE_INTEGER, dsn, + "uid", MSIM_TYPE_INTEGER, session->userid, + "lid", MSIM_TYPE_INTEGER, lid, + "rid", MSIM_TYPE_INTEGER, rid, + "body", MSIM_TYPE_DICTIONARY, body, + * Check if a string is a userid (all numeric). + * @param user The user id, email, or name. + * @return TRUE if is userid, FALSE if not. +msim_is_userid(const gchar *user) + g_return_val_if_fail(user != NULL, FALSE); + return strspn(user, "0123456789") == strlen(user); + * Check if a string is an email address (contains an @). + * @param user The user id, email, or name. + * @return TRUE if is an email, FALSE if not. + * This function is not intended to be used as a generic + * means of validating email addresses, but to distinguish + * between a user represented by an email address from + * other forms of identification. +msim_is_email(const gchar *user) + g_return_val_if_fail(user != NULL, FALSE); + return strchr(user, '@') != NULL; +/** Callback for when a buddy icon finished being downloaded. */ +msim_downloaded_buddy_icon(PurpleUtilFetchUrlData *url_data, + const gchar *error_message) + user = (MsimUser *)user_data; + purple_debug_info("msim_downloaded_buddy_icon", + "Downloaded %d bytes\n", len); + purple_debug_info("msim_downloaded_buddy_icon", + "failed to download icon for %s", + purple_buddy_icons_set_for_user(user->buddy->account, + g_memdup((gchar *)url_text, len), len, + /* Use URL itself as buddy icon "checksum" (TODO: ETag) */ + user->image_url); /* checksum */ --- a/libpurple/protocols/myspace/user.h Mon Sep 17 03:34:11 2007 +0000
+++ b/libpurple/protocols/myspace/user.h Tue Sep 18 00:47:51 2007 +0000
@@ -1,55 +1,55 @@
-/* MySpaceIM Protocol Plugin, header file
- * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im>
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-/* Hold ephemeral information about buddies, for proto_data of PurpleBuddy. */
-typedef struct _MsimUser
- /* Note: uid is in &buddy->node (set_blist_node_int), since it never changes */
- gchar *band_name, *song_name;
- guint last_image_updated;
-/* Callback function pointer type for when a user's information is received,
- * initiated from a user lookup. */
-typedef void (*MSIM_USER_LOOKUP_CB)(MsimSession *session, MsimMessage *userinfo, gpointer data);
-MsimUser *msim_get_user_from_buddy(PurpleBuddy *buddy);
-MsimUser *msim_find_user(MsimSession *session, const gchar *username);
-void msim_append_user_info(MsimSession *session, PurpleNotifyUserInfo *user_info, MsimUser *user, gboolean full);
-gboolean msim_store_user_info(MsimSession *session, MsimMessage *msg, MsimUser *user);
-gboolean msim_is_userid(const gchar *user);
-gboolean msim_is_email(const gchar *user);
-void msim_lookup_user(MsimSession *session, const gchar *user, MSIM_USER_LOOKUP_CB cb, gpointer data);
-#endif /* !_MYSPACE_USER_H */
+/* MySpaceIM Protocol Plugin, header file + * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im> + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +/* Hold ephemeral information about buddies, for proto_data of PurpleBuddy. */ +typedef struct _MsimUser + /* Note: uid is in &buddy->node (set_blist_node_int), since it never changes */ + gchar *band_name, *song_name; + guint last_image_updated; +/* Callback function pointer type for when a user's information is received, + * initiated from a user lookup. */ +typedef void (*MSIM_USER_LOOKUP_CB)(MsimSession *session, MsimMessage *userinfo, gpointer data); +MsimUser *msim_get_user_from_buddy(PurpleBuddy *buddy); +MsimUser *msim_find_user(MsimSession *session, const gchar *username); +void msim_append_user_info(MsimSession *session, PurpleNotifyUserInfo *user_info, MsimUser *user, gboolean full); +gboolean msim_store_user_info(MsimSession *session, MsimMessage *msg, MsimUser *user); +gboolean msim_is_userid(const gchar *user); +gboolean msim_is_email(const gchar *user); +void msim_lookup_user(MsimSession *session, const gchar *user, MSIM_USER_LOOKUP_CB cb, gpointer data); +#endif /* !_MYSPACE_USER_H */ --- a/libpurple/protocols/myspace/zap.c Mon Sep 17 03:34:11 2007 +0000
+++ b/libpurple/protocols/myspace/zap.c Tue Sep 18 00:47:51 2007 +0000
@@ -1,265 +1,265 @@
-/* MySpaceIM Protocol Plugin - zap support
- * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im>
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-static gboolean msim_send_zap(MsimSession *session, const gchar *username, guint code);
-static void msim_send_zap_from_menu(PurpleBlistNode *node, gpointer zap_num_ptr);
-msim_attention_types(PurpleAccount *acct)
- static GList *types = NULL;
- MsimAttentionType* attn;
-#define _MSIM_ADD_NEW_ATTENTION(icn, nme, incoming, outgoing) \
- attn = g_new0(MsimAttentionType, 1); \
- attn->icon_name = icn; \
- attn->incoming_description = incoming; \
- attn->outgoing_description = outgoing; \
- types = g_list_append(types, attn);
- /* TODO: icons for each zap */
- _MSIM_ADD_NEW_ATTENTION(NULL, _("zap"), _("zapped"), _("Zapping"));
- _MSIM_ADD_NEW_ATTENTION(NULL, _("whack"), _("whacked"), _("Whacking"));
- _MSIM_ADD_NEW_ATTENTION(NULL, _("torch"), _("torched"), _("Torching"));
- _MSIM_ADD_NEW_ATTENTION(NULL, _("smooch"), _("smooched"), _("Smooching"));
- _MSIM_ADD_NEW_ATTENTION(NULL, _("hug"), _("hugged"), _("Hugging"));
- _MSIM_ADD_NEW_ATTENTION(NULL, _("bslap"), _("bslapped"), _("Bslapping"));
- _MSIM_ADD_NEW_ATTENTION(NULL, _("goose"), _("goosed"), _("Goosing"));
- _MSIM_ADD_NEW_ATTENTION(NULL, _("hi-five"), _("hi-fived"), _("Hi-fiving"));
- _MSIM_ADD_NEW_ATTENTION(NULL, _("punk"), _("punk'd"), _("Punking"));
- _MSIM_ADD_NEW_ATTENTION(NULL, _("raspberry"), _("raspberried"), _("Raspberry'ing"));
-msim_send_attention(PurpleConnection *gc, const gchar *username, guint code)
- MsimAttentionType *attn;
- session = (MsimSession *)gc->proto_data;
- /* Look for this attention type, by the code index given. */
- types = msim_attention_types(gc->account);
- attn = (MsimAttentionType *)g_list_nth_data(types, code);
- purple_debug_info("msim_send_attention", "got invalid zap code %d\n", code);
- buddy = purple_find_buddy(session->account, username);
- msim_send_zap(session, username, code);
-/** Send a zap to a user. */
-msim_send_zap(MsimSession *session, const gchar *username, guint code)
-#ifndef MSIM_USE_ATTENTION_API
- MsimAttentionType *attn;
- gchar *zap_description;
- g_return_val_if_fail(session != NULL, FALSE);
- g_return_val_if_fail(username != NULL, FALSE);
-#ifdef MSIM_USE_ATTENTION_API
- /* serv_send_attention(session->gc, username, code); */
- types = msim_attention_types(session->account);
- attn = g_list_nth_data(types, code);
- zap_description = g_strdup_printf("*** Attention: %s %s ***", attn->outgoing_description,
- serv_got_im(session->gc, username, zap_description,
- PURPLE_MESSAGE_SEND | PURPLE_MESSAGE_SYSTEM, time(NULL));
- g_free(zap_description);
- /* Construct and send the actual zap command. */
- zap_string = g_strdup_printf("!!!ZAP_SEND!!!=RTE_BTN_ZAPS_%d", code);
- if (!msim_send_bm(session, username, zap_string, MSIM_BM_ACTION)) {
- purple_debug_info("msim_send_zap_from_menu", "msim_send_bm failed: zapping %s with %s",
-/** Zap someone. Callback from msim_blist_node_menu zap menu. */
-msim_send_zap_from_menu(PurpleBlistNode *node, gpointer zap_num_ptr)
- PurpleAccount *account;
- if (!PURPLE_BLIST_NODE_IS_BUDDY(node)) {
- /* Only know about buddies for now. */
- g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
- buddy = (PurpleBuddy *)node;
- account = buddy->account;
- gc = purple_account_get_connection(account);
- session = (MsimSession *)gc->proto_data;
- zap = GPOINTER_TO_INT(zap_num_ptr);
-#ifdef MSIM_USE_ATTENTION_API
- serv_send_attention(session->gc, buddy->name, zap);
- g_return_if_fail(msim_send_zap(session, buddy->name, zap));
-/** Return menu, if any, for a buddy list node. */
-msim_blist_node_menu(PurpleBlistNode *node)
- GList *menu, *zap_menu;
- /* Warning: hardcoded to match that in msim_attention_types. */
- const gchar *zap_names[10];
- if (!PURPLE_BLIST_NODE_IS_BUDDY(node)) {
- /* Only know about buddies for now. */
- /* Names from official client. */
- types = msim_attention_types(NULL);
- MsimAttentionType *attn;
- attn = (MsimAttentionType *)types->data;
- zap_names[i] = attn->name;
- } while ((types = g_list_next(types)));
- menu = zap_menu = NULL;
- /* TODO: get rid of once is accessible directly in GUI */
- for (i = 0; i < sizeof(zap_names) / sizeof(zap_names[0]); ++i) {
- act = purple_menu_action_new(zap_names[i], PURPLE_CALLBACK(msim_send_zap_from_menu),
- GUINT_TO_POINTER(i), NULL);
- zap_menu = g_list_append(zap_menu, act);
- act = purple_menu_action_new(_("Zap"), NULL, NULL, zap_menu);
- menu = g_list_append(menu, act);
-/** Process an incoming zap. */
-msim_incoming_zap(MsimSession *session, MsimMessage *msg)
- gchar *msg_text, *username;
-#ifndef MSIM_USE_ATTENTION_API
- const gchar *zap_past_tense[10];
- zap_past_tense[0] = _("zapped");
- zap_past_tense[1] = _("whacked");
- zap_past_tense[2] = _("torched");
- zap_past_tense[3] = _("smooched");
- zap_past_tense[4] = _("hugged");
- zap_past_tense[5] = _("bslapped");
- zap_past_tense[6] = _("goosed");
- zap_past_tense[7] = _("hi-fived");
- zap_past_tense[8] = _("punk'd");
- zap_past_tense[9] = _("raspberried");
- msg_text = msim_msg_get_string(msg, "msg");
- username = msim_msg_get_string(msg, "_username");
- g_return_val_if_fail(msg_text != NULL, FALSE);
- g_return_val_if_fail(username != NULL, FALSE);
- g_return_val_if_fail(sscanf(msg_text, "!!!ZAP_SEND!!!=RTE_BTN_ZAPS_%d", &zap) == 1, FALSE);
- zap = CLAMP(zap, 0, 9);
-#ifdef MSIM_USE_ATTENTION_API
- serv_got_attention(session->gc, username, zap);
- zap_text = g_strdup_printf(_("*** You have been %s! ***"), zap_past_tense[zap]);
- serv_got_im(session->gc, username, zap_text,
- PURPLE_MESSAGE_RECV | PURPLE_MESSAGE_SYSTEM, time(NULL));
+/* MySpaceIM Protocol Plugin - zap support + * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im> + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +static gboolean msim_send_zap(MsimSession *session, const gchar *username, guint code); +static void msim_send_zap_from_menu(PurpleBlistNode *node, gpointer zap_num_ptr); +msim_attention_types(PurpleAccount *acct) + static GList *types = NULL; + MsimAttentionType* attn; +#define _MSIM_ADD_NEW_ATTENTION(icn, nme, incoming, outgoing) \ + attn = g_new0(MsimAttentionType, 1); \ + attn->icon_name = icn; \ + attn->incoming_description = incoming; \ + attn->outgoing_description = outgoing; \ + types = g_list_append(types, attn); + /* TODO: icons for each zap */ + _MSIM_ADD_NEW_ATTENTION(NULL, _("zap"), _("zapped"), _("Zapping")); + _MSIM_ADD_NEW_ATTENTION(NULL, _("whack"), _("whacked"), _("Whacking")); + _MSIM_ADD_NEW_ATTENTION(NULL, _("torch"), _("torched"), _("Torching")); + _MSIM_ADD_NEW_ATTENTION(NULL, _("smooch"), _("smooched"), _("Smooching")); + _MSIM_ADD_NEW_ATTENTION(NULL, _("hug"), _("hugged"), _("Hugging")); + _MSIM_ADD_NEW_ATTENTION(NULL, _("bslap"), _("bslapped"), _("Bslapping")); + _MSIM_ADD_NEW_ATTENTION(NULL, _("goose"), _("goosed"), _("Goosing")); + _MSIM_ADD_NEW_ATTENTION(NULL, _("hi-five"), _("hi-fived"), _("Hi-fiving")); + _MSIM_ADD_NEW_ATTENTION(NULL, _("punk"), _("punk'd"), _("Punking")); + _MSIM_ADD_NEW_ATTENTION(NULL, _("raspberry"), _("raspberried"), _("Raspberry'ing")); +msim_send_attention(PurpleConnection *gc, const gchar *username, guint code) + MsimAttentionType *attn; + session = (MsimSession *)gc->proto_data; + /* Look for this attention type, by the code index given. */ + types = msim_attention_types(gc->account); + attn = (MsimAttentionType *)g_list_nth_data(types, code); + purple_debug_info("msim_send_attention", "got invalid zap code %d\n", code); + buddy = purple_find_buddy(session->account, username); + msim_send_zap(session, username, code); +/** Send a zap to a user. */ +msim_send_zap(MsimSession *session, const gchar *username, guint code) +#ifndef MSIM_USE_ATTENTION_API + MsimAttentionType *attn; + gchar *zap_description; + g_return_val_if_fail(session != NULL, FALSE); + g_return_val_if_fail(username != NULL, FALSE); +#ifdef MSIM_USE_ATTENTION_API + /* serv_send_attention(session->gc, username, code); */ + types = msim_attention_types(session->account); + attn = g_list_nth_data(types, code); + zap_description = g_strdup_printf("*** Attention: %s %s ***", attn->outgoing_description, + serv_got_im(session->gc, username, zap_description, + PURPLE_MESSAGE_SEND | PURPLE_MESSAGE_SYSTEM, time(NULL)); + g_free(zap_description); + /* Construct and send the actual zap command. */ + zap_string = g_strdup_printf("!!!ZAP_SEND!!!=RTE_BTN_ZAPS_%d", code); + if (!msim_send_bm(session, username, zap_string, MSIM_BM_ACTION)) { + purple_debug_info("msim_send_zap_from_menu", "msim_send_bm failed: zapping %s with %s", +/** Zap someone. Callback from msim_blist_node_menu zap menu. */ +msim_send_zap_from_menu(PurpleBlistNode *node, gpointer zap_num_ptr) + PurpleAccount *account; + if (!PURPLE_BLIST_NODE_IS_BUDDY(node)) { + /* Only know about buddies for now. */ + g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); + buddy = (PurpleBuddy *)node; + account = buddy->account; + gc = purple_account_get_connection(account); + session = (MsimSession *)gc->proto_data; + zap = GPOINTER_TO_INT(zap_num_ptr); +#ifdef MSIM_USE_ATTENTION_API + serv_send_attention(session->gc, buddy->name, zap); + g_return_if_fail(msim_send_zap(session, buddy->name, zap)); +/** Return menu, if any, for a buddy list node. */ +msim_blist_node_menu(PurpleBlistNode *node) + GList *menu, *zap_menu; + /* Warning: hardcoded to match that in msim_attention_types. */ + const gchar *zap_names[10]; + if (!PURPLE_BLIST_NODE_IS_BUDDY(node)) { + /* Only know about buddies for now. */ + /* Names from official client. */ + types = msim_attention_types(NULL); + MsimAttentionType *attn; + attn = (MsimAttentionType *)types->data; + zap_names[i] = attn->name; + } while ((types = g_list_next(types))); + menu = zap_menu = NULL; + /* TODO: get rid of once is accessible directly in GUI */ + for (i = 0; i < sizeof(zap_names) / sizeof(zap_names[0]); ++i) { + act = purple_menu_action_new(zap_names[i], PURPLE_CALLBACK(msim_send_zap_from_menu), + GUINT_TO_POINTER(i), NULL); + zap_menu = g_list_append(zap_menu, act); + act = purple_menu_action_new(_("Zap"), NULL, NULL, zap_menu); + menu = g_list_append(menu, act); +/** Process an incoming zap. */ +msim_incoming_zap(MsimSession *session, MsimMessage *msg) + gchar *msg_text, *username; +#ifndef MSIM_USE_ATTENTION_API + const gchar *zap_past_tense[10]; + zap_past_tense[0] = _("zapped"); + zap_past_tense[1] = _("whacked"); + zap_past_tense[2] = _("torched"); + zap_past_tense[3] = _("smooched"); + zap_past_tense[4] = _("hugged"); + zap_past_tense[5] = _("bslapped"); + zap_past_tense[6] = _("goosed"); + zap_past_tense[7] = _("hi-fived"); + zap_past_tense[8] = _("punk'd"); + zap_past_tense[9] = _("raspberried"); + msg_text = msim_msg_get_string(msg, "msg"); + username = msim_msg_get_string(msg, "_username"); + g_return_val_if_fail(msg_text != NULL, FALSE); + g_return_val_if_fail(username != NULL, FALSE); + g_return_val_if_fail(sscanf(msg_text, "!!!ZAP_SEND!!!=RTE_BTN_ZAPS_%d", &zap) == 1, FALSE); + zap = CLAMP(zap, 0, 9); +#ifdef MSIM_USE_ATTENTION_API + serv_got_attention(session->gc, username, zap); + zap_text = g_strdup_printf(_("*** You have been %s! ***"), zap_past_tense[zap]); + serv_got_im(session->gc, username, zap_text, + PURPLE_MESSAGE_RECV | PURPLE_MESSAGE_SYSTEM, time(NULL)); --- a/libpurple/protocols/myspace/zap.h Mon Sep 17 03:34:11 2007 +0000
+++ b/libpurple/protocols/myspace/zap.h Tue Sep 18 00:47:51 2007 +0000
@@ -1,28 +1,28 @@
-/* MySpaceIM Protocol Plugin - zap support
- * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im>
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-GList *msim_attention_types(PurpleAccount *acct);
-gboolean msim_send_attention(PurpleConnection *gc, const gchar *username, guint code);
-GList *msim_blist_node_menu(PurpleBlistNode *node);
-gboolean msim_incoming_zap(MsimSession *session, MsimMessage *msg);
-#endif /* !_MYSPACE_ZAP_H */
+/* MySpaceIM Protocol Plugin - zap support + * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im> + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +GList *msim_attention_types(PurpleAccount *acct); +gboolean msim_send_attention(PurpleConnection *gc, const gchar *username, guint code); +GList *msim_blist_node_menu(PurpleBlistNode *node); +gboolean msim_incoming_zap(MsimSession *session, MsimMessage *msg); +#endif /* !_MYSPACE_ZAP_H */