Merge lp:~larsu/indicator-messages/lp1386584 into lp:indicator-messages/15.04

Proposed by Lars Karlitski
Status: Merged
Approved by: Ted Gould
Approved revision: 429
Merged at revision: 433
Proposed branch: lp:~larsu/indicator-messages/lp1386584
Merge into: lp:indicator-messages/15.04
Diff against target: 315 lines (+113/-23)
1 file modified
src/im-application-list.c (+113/-23)
To merge this branch: bzr merge lp:~larsu/indicator-messages/lp1386584
Reviewer Review Type Date Requested Status
Ted Gould (community) Approve
Sebastien Bacher Approve
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+240773@code.launchpad.net

Commit message

Escape message and source ids when using them as action names

Description of the change

Escape message and source ids when using them as action names

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Sebastien Bacher (seb128) wrote :

I didn't review the code but just gave it a round of testing and I can confirm indicator-messages is still working and it's not segfaulting anymore, good job ;-)

Revision history for this message
Sebastien Bacher (seb128) wrote :

There is no segfault but the notifications fail to clear when you view the messages (it's doing it at least for xchat-gnome and tb, if you get some ping/emails, and go read them, the counter in the launcher is cleared but the envelop stay on blue and the corresponding line is not cleared)

review: Needs Fixing
429. By Lars Karlitski

Also escape message and source ids when removing them from the app

The last commit missed these two places.

Revision history for this message
Lars Karlitski (larsu) wrote :

You're right. I missed two instances of escaping. Thanks for testing!

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Sebastien Bacher (seb128) wrote :

The new version works fine, it resolve the segfault issue as well.

Ted/Charles, could you do a code review for it?

review: Approve
Revision history for this message
Ted Gould (ted) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/im-application-list.c'
--- src/im-application-list.c 2014-10-10 15:22:50 +0000
+++ src/im-application-list.c 2014-11-07 11:43:25 +0000
@@ -134,6 +134,62 @@
134 return retval;134 return retval;
135}135}
136136
137static gchar *
138escape_action_name (const gchar *name)
139{
140 static const gchar *xdigits = "0123456789abcdef";
141 GString *escaped;
142 gchar c;
143
144 g_return_val_if_fail (name != NULL, NULL);
145
146 escaped = g_string_new (NULL);
147 while ((c = *name++))
148 {
149 if (g_ascii_isalnum (c) || c == '.')
150 {
151 g_string_append_c (escaped, c);
152 }
153 else
154 {
155 g_string_append_c (escaped, '-');
156 g_string_append_c (escaped, xdigits[c >> 4]);
157 g_string_append_c (escaped, xdigits[c & 0xf]);
158 }
159 }
160
161 return g_string_free (escaped, FALSE);
162}
163
164static gchar *
165unescape_action_name (const gchar *name)
166{
167 GString *unescaped;
168 gint i;
169
170 g_return_val_if_fail (name != NULL, NULL);
171
172 unescaped = g_string_new (NULL);
173 for (i = 0; name[i]; i++)
174 {
175 gint one, two;
176
177 if (name[i] == '-' &&
178 (one = g_ascii_xdigit_value (name[i + 1])) >= 0 &&
179 (two = g_ascii_xdigit_value (name[i + 2])) >= 0)
180 {
181 g_string_append_c (unescaped, (one << 4) & two);
182 i += 2;
183 }
184 else
185 {
186 g_string_append_c (unescaped, name[i]);
187 }
188 }
189
190 return g_string_free (unescaped, FALSE);
191}
192
137/* Check to see if either of our action groups has any actions, if193/* Check to see if either of our action groups has any actions, if
138 so return TRUE so we get chosen! */194 so return TRUE so we get chosen! */
139static gboolean195static gboolean
@@ -293,12 +349,17 @@
293im_application_list_source_removed (Application *app,349im_application_list_source_removed (Application *app,
294 const gchar *id)350 const gchar *id)
295{351{
296 g_action_map_remove_action (G_ACTION_MAP(app->source_actions), id);352 gchar *action_name;
297353
298 g_signal_emit (app->list, signals[SOURCE_REMOVED], 0, app->id, id);354 action_name = escape_action_name (id);
355
356 g_action_map_remove_action (G_ACTION_MAP(app->source_actions), action_name);
357 g_signal_emit (app->list, signals[SOURCE_REMOVED], 0, app->id, action_name);
299358
300 if (application_update_draws_attention(app))359 if (application_update_draws_attention(app))
301 im_application_list_update_root_action (app->list);360 im_application_list_update_root_action (app->list);
361
362 g_free (action_name);
302}363}
303364
304static void365static void
@@ -307,9 +368,11 @@
307 gpointer user_data)368 gpointer user_data)
308{369{
309 Application *app = user_data;370 Application *app = user_data;
310 const gchar *source_id;371 const gchar *action_name;
372 gchar *source_id;
311373
312 source_id = g_action_get_name (G_ACTION (action));374 action_name = g_action_get_name (G_ACTION (action));
375 source_id = unescape_action_name (action_name);
313376
314 if (g_variant_get_boolean (parameter))377 if (g_variant_get_boolean (parameter))
315 {378 {
@@ -326,20 +389,28 @@
326 app->cancellable, NULL, NULL);389 app->cancellable, NULL, NULL);
327 }390 }
328391
329 im_application_list_source_removed (app, source_id);392 im_application_list_source_removed (app, action_name);
393
394 g_free (source_id);
330}395}
331396
332static void397static void
333im_application_list_message_removed (Application *app,398im_application_list_message_removed (Application *app,
334 const gchar *id)399 const gchar *id)
335{400{
336 g_action_map_remove_action (G_ACTION_MAP(app->message_actions), id);401 gchar *action_name;
337 g_action_muxer_remove (app->message_sub_actions, id);402
403 action_name = escape_action_name (id);
404
405 g_action_map_remove_action (G_ACTION_MAP(app->message_actions), action_name);
406 g_action_muxer_remove (app->message_sub_actions, action_name);
338407
339 if (application_update_draws_attention(app))408 if (application_update_draws_attention(app))
340 im_application_list_update_root_action (app->list);409 im_application_list_update_root_action (app->list);
341410
342 g_signal_emit (app->list, signals[MESSAGE_REMOVED], 0, app->id, id);411 g_signal_emit (app->list, signals[MESSAGE_REMOVED], 0, app->id, action_name);
412
413 g_free (action_name);
343}414}
344415
345static void416static void
@@ -348,9 +419,11 @@
348 gpointer user_data)419 gpointer user_data)
349{420{
350 Application *app = user_data;421 Application *app = user_data;
351 const gchar *message_id;422 const gchar *action_name;
423 gchar *message_id;
352424
353 message_id = g_action_get_name (G_ACTION (action));425 action_name = g_action_get_name (G_ACTION (action));
426 message_id = unescape_action_name (action_name);
354427
355 if (g_variant_get_boolean (parameter))428 if (g_variant_get_boolean (parameter))
356 {429 {
@@ -369,7 +442,9 @@
369 app->cancellable, NULL, NULL);442 app->cancellable, NULL, NULL);
370 }443 }
371444
372 im_application_list_message_removed (app, message_id);445 im_application_list_message_removed (app, action_name);
446
447 g_free (message_id);
373}448}
374449
375static void450static void
@@ -379,11 +454,11 @@
379{454{
380 Application *app = user_data;455 Application *app = user_data;
381 const gchar *message_id;456 const gchar *message_id;
382 const gchar *action_id;457 gchar *action_id;
383 GVariantBuilder builder;458 GVariantBuilder builder;
384459
385 message_id = g_object_get_data (G_OBJECT (action), "message");460 message_id = g_object_get_data (G_OBJECT (action), "message");
386 action_id = g_action_get_name (G_ACTION (action));461 action_id = unescape_action_name (g_action_get_name (G_ACTION (action)));
387462
388 g_variant_builder_init (&builder, G_VARIANT_TYPE ("av"));463 g_variant_builder_init (&builder, G_VARIANT_TYPE ("av"));
389 if (parameter)464 if (parameter)
@@ -397,6 +472,8 @@
397 NULL, NULL);472 NULL, NULL);
398473
399 im_application_list_message_removed (app, message_id);474 im_application_list_message_removed (app, message_id);
475
476 g_free (action_id);
400}477}
401478
402static void479static void
@@ -799,6 +876,7 @@
799 GVariant *serialized_icon = NULL;876 GVariant *serialized_icon = NULL;
800 GVariant *state;877 GVariant *state;
801 GSimpleAction *action;878 GSimpleAction *action;
879 gchar *action_name;
802880
803 g_variant_get (source, "(&s&s@avux&sb)",881 g_variant_get (source, "(&s&s@avux&sb)",
804 &id, &label, &maybe_serialized_icon, &count, &time, &string, &draws_attention);882 &id, &label, &maybe_serialized_icon, &count, &time, &string, &draws_attention);
@@ -809,12 +887,13 @@
809 visible = count > 0 || time != 0 || (string != NULL && string[0] != '\0');887 visible = count > 0 || time != 0 || (string != NULL && string[0] != '\0');
810888
811 state = g_variant_new ("(uxsb)", count, time, string, draws_attention);889 state = g_variant_new ("(uxsb)", count, time, string, draws_attention);
812 action = g_simple_action_new_stateful (id, G_VARIANT_TYPE_BOOLEAN, state);890 action_name = escape_action_name (id);
891 action = g_simple_action_new_stateful (action_name, G_VARIANT_TYPE_BOOLEAN, state);
813 g_signal_connect (action, "activate", G_CALLBACK (im_application_list_source_activated), app);892 g_signal_connect (action, "activate", G_CALLBACK (im_application_list_source_activated), app);
814893
815 g_action_map_add_action (G_ACTION_MAP(app->source_actions), G_ACTION (action));894 g_action_map_add_action (G_ACTION_MAP(app->source_actions), G_ACTION (action));
816895
817 g_signal_emit (app->list, signals[SOURCE_ADDED], 0, app->id, id, label, serialized_icon, visible);896 g_signal_emit (app->list, signals[SOURCE_ADDED], 0, app->id, action_name, label, serialized_icon, visible);
818897
819 if (visible && draws_attention && app->draws_attention == FALSE)898 if (visible && draws_attention && app->draws_attention == FALSE)
820 {899 {
@@ -822,6 +901,7 @@
822 im_application_list_update_root_action (app->list);901 im_application_list_update_root_action (app->list);
823 }902 }
824903
904 g_free (action_name);
825 g_object_unref (action);905 g_object_unref (action);
826 if (serialized_icon)906 if (serialized_icon)
827 g_variant_unref (serialized_icon);907 g_variant_unref (serialized_icon);
@@ -841,6 +921,7 @@
841 gboolean draws_attention;921 gboolean draws_attention;
842 GVariant *serialized_icon = NULL;922 GVariant *serialized_icon = NULL;
843 gboolean visible;923 gboolean visible;
924 gchar *action_name;
844925
845 g_variant_get (source, "(&s&s@avux&sb)",926 g_variant_get (source, "(&s&s@avux&sb)",
846 &id, &label, &maybe_serialized_icon, &count, &time, &string, &draws_attention);927 &id, &label, &maybe_serialized_icon, &count, &time, &string, &draws_attention);
@@ -848,12 +929,14 @@
848 if (g_variant_n_children (maybe_serialized_icon) == 1)929 if (g_variant_n_children (maybe_serialized_icon) == 1)
849 g_variant_get_child (maybe_serialized_icon, 0, "v", &serialized_icon);930 g_variant_get_child (maybe_serialized_icon, 0, "v", &serialized_icon);
850931
851 g_action_group_change_action_state (G_ACTION_GROUP (app->source_actions), id,932 action_name = escape_action_name (id);
933
934 g_action_group_change_action_state (G_ACTION_GROUP (app->source_actions), action_name,
852 g_variant_new ("(uxsb)", count, time, string, draws_attention));935 g_variant_new ("(uxsb)", count, time, string, draws_attention));
853936
854 visible = count > 0 || time != 0 || (string != NULL && string[0] != '\0');937 visible = count > 0 || time != 0 || (string != NULL && string[0] != '\0');
855938
856 g_signal_emit (app->list, signals[SOURCE_CHANGED], 0, app->id, id, label, serialized_icon, visible);939 g_signal_emit (app->list, signals[SOURCE_CHANGED], 0, app->id, action_name, label, serialized_icon, visible);
857940
858 if (application_update_draws_attention (app))941 if (application_update_draws_attention (app))
859 im_application_list_update_root_action (app->list);942 im_application_list_update_root_action (app->list);
@@ -861,6 +944,7 @@
861 if (serialized_icon)944 if (serialized_icon)
862 g_variant_unref (serialized_icon);945 g_variant_unref (serialized_icon);
863 g_variant_unref (maybe_serialized_icon);946 g_variant_unref (maybe_serialized_icon);
947 g_free (action_name);
864}948}
865949
866static void950static void
@@ -965,6 +1049,7 @@
965 GSimpleAction *action;1049 GSimpleAction *action;
966 GIcon *app_icon;1050 GIcon *app_icon;
967 GVariant *actions = NULL;1051 GVariant *actions = NULL;
1052 gchar *action_name;
9681053
969 g_variant_get (message, "(&s@av&s&s&sxaa{sv}b)",1054 g_variant_get (message, "(&s@av&s&s&sxaa{sv}b)",
970 &id, &maybe_serialized_icon, &title, &subtitle, &body, &time, &action_iter, &draws_attention);1055 &id, &maybe_serialized_icon, &title, &subtitle, &body, &time, &action_iter, &draws_attention);
@@ -972,7 +1057,8 @@
972 if (g_variant_n_children (maybe_serialized_icon) == 1)1057 if (g_variant_n_children (maybe_serialized_icon) == 1)
973 g_variant_get_child (maybe_serialized_icon, 0, "v", &serialized_icon);1058 g_variant_get_child (maybe_serialized_icon, 0, "v", &serialized_icon);
9741059
975 action = g_simple_action_new (id, G_VARIANT_TYPE_BOOLEAN);1060 action_name = escape_action_name (id);
1061 action = g_simple_action_new (action_name, G_VARIANT_TYPE_BOOLEAN);
976 g_object_set_qdata(G_OBJECT(action), message_action_draws_attention_quark(), GINT_TO_POINTER(draws_attention));1062 g_object_set_qdata(G_OBJECT(action), message_action_draws_attention_quark(), GINT_TO_POINTER(draws_attention));
977 g_signal_connect (action, "activate", G_CALLBACK (im_application_list_message_activated), app);1063 g_signal_connect (action, "activate", G_CALLBACK (im_application_list_message_activated), app);
978 g_action_map_add_action (G_ACTION_MAP(app->message_actions), G_ACTION (action));1064 g_action_map_add_action (G_ACTION_MAP(app->message_actions), G_ACTION (action));
@@ -994,6 +1080,7 @@
994 GVariant *hint;1080 GVariant *hint;
995 GVariantBuilder dict_builder;1081 GVariantBuilder dict_builder;
996 gchar *prefixed_name;1082 gchar *prefixed_name;
1083 gchar *escaped_name;
9971084
998 if (!g_variant_lookup (entry, "name", "&s", &name))1085 if (!g_variant_lookup (entry, "name", "&s", &name))
999 {1086 {
@@ -1005,14 +1092,15 @@
1005 g_variant_lookup (entry, "parameter-type", "&g", &type);1092 g_variant_lookup (entry, "parameter-type", "&g", &type);
1006 hint = g_variant_lookup_value (entry, "parameter-hint", NULL);1093 hint = g_variant_lookup_value (entry, "parameter-hint", NULL);
10071094
1008 action = g_simple_action_new (name, type ? G_VARIANT_TYPE (type) : NULL);1095 escaped_name = escape_action_name (name);
1096 action = g_simple_action_new (escaped_name, type ? G_VARIANT_TYPE (type) : NULL);
1009 g_object_set_data_full (G_OBJECT (action), "message", g_strdup (id), g_free);1097 g_object_set_data_full (G_OBJECT (action), "message", g_strdup (id), g_free);
1010 g_signal_connect (action, "activate", G_CALLBACK (im_application_list_sub_message_activated), app);1098 g_signal_connect (action, "activate", G_CALLBACK (im_application_list_sub_message_activated), app);
1011 g_action_map_add_action (G_ACTION_MAP(action_group), G_ACTION (action));1099 g_action_map_add_action (G_ACTION_MAP(action_group), G_ACTION (action));
10121100
1013 g_variant_builder_init (&dict_builder, G_VARIANT_TYPE ("a{sv}"));1101 g_variant_builder_init (&dict_builder, G_VARIANT_TYPE ("a{sv}"));
10141102
1015 prefixed_name = g_strjoin (".", app->id, "msg-actions", id, name, NULL);1103 prefixed_name = g_strjoin (".", app->id, "msg-actions", escaped_name, escaped_name, NULL);
1016 g_variant_builder_add (&dict_builder, "{sv}", "name", g_variant_new_string (prefixed_name));1104 g_variant_builder_add (&dict_builder, "{sv}", "name", g_variant_new_string (prefixed_name));
10171105
1018 if (label)1106 if (label)
@@ -1035,9 +1123,10 @@
1035 g_object_unref (action);1123 g_object_unref (action);
1036 g_variant_unref (entry);1124 g_variant_unref (entry);
1037 g_free (prefixed_name);1125 g_free (prefixed_name);
1126 g_free (escaped_name);
1038 }1127 }
10391128
1040 g_action_muxer_insert (app->message_sub_actions, id, G_ACTION_GROUP (action_group));1129 g_action_muxer_insert (app->message_sub_actions, action_name, G_ACTION_GROUP (action_group));
1041 actions = g_variant_builder_end (&actions_builder);1130 actions = g_variant_builder_end (&actions_builder);
10421131
1043 g_object_unref (action_group);1132 g_object_unref (action_group);
@@ -1052,9 +1141,10 @@
1052 app_icon = get_symbolic_app_icon (app->info);1141 app_icon = get_symbolic_app_icon (app->info);
10531142
1054 g_signal_emit (app->list, signals[MESSAGE_ADDED], 0,1143 g_signal_emit (app->list, signals[MESSAGE_ADDED], 0,
1055 app->id, app_icon, id, serialized_icon, title,1144 app->id, app_icon, action_name, serialized_icon, title,
1056 subtitle, body, actions, time, draws_attention);1145 subtitle, body, actions, time, draws_attention);
10571146
1147 g_free (action_name);
1058 g_variant_iter_free (action_iter);1148 g_variant_iter_free (action_iter);
1059 g_object_unref (action);1149 g_object_unref (action);
1060 if (serialized_icon)1150 if (serialized_icon)

Subscribers

People subscribed via source and target branches