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
1=== modified file 'src/im-application-list.c'
2--- src/im-application-list.c 2014-10-10 15:22:50 +0000
3+++ src/im-application-list.c 2014-11-07 11:43:25 +0000
4@@ -134,6 +134,62 @@
5 return retval;
6 }
7
8+static gchar *
9+escape_action_name (const gchar *name)
10+{
11+ static const gchar *xdigits = "0123456789abcdef";
12+ GString *escaped;
13+ gchar c;
14+
15+ g_return_val_if_fail (name != NULL, NULL);
16+
17+ escaped = g_string_new (NULL);
18+ while ((c = *name++))
19+ {
20+ if (g_ascii_isalnum (c) || c == '.')
21+ {
22+ g_string_append_c (escaped, c);
23+ }
24+ else
25+ {
26+ g_string_append_c (escaped, '-');
27+ g_string_append_c (escaped, xdigits[c >> 4]);
28+ g_string_append_c (escaped, xdigits[c & 0xf]);
29+ }
30+ }
31+
32+ return g_string_free (escaped, FALSE);
33+}
34+
35+static gchar *
36+unescape_action_name (const gchar *name)
37+{
38+ GString *unescaped;
39+ gint i;
40+
41+ g_return_val_if_fail (name != NULL, NULL);
42+
43+ unescaped = g_string_new (NULL);
44+ for (i = 0; name[i]; i++)
45+ {
46+ gint one, two;
47+
48+ if (name[i] == '-' &&
49+ (one = g_ascii_xdigit_value (name[i + 1])) >= 0 &&
50+ (two = g_ascii_xdigit_value (name[i + 2])) >= 0)
51+ {
52+ g_string_append_c (unescaped, (one << 4) & two);
53+ i += 2;
54+ }
55+ else
56+ {
57+ g_string_append_c (unescaped, name[i]);
58+ }
59+ }
60+
61+ return g_string_free (unescaped, FALSE);
62+}
63+
64 /* Check to see if either of our action groups has any actions, if
65 so return TRUE so we get chosen! */
66 static gboolean
67@@ -293,12 +349,17 @@
68 im_application_list_source_removed (Application *app,
69 const gchar *id)
70 {
71- g_action_map_remove_action (G_ACTION_MAP(app->source_actions), id);
72-
73- g_signal_emit (app->list, signals[SOURCE_REMOVED], 0, app->id, id);
74+ gchar *action_name;
75+
76+ action_name = escape_action_name (id);
77+
78+ g_action_map_remove_action (G_ACTION_MAP(app->source_actions), action_name);
79+ g_signal_emit (app->list, signals[SOURCE_REMOVED], 0, app->id, action_name);
80
81 if (application_update_draws_attention(app))
82 im_application_list_update_root_action (app->list);
83+
84+ g_free (action_name);
85 }
86
87 static void
88@@ -307,9 +368,11 @@
89 gpointer user_data)
90 {
91 Application *app = user_data;
92- const gchar *source_id;
93+ const gchar *action_name;
94+ gchar *source_id;
95
96- source_id = g_action_get_name (G_ACTION (action));
97+ action_name = g_action_get_name (G_ACTION (action));
98+ source_id = unescape_action_name (action_name);
99
100 if (g_variant_get_boolean (parameter))
101 {
102@@ -326,20 +389,28 @@
103 app->cancellable, NULL, NULL);
104 }
105
106- im_application_list_source_removed (app, source_id);
107+ im_application_list_source_removed (app, action_name);
108+
109+ g_free (source_id);
110 }
111
112 static void
113 im_application_list_message_removed (Application *app,
114 const gchar *id)
115 {
116- g_action_map_remove_action (G_ACTION_MAP(app->message_actions), id);
117- g_action_muxer_remove (app->message_sub_actions, id);
118+ gchar *action_name;
119+
120+ action_name = escape_action_name (id);
121+
122+ g_action_map_remove_action (G_ACTION_MAP(app->message_actions), action_name);
123+ g_action_muxer_remove (app->message_sub_actions, action_name);
124
125 if (application_update_draws_attention(app))
126 im_application_list_update_root_action (app->list);
127
128- g_signal_emit (app->list, signals[MESSAGE_REMOVED], 0, app->id, id);
129+ g_signal_emit (app->list, signals[MESSAGE_REMOVED], 0, app->id, action_name);
130+
131+ g_free (action_name);
132 }
133
134 static void
135@@ -348,9 +419,11 @@
136 gpointer user_data)
137 {
138 Application *app = user_data;
139- const gchar *message_id;
140+ const gchar *action_name;
141+ gchar *message_id;
142
143- message_id = g_action_get_name (G_ACTION (action));
144+ action_name = g_action_get_name (G_ACTION (action));
145+ message_id = unescape_action_name (action_name);
146
147 if (g_variant_get_boolean (parameter))
148 {
149@@ -369,7 +442,9 @@
150 app->cancellable, NULL, NULL);
151 }
152
153- im_application_list_message_removed (app, message_id);
154+ im_application_list_message_removed (app, action_name);
155+
156+ g_free (message_id);
157 }
158
159 static void
160@@ -379,11 +454,11 @@
161 {
162 Application *app = user_data;
163 const gchar *message_id;
164- const gchar *action_id;
165+ gchar *action_id;
166 GVariantBuilder builder;
167
168 message_id = g_object_get_data (G_OBJECT (action), "message");
169- action_id = g_action_get_name (G_ACTION (action));
170+ action_id = unescape_action_name (g_action_get_name (G_ACTION (action)));
171
172 g_variant_builder_init (&builder, G_VARIANT_TYPE ("av"));
173 if (parameter)
174@@ -397,6 +472,8 @@
175 NULL, NULL);
176
177 im_application_list_message_removed (app, message_id);
178+
179+ g_free (action_id);
180 }
181
182 static void
183@@ -799,6 +876,7 @@
184 GVariant *serialized_icon = NULL;
185 GVariant *state;
186 GSimpleAction *action;
187+ gchar *action_name;
188
189 g_variant_get (source, "(&s&s@avux&sb)",
190 &id, &label, &maybe_serialized_icon, &count, &time, &string, &draws_attention);
191@@ -809,12 +887,13 @@
192 visible = count > 0 || time != 0 || (string != NULL && string[0] != '\0');
193
194 state = g_variant_new ("(uxsb)", count, time, string, draws_attention);
195- action = g_simple_action_new_stateful (id, G_VARIANT_TYPE_BOOLEAN, state);
196+ action_name = escape_action_name (id);
197+ action = g_simple_action_new_stateful (action_name, G_VARIANT_TYPE_BOOLEAN, state);
198 g_signal_connect (action, "activate", G_CALLBACK (im_application_list_source_activated), app);
199
200 g_action_map_add_action (G_ACTION_MAP(app->source_actions), G_ACTION (action));
201
202- g_signal_emit (app->list, signals[SOURCE_ADDED], 0, app->id, id, label, serialized_icon, visible);
203+ g_signal_emit (app->list, signals[SOURCE_ADDED], 0, app->id, action_name, label, serialized_icon, visible);
204
205 if (visible && draws_attention && app->draws_attention == FALSE)
206 {
207@@ -822,6 +901,7 @@
208 im_application_list_update_root_action (app->list);
209 }
210
211+ g_free (action_name);
212 g_object_unref (action);
213 if (serialized_icon)
214 g_variant_unref (serialized_icon);
215@@ -841,6 +921,7 @@
216 gboolean draws_attention;
217 GVariant *serialized_icon = NULL;
218 gboolean visible;
219+ gchar *action_name;
220
221 g_variant_get (source, "(&s&s@avux&sb)",
222 &id, &label, &maybe_serialized_icon, &count, &time, &string, &draws_attention);
223@@ -848,12 +929,14 @@
224 if (g_variant_n_children (maybe_serialized_icon) == 1)
225 g_variant_get_child (maybe_serialized_icon, 0, "v", &serialized_icon);
226
227- g_action_group_change_action_state (G_ACTION_GROUP (app->source_actions), id,
228+ action_name = escape_action_name (id);
229+
230+ g_action_group_change_action_state (G_ACTION_GROUP (app->source_actions), action_name,
231 g_variant_new ("(uxsb)", count, time, string, draws_attention));
232
233 visible = count > 0 || time != 0 || (string != NULL && string[0] != '\0');
234
235- g_signal_emit (app->list, signals[SOURCE_CHANGED], 0, app->id, id, label, serialized_icon, visible);
236+ g_signal_emit (app->list, signals[SOURCE_CHANGED], 0, app->id, action_name, label, serialized_icon, visible);
237
238 if (application_update_draws_attention (app))
239 im_application_list_update_root_action (app->list);
240@@ -861,6 +944,7 @@
241 if (serialized_icon)
242 g_variant_unref (serialized_icon);
243 g_variant_unref (maybe_serialized_icon);
244+ g_free (action_name);
245 }
246
247 static void
248@@ -965,6 +1049,7 @@
249 GSimpleAction *action;
250 GIcon *app_icon;
251 GVariant *actions = NULL;
252+ gchar *action_name;
253
254 g_variant_get (message, "(&s@av&s&s&sxaa{sv}b)",
255 &id, &maybe_serialized_icon, &title, &subtitle, &body, &time, &action_iter, &draws_attention);
256@@ -972,7 +1057,8 @@
257 if (g_variant_n_children (maybe_serialized_icon) == 1)
258 g_variant_get_child (maybe_serialized_icon, 0, "v", &serialized_icon);
259
260- action = g_simple_action_new (id, G_VARIANT_TYPE_BOOLEAN);
261+ action_name = escape_action_name (id);
262+ action = g_simple_action_new (action_name, G_VARIANT_TYPE_BOOLEAN);
263 g_object_set_qdata(G_OBJECT(action), message_action_draws_attention_quark(), GINT_TO_POINTER(draws_attention));
264 g_signal_connect (action, "activate", G_CALLBACK (im_application_list_message_activated), app);
265 g_action_map_add_action (G_ACTION_MAP(app->message_actions), G_ACTION (action));
266@@ -994,6 +1080,7 @@
267 GVariant *hint;
268 GVariantBuilder dict_builder;
269 gchar *prefixed_name;
270+ gchar *escaped_name;
271
272 if (!g_variant_lookup (entry, "name", "&s", &name))
273 {
274@@ -1005,14 +1092,15 @@
275 g_variant_lookup (entry, "parameter-type", "&g", &type);
276 hint = g_variant_lookup_value (entry, "parameter-hint", NULL);
277
278- action = g_simple_action_new (name, type ? G_VARIANT_TYPE (type) : NULL);
279+ escaped_name = escape_action_name (name);
280+ action = g_simple_action_new (escaped_name, type ? G_VARIANT_TYPE (type) : NULL);
281 g_object_set_data_full (G_OBJECT (action), "message", g_strdup (id), g_free);
282 g_signal_connect (action, "activate", G_CALLBACK (im_application_list_sub_message_activated), app);
283 g_action_map_add_action (G_ACTION_MAP(action_group), G_ACTION (action));
284
285 g_variant_builder_init (&dict_builder, G_VARIANT_TYPE ("a{sv}"));
286
287- prefixed_name = g_strjoin (".", app->id, "msg-actions", id, name, NULL);
288+ prefixed_name = g_strjoin (".", app->id, "msg-actions", escaped_name, escaped_name, NULL);
289 g_variant_builder_add (&dict_builder, "{sv}", "name", g_variant_new_string (prefixed_name));
290
291 if (label)
292@@ -1035,9 +1123,10 @@
293 g_object_unref (action);
294 g_variant_unref (entry);
295 g_free (prefixed_name);
296+ g_free (escaped_name);
297 }
298
299- g_action_muxer_insert (app->message_sub_actions, id, G_ACTION_GROUP (action_group));
300+ g_action_muxer_insert (app->message_sub_actions, action_name, G_ACTION_GROUP (action_group));
301 actions = g_variant_builder_end (&actions_builder);
302
303 g_object_unref (action_group);
304@@ -1052,9 +1141,10 @@
305 app_icon = get_symbolic_app_icon (app->info);
306
307 g_signal_emit (app->list, signals[MESSAGE_ADDED], 0,
308- app->id, app_icon, id, serialized_icon, title,
309+ app->id, app_icon, action_name, serialized_icon, title,
310 subtitle, body, actions, time, draws_attention);
311
312+ g_free (action_name);
313 g_variant_iter_free (action_iter);
314 g_object_unref (action);
315 if (serialized_icon)

Subscribers

People subscribed via source and target branches