From: <the...@us...> - 2006-08-18 06:18:50
|
Revision: 16831 Author: thekingant Date: 2006-08-17 23:18:38 -0700 (Thu, 17 Aug 2006) ViewCVS: http://svn.sourceforge.net/gaim/?rev=16831&view=rev Log Message: ----------- Backport SVN revisions 16815-16830 from HEAD to v2_0_0, excluding 16818 and 16827 (they were conflicting--I'll get to them in a minute). Original commit messages: 16815: If g_open isn't a macro, we need to specify the mode variable 16816: I will apologize in advance for this ugliness - it is necessary because we have a "connect" macro to cause the wgaim_connect() wrapper function to be used. 16817: nosnilmot pointed out that I'm an idiot and this is a far less ugly way to achieve the same goal. (I swear I tried it first, but must have not actually saved the file when I tested it). 16819: Patch to eggtrayicon by Dan Winship makes icon transparent 16820: Fix CID 250 (also change the behavior to be slightly more sane) and 213 (which wouldn't happen unless the sasl library returned some weird values) 16821: Patch #1523103 ("Improved markup processing"): "This patch tries to handle all the html-entities (including stuff like ® and &#xx;) in gaim_markup_strip_html and gaim_unescape_html. This also allows fixing the issue with libxml2 where & was being converted to &." 16822: Patch #1541742 ("Add boolean property \"iconsel\" for Statusbox"): "This adds a boolean property "iconsel" for statusbox. Setting the property to TRUE shows the icon-selector, setting it to FALSE removes it. It would allow plugins like mystatusbox to better control the statusboxes, especially the per-account ones." 16823: Patch #1541744 ("Memleak"): "This plugs a possible memleak." The memleak would happen if you switch from an account with account-options to an account with none. 16824: This is better. 16825: deryni noticed a missing ')' (it turns out I had SASL disabled) 16826: Fix asserts at startup. 16828: Get rid of an assertion failure when the selected icon is not a valid image 16829: Just rename connect to connectfunc. This is what it was like before my changes. Now I know why! 16830: Patch from Henning Nor?\195?\169n to not show ICQ users as "pending" when they are away without a message Modified Paths: -------------- branches/v2_0_0/COPYRIGHT branches/v2_0_0/ChangeLog branches/v2_0_0/plugins/docklet/eggtrayicon.c branches/v2_0_0/src/gtkaccount.c branches/v2_0_0/src/gtkstatusbox.c branches/v2_0_0/src/protocols/jabber/auth.c branches/v2_0_0/src/protocols/oscar/oscar.c branches/v2_0_0/src/protocols/silc/util.c branches/v2_0_0/src/sslconn.c branches/v2_0_0/src/sslconn.h branches/v2_0_0/src/util.c branches/v2_0_0/src/xmlnode.c Modified: branches/v2_0_0/COPYRIGHT =================================================================== --- branches/v2_0_0/COPYRIGHT 2006-08-18 05:59:47 UTC (rev 16830) +++ branches/v2_0_0/COPYRIGHT 2006-08-18 06:18:38 UTC (rev 16831) @@ -316,6 +316,7 @@ Dan Willemsen Jason Willis Matt Wilson +Dan Winship Scott Wolchok Pui Lam Wong Justin Wood Modified: branches/v2_0_0/ChangeLog =================================================================== --- branches/v2_0_0/ChangeLog 2006-08-18 05:59:47 UTC (rev 16830) +++ branches/v2_0_0/ChangeLog 2006-08-18 06:18:38 UTC (rev 16831) @@ -99,6 +99,7 @@ removed. * 'Highlight when nick said' option added to Message Notification plugin. + * The system tray icon is now transparent (Dan Winship) MSN Features: * Custom smiley receiving support (Irving Cordova & Francesco Fracassi) Modified: branches/v2_0_0/plugins/docklet/eggtrayicon.c =================================================================== --- branches/v2_0_0/plugins/docklet/eggtrayicon.c 2006-08-18 05:59:47 UTC (rev 16830) +++ branches/v2_0_0/plugins/docklet/eggtrayicon.c 2006-08-18 06:18:38 UTC (rev 16831) @@ -54,6 +54,9 @@ static void egg_tray_icon_realize (GtkWidget *widget); static void egg_tray_icon_unrealize (GtkWidget *widget); +static void egg_tray_icon_add (GtkContainer *container, + GtkWidget *widget); + static void egg_tray_icon_update_manager_window (EggTrayIcon *icon, gboolean dock_if_realized); static void egg_tray_icon_manager_window_destroyed (EggTrayIcon *icon); @@ -109,6 +112,7 @@ { GObjectClass *gobject_class = (GObjectClass *)klass; GtkWidgetClass *widget_class = (GtkWidgetClass *)klass; + GtkContainerClass *container_class = (GtkContainerClass *)klass; parent_class = g_type_class_peek_parent (klass); @@ -117,6 +121,8 @@ widget_class->realize = egg_tray_icon_realize; widget_class->unrealize = egg_tray_icon_unrealize; + container_class->add = egg_tray_icon_add; + g_object_class_install_property (gobject_class, PROP_ORIENTATION, g_param_spec_enum ("orientation", @@ -374,7 +380,37 @@ egg_tray_icon_update_manager_window (icon, TRUE); } +static gboolean +transparent_expose_event (GtkWidget *widget, GdkEventExpose *event, gpointer user_data) +{ + gdk_window_clear_area (widget->window, event->area.x, event->area.y, + event->area.width, event->area.height); + return FALSE; +} + static void +make_transparent_again (GtkWidget *widget, GtkStyle *previous_style, + gpointer user_data) +{ + gdk_window_set_back_pixmap(widget->window, NULL, TRUE); +} + +static void +make_transparent (GtkWidget *widget, gpointer user_data) +{ + if (GTK_WIDGET_NO_WINDOW (widget) || GTK_WIDGET_APP_PAINTABLE (widget)) + return; + + gtk_widget_set_app_paintable (widget, TRUE); + gtk_widget_set_double_buffered (widget, FALSE); + gdk_window_set_back_pixmap (widget->window, NULL, TRUE); + g_signal_connect (widget, "expose_event", + G_CALLBACK (transparent_expose_event), NULL); + g_signal_connect_after (widget, "style_set", + G_CALLBACK (make_transparent_again), NULL); +} + +static void egg_tray_icon_realize (GtkWidget *widget) { EggTrayIcon *icon = EGG_TRAY_ICON (widget); @@ -386,6 +422,8 @@ if (GTK_WIDGET_CLASS (parent_class)->realize) GTK_WIDGET_CLASS (parent_class)->realize (widget); + make_transparent (widget, NULL); + #if GTK_CHECK_VERSION(2,1,0) screen = gdk_screen_get_number (gtk_widget_get_screen (widget)); xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (widget)); @@ -425,6 +463,14 @@ egg_tray_icon_manager_filter, icon); } +static void +egg_tray_icon_add (GtkContainer *container, GtkWidget *widget) +{ + g_signal_connect (widget, "realize", + G_CALLBACK (make_transparent), NULL); + GTK_CONTAINER_CLASS (parent_class)->add (container, widget); +} + #if GTK_CHECK_VERSION(2,1,0) EggTrayIcon * egg_tray_icon_new_for_screen (GdkScreen *screen, const char *name) Modified: branches/v2_0_0/src/gtkaccount.c =================================================================== --- branches/v2_0_0/src/gtkaccount.c 2006-08-18 05:59:47 UTC (rev 16830) +++ branches/v2_0_0/src/gtkaccount.c 2006-08-18 06:18:38 UTC (rev 16831) @@ -646,6 +646,11 @@ dialog->protocol_frame = NULL; } + if (dialog->protocol_opt_entries != NULL) { + g_list_free(dialog->protocol_opt_entries); + dialog->protocol_opt_entries = NULL; + } + if (dialog->prpl_info == NULL || dialog->prpl_info->protocol_options == NULL) { @@ -669,11 +674,6 @@ gtk_container_add(GTK_CONTAINER(frame), vbox); gtk_widget_show(vbox); - if (dialog->protocol_opt_entries != NULL) { - g_list_free(dialog->protocol_opt_entries); - dialog->protocol_opt_entries = NULL; - } - for (l = dialog->prpl_info->protocol_options; l != NULL; l = l->next) { option = (GaimAccountOption *)l->data; Modified: branches/v2_0_0/src/gtkstatusbox.c =================================================================== --- branches/v2_0_0/src/gtkstatusbox.c 2006-08-18 05:59:47 UTC (rev 16830) +++ branches/v2_0_0/src/gtkstatusbox.c 2006-08-18 06:18:38 UTC (rev 16831) @@ -115,7 +115,8 @@ enum { PROP_0, - PROP_ACCOUNT + PROP_ACCOUNT, + PROP_ICON_SEL, }; GtkComboBoxClass *parent_class = NULL; @@ -163,6 +164,9 @@ case PROP_ACCOUNT: g_value_set_pointer(value, statusbox->account); break; + case PROP_ICON_SEL: + g_value_set_boolean(value, statusbox->icon_box != NULL); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, psec); break; @@ -253,6 +257,9 @@ static void setup_icon_box(GtkGaimStatusBox *status_box) { + if (status_box->icon_box != NULL) + return; + if (status_box->account && !gaim_account_get_ui_bool(status_box->account, GAIM_GTK_UI, "use-global-buddyicon", TRUE)) { @@ -280,12 +287,54 @@ } static void +destroy_icon_box(GtkGaimStatusBox *statusbox) +{ + if (statusbox->icon_box == NULL) + return; + + gtk_widget_destroy(statusbox->icon_box); + gdk_cursor_unref(statusbox->hand_cursor); + gdk_cursor_unref(statusbox->arrow_cursor); + + g_object_unref(G_OBJECT(statusbox->buddy_icon)); + g_object_unref(G_OBJECT(statusbox->buddy_icon_hover)); + + if (statusbox->buddy_icon_sel) + gtk_widget_destroy(statusbox->buddy_icon_sel); + + g_free(statusbox->buddy_icon_path); + + statusbox->icon_box = NULL; + statusbox->buddy_icon_path = NULL; + statusbox->buddy_icon = NULL; + statusbox->buddy_icon_hover = NULL; + statusbox->hand_cursor = NULL; + statusbox->arrow_cursor = NULL; +} + +static void gtk_gaim_status_box_set_property(GObject *object, guint param_id, const GValue *value, GParamSpec *pspec) { GtkGaimStatusBox *statusbox = GTK_GAIM_STATUS_BOX(object); switch (param_id) { + case PROP_ICON_SEL: + if (g_value_get_boolean(value)) { + if (statusbox->account) { + GaimPlugin *plug = gaim_plugins_find_with_id(gaim_account_get_protocol_id(statusbox->account)); + if (plug) { + GaimPluginProtocolInfo *prplinfo = GAIM_PLUGIN_PROTOCOL_INFO(plug); + if (prplinfo && prplinfo->icon_spec.format != NULL) + setup_icon_box(statusbox); + } + } else { + setup_icon_box(statusbox); + } + } else { + destroy_icon_box(statusbox); + } + break; case PROP_ACCOUNT: statusbox->account = g_value_get_pointer(value); @@ -296,16 +345,9 @@ } if (statusbox->account) { - GaimPlugin *plug = gaim_plugins_find_with_id(gaim_account_get_protocol_id(statusbox->account)); - GaimPluginProtocolInfo *prplinfo = GAIM_PLUGIN_PROTOCOL_INFO(plug); - if (prplinfo && prplinfo->icon_spec.format != NULL) { - setup_icon_box(statusbox); - } statusbox->status_changed_signal = gaim_signal_connect(gaim_accounts_get_handle(), "account-status-changed", statusbox, GAIM_CALLBACK(account_status_changed_cb), statusbox); - } else { - setup_icon_box(statusbox); } gtk_gaim_status_box_regenerate(statusbox); @@ -365,6 +407,7 @@ combo_box_forall = container_class->forall; container_class->forall = gtk_gaim_status_box_forall; + container_class->remove = NULL; object_class = (GObjectClass *)klass; @@ -381,6 +424,15 @@ G_PARAM_READWRITE ) ); + g_object_class_install_property(object_class, + PROP_ICON_SEL, + g_param_spec_boolean("iconsel", + "Icon Selector", + "Whether the icon selector should be displayed or not.", + FALSE, + G_PARAM_READWRITE + ) + ); } /** @@ -1001,6 +1053,7 @@ gaim_account_set_buddy_icon(box->account, icon); g_free(icon); gaim_account_set_ui_bool(box->account, GAIM_GTK_UI, "use-global-buddyicon", FALSE); + gaim_account_set_ui_string(box->account, GAIM_GTK_UI, "non-global-buddyicon", icon); } } } else { @@ -1218,17 +1271,22 @@ if (status_box->icon_size != icon_alc.height) { + if (status_box->buddy_icon_hover) + g_object_unref(status_box->buddy_icon_hover); if ((status_box->buddy_icon_path != NULL) && (*status_box->buddy_icon_path != '\0')) { scaled = gdk_pixbuf_new_from_file_at_scale(status_box->buddy_icon_path, icon_alc.height, icon_alc.width, FALSE, NULL); - g_object_unref(status_box->buddy_icon_hover); - status_box->buddy_icon_hover = gdk_pixbuf_copy(scaled); - do_colorshift(status_box->buddy_icon_hover, status_box->buddy_icon_hover, 30); - g_object_unref(status_box->buddy_icon); - status_box->buddy_icon = scaled; - gtk_image_set_from_pixbuf(GTK_IMAGE(status_box->icon), status_box->buddy_icon); + if (scaled != NULL) + { + status_box->buddy_icon_hover = gdk_pixbuf_copy(scaled); + do_colorshift(status_box->buddy_icon_hover, status_box->buddy_icon_hover, 30); + if (status_box->buddy_icon) + g_object_unref(status_box->buddy_icon); + status_box->buddy_icon = scaled; + gtk_image_set_from_pixbuf(GTK_IMAGE(status_box->icon), status_box->buddy_icon); + } } status_box->icon_size = icon_alc.height; } @@ -1247,7 +1305,8 @@ GtkGaimStatusBox *status_box = GTK_GAIM_STATUS_BOX(widget); gtk_container_propagate_expose(GTK_CONTAINER(widget), status_box->vbox, event); gtk_container_propagate_expose(GTK_CONTAINER(widget), status_box->toggle_button, event); - gtk_container_propagate_expose(GTK_CONTAINER(widget), status_box->icon_box, event); + if (status_box->icon_box) + gtk_container_propagate_expose(GTK_CONTAINER(widget), status_box->icon_box, event); return FALSE; } @@ -1274,13 +1333,15 @@ GtkWidget * gtk_gaim_status_box_new() { - return g_object_new(GTK_GAIM_TYPE_STATUS_BOX, "account", NULL, NULL); + return g_object_new(GTK_GAIM_TYPE_STATUS_BOX, "account", NULL, + "iconsel", TRUE, NULL); } GtkWidget * gtk_gaim_status_box_new_with_account(GaimAccount *account) { - return g_object_new(GTK_GAIM_TYPE_STATUS_BOX, "account", account, NULL); + return g_object_new(GTK_GAIM_TYPE_STATUS_BOX, "account", account, + "iconsel", TRUE, NULL); } /** @@ -1384,14 +1445,18 @@ { if (box->buddy_icon != NULL) g_object_unref(box->buddy_icon); - scaled = gdk_pixbuf_new_from_file_at_scale(filename, - box->icon_size, box->icon_size, FALSE, NULL); - if (scaled != NULL) - { - box->buddy_icon_hover = gdk_pixbuf_copy(scaled); - do_colorshift(box->buddy_icon_hover, box->buddy_icon_hover, 30); - box->buddy_icon = scaled; - gtk_image_set_from_pixbuf(GTK_IMAGE(box->icon), box->buddy_icon); + + /* This will get called before the box is shown and will not have a size */ + if (box->icon_size > 0) { + scaled = gdk_pixbuf_new_from_file_at_scale(filename, + box->icon_size, box->icon_size, FALSE, NULL); + if (scaled != NULL) + { + box->buddy_icon_hover = gdk_pixbuf_copy(scaled); + do_colorshift(box->buddy_icon_hover, box->buddy_icon_hover, 30); + box->buddy_icon = scaled; + gtk_image_set_from_pixbuf(GTK_IMAGE(box->icon), box->buddy_icon); + } } } Modified: branches/v2_0_0/src/protocols/jabber/auth.c =================================================================== --- branches/v2_0_0/src/protocols/jabber/auth.c 2006-08-18 05:59:47 UTC (rev 16830) +++ branches/v2_0_0/src/protocols/jabber/auth.c 2006-08-18 06:18:38 UTC (rev 16831) @@ -181,9 +181,9 @@ static void jabber_auth_start_cyrus(JabberStream *js) { - const char *clientout, *mech; + const char *clientout = NULL, *mech = NULL; char *enc_out; - unsigned coutlen; + unsigned coutlen = 0; xmlnode *auth; sasl_security_properties_t secprops; gboolean again; @@ -256,21 +256,29 @@ /* For everything else, fail the mechanism and try again */ default: gaim_debug_info("sasl", "sasl_state is %d, failing the mech and trying again\n", js->sasl_state); - if (strlen(mech)>0) { + + /* + * DAA: is this right? + * The manpage says that "mech" will contain the chosen mechanism on success. + * Presumably, if we get here that isn't the case and we shouldn't try again? + * I suspect that this never happens. + */ + if (mech && strlen(mech) > 0) { char *pos; - pos = strstr(js->sasl_mechs->str,mech); - g_assert(pos!=NULL); - g_string_erase(js->sasl_mechs, pos-js->sasl_mechs->str,strlen(mech)); + if ((pos = strstr(js->sasl_mechs->str, mech))) { + g_string_erase(js->sasl_mechs, pos-js->sasl_mechs->str, strlen(mech)); + } + again = TRUE; } + sasl_dispose(&js->sasl); - again=TRUE; } } while (again); if (js->sasl_state == SASL_CONTINUE || js->sasl_state == SASL_OK) { auth = xmlnode_new("auth"); xmlnode_set_namespace(auth, "urn:ietf:params:xml:ns:xmpp-sasl"); - xmlnode_set_attrib(auth,"mechanism", mech); + xmlnode_set_attrib(auth, "mechanism", mech); if (clientout) { if (coutlen == 0) { xmlnode_insert_data(auth, "=", -1); @@ -332,7 +340,7 @@ char *mech_name = xmlnode_get_data(mechnode); #ifdef HAVE_CYRUS_SASL g_string_append(js->sasl_mechs, mech_name); - g_string_append_c(js->sasl_mechs,' '); + g_string_append_c(js->sasl_mechs, ' '); #else if(mech_name && !strcmp(mech_name, "DIGEST-MD5")) digest_md5 = TRUE; Modified: branches/v2_0_0/src/protocols/oscar/oscar.c =================================================================== --- branches/v2_0_0/src/protocols/oscar/oscar.c 2006-08-18 05:59:47 UTC (rev 16830) +++ branches/v2_0_0/src/protocols/oscar/oscar.c 2006-08-18 06:18:38 UTC (rev 16831) @@ -2885,6 +2885,9 @@ gaim_status_set_attr_string(status, "message", message); g_free(message); } + else + /* Set an empty message so that we know not to show "pending" */ + gaim_status_set_attr_string(status, "message", message); gaim_blist_update_buddy_status(b, status); } Modified: branches/v2_0_0/src/protocols/silc/util.c =================================================================== --- branches/v2_0_0/src/protocols/silc/util.c 2006-08-18 05:59:47 UTC (rev 16830) +++ branches/v2_0_0/src/protocols/silc/util.c 2006-08-18 06:18:38 UTC (rev 16831) @@ -234,7 +234,7 @@ } #endif - if ((fd = g_open(file_private_key, O_RDONLY)) != -1) { + if ((fd = g_open(file_private_key, O_RDONLY, 0)) != -1) { if ((fstat(fd, &st)) == -1) { gaim_debug_error("silc", "Couldn't stat '%s' private key, error: %s\n", file_private_key, strerror(errno)); @@ -254,7 +254,7 @@ return FALSE; } - if ((fd = g_open(file_private_key, O_RDONLY)) != -1) { + if ((fd = g_open(file_private_key, O_RDONLY, 0)) != -1) { if ((fstat(fd, &st)) == -1) { gaim_debug_error("silc", "Couldn't stat '%s' private key, error: %s\n", file_private_key, strerror(errno)); Modified: branches/v2_0_0/src/sslconn.c =================================================================== --- branches/v2_0_0/src/sslconn.c 2006-08-18 05:59:47 UTC (rev 16830) +++ branches/v2_0_0/src/sslconn.c 2006-08-18 06:18:38 UTC (rev 16831) @@ -46,7 +46,7 @@ ops = gaim_ssl_get_ops(); if ((ops == NULL) || (ops->init == NULL) || (ops->uninit == NULL) || - (ops->connect == NULL) || (ops->close == NULL) || + (ops->connectfunc == NULL) || (ops->close == NULL) || (ops->read == NULL) || (ops->write == NULL)) { return FALSE; @@ -87,7 +87,7 @@ gsc->fd = source; ops = gaim_ssl_get_ops(); - ops->connect(gsc); + ops->connectfunc(gsc); } GaimSslConnection * @@ -177,7 +177,7 @@ gsc->fd = fd; ops = gaim_ssl_get_ops(); - ops->connect(gsc); + ops->connectfunc(gsc); return (GaimSslConnection *)gsc; } Modified: branches/v2_0_0/src/sslconn.h =================================================================== --- branches/v2_0_0/src/sslconn.h 2006-08-18 05:59:47 UTC (rev 16830) +++ branches/v2_0_0/src/sslconn.h 2006-08-18 06:18:38 UTC (rev 16831) @@ -68,7 +68,7 @@ { gboolean (*init)(void); void (*uninit)(void); - void (*connect)(GaimSslConnection *gsc); + void (*connectfunc)(GaimSslConnection *gsc); void (*close)(GaimSslConnection *gsc); size_t (*read)(GaimSslConnection *gsc, void *data, size_t len); size_t (*write)(GaimSslConnection *gsc, const void *data, size_t len); Modified: branches/v2_0_0/src/util.c =================================================================== --- branches/v2_0_0/src/util.c 2006-08-18 05:59:47 UTC (rev 16830) +++ branches/v2_0_0/src/util.c 2006-08-18 06:18:38 UTC (rev 16831) @@ -854,6 +854,55 @@ /************************************************************************** * Markup Functions **************************************************************************/ + +/* Returns a NULL-terminated string after unescaping an entity + * (eg. &, < & etc.) starting at s. Returns NULL on failure.*/ +static const char * +detect_entity(const char *text, int *length) +{ + const char *pln; + int len, pound; + + if (!text || *text != '&') + return NULL; + +#define IS_ENTITY(s) (!g_ascii_strncasecmp(text, s, (len = sizeof(s) - 1))) + + if(IS_ENTITY("&")) + pln = "&"; + else if(IS_ENTITY("<")) + pln = "<"; + else if(IS_ENTITY(">")) + pln = ">"; + else if(IS_ENTITY(" ")) + pln = " "; + else if(IS_ENTITY("©")) + pln = "\302\251"; /* or use g_unichar_to_utf8(0xa9); */ + else if(IS_ENTITY(""")) + pln = "\""; + else if(IS_ENTITY("®")) + pln = "\302\256"; /* or use g_unichar_to_utf8(0xae); */ + else if(IS_ENTITY("'")) + pln = "\'"; + else if(*(text+1) == '#' && (sscanf(text, "&#%u;", £) == 1) && + pound != 0 && *(text+3+(gint)log10(pound)) == ';') { + static char buf[7]; + int buflen = g_unichar_to_utf8((gunichar)pound, buf); + buf[buflen] = '\0'; + pln = buf; + + len = 2; + while(isdigit((gint) text[len])) len++; + if(text[len] == ';') len++; + } + else + return NULL; + + if (length) + *length = len; + return pln; +} + gboolean gaim_markup_find_tag(const char *needle, const char *haystack, const char **start, const char **end, GData **attributes) @@ -1443,44 +1492,10 @@ } } else if(*c == '&') { char buf[7]; - char *pln; - int len = 1; - guint pound; - if(!g_ascii_strncasecmp(c, "&", 5)) { - pln = "&"; - len = 5; - } else if(!g_ascii_strncasecmp(c, "<", 4)) { - pln = "<"; - len = 4; - } else if(!g_ascii_strncasecmp(c, ">", 4)) { - pln = ">"; - len = 4; - } else if(!g_ascii_strncasecmp(c, " ", 6)) { - pln = " "; - len = 6; - } else if(!g_ascii_strncasecmp(c, "©", 6)) { - pln = "©"; - len = 6; - } else if(!g_ascii_strncasecmp(c, """, 6)) { - pln = "\""; - len = 6; - } else if(!g_ascii_strncasecmp(c, "®", 5)) { - pln = "®"; - len = 5; - } else if(!g_ascii_strncasecmp(c, "'", 6)) { - pln = "\'"; - len = 6; - } else if(*(c+1) == '#' && (sscanf(c, "&#%u;", £) == 1) && - pound != 0 && *(c+3+(gint)log10(pound)) == ';') { - int buflen = g_unichar_to_utf8((gunichar)pound, buf); - buf[buflen] = '\0'; - pln = buf; + const char *pln; + int len; - - len = 2; - while(isdigit((gint) c [len])) len++; - if(c [len] == ';') len++; - } else { + if ((pln = detect_entity(c, &len)) == NULL) { len = 1; g_snprintf(buf, sizeof(buf), "%c", *c); pln = buf; @@ -1522,11 +1537,11 @@ char * gaim_markup_strip_html(const char *str) { - int i, j, k; + int i, j, k, entlen; gboolean visible = TRUE; gboolean closing_td_p = FALSE; gchar *str2; - const gchar *cdata_close_tag = NULL; + const gchar *cdata_close_tag = NULL, *ent; gchar *href = NULL; int href_st = 0; @@ -1685,44 +1700,14 @@ visible = TRUE; } - /* XXX: This sucks. We need to be un-escaping all entities, which - * includes these, as well as the &#num; ones */ - - if (str2[i] == '&' && strncasecmp(str2 + i, """, 6) == 0) + if (str2[i] == '&' && (ent = detect_entity(str2 + i, &entlen)) != NULL) { - str2[j++] = '\"'; - i = i + 5; - continue; - } - - if (str2[i] == '&' && strncasecmp(str2 + i, "&", 5) == 0) - { - str2[j++] = '&'; - i = i + 4; + while (*ent) + str2[j++] = *ent++; + i += entlen - 1; continue; } - if (str2[i] == '&' && strncasecmp(str2 + i, "<", 4) == 0) - { - str2[j++] = '<'; - i = i + 3; - continue; - } - - if (str2[i] == '&' && strncasecmp(str2 + i, ">", 4) == 0) - { - str2[j++] = '>'; - i = i + 3; - continue; - } - - if (str2[i] == '&' && strncasecmp(str2 + i, "'", 6) == 0) - { - str2[j++] = '\''; - i = i + 5; - continue; - } - if (visible) str2[j++] = g_ascii_isspace(str2[i])? ' ': str2[i]; } @@ -2026,41 +2011,28 @@ char * gaim_unescape_html(const char *html) { - const char *c; - GString *ret; + if (html != NULL) { + const char *c = html; + GString *ret = g_string_new(""); + while (*c) { + int len; + const char *ent; - if (html == NULL) - return NULL; - - c = html; - ret = g_string_new(""); - while (*c) { - if (!strncmp(c, "&", 5)) { - ret = g_string_append_c(ret, '&'); - c += 5; - } else if (!strncmp(c, "<", 4)) { - ret = g_string_append_c(ret, '<'); - c += 4; - } else if (!strncmp(c, ">", 4)) { - ret = g_string_append_c(ret, '>'); - c += 4; - } else if (!strncmp(c, """, 6)) { - ret = g_string_append_c(ret, '"'); - c += 6; - } else if (!strncmp(c, "'", 6)) { - ret = g_string_append_c(ret, '\''); - c += 6; - } else if (!strncmp(c, "<br>", 4)) { - ret = g_string_append_c(ret, '\n'); - c += 4; - } else { - ret = g_string_append_c(ret, *c); - c++; + if ((ent = detect_entity(c, &len)) != NULL) { + ret = g_string_append(ret, ent); + c += len; + } else if (!strncmp(c, "<br>", 4)) { + ret = g_string_append_c(ret, '\n'); + c += 4; + } else { + ret = g_string_append_c(ret, *c); + c++; + } } + return g_string_free(ret, FALSE); } - return g_string_free(ret, FALSE); - + return NULL; } char * @@ -3996,4 +3968,3 @@ return buf; } - Modified: branches/v2_0_0/src/xmlnode.c =================================================================== --- branches/v2_0_0/src/xmlnode.c 2006-08-18 05:59:47 UTC (rev 16830) +++ branches/v2_0_0/src/xmlnode.c 2006-08-18 06:18:38 UTC (rev 16831) @@ -35,6 +35,7 @@ #include <string.h> #include <glib.h> +#include "util.h" #include "xmlnode.h" #ifdef _WIN32 @@ -406,6 +407,11 @@ char *attrib = g_malloc(attrib_len + 1); memcpy(attrib, attributes[i+3], attrib_len); attrib[attrib_len] = '\0'; +#ifdef HAVE_LIBXML + char *txt = attrib; + attrib = gaim_unescape_html(txt); + g_free(txt); +#endif xmlnode_set_attrib(node, attributes[i], attrib); g_free(attrib); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |