24
24
#include "../SDL_tray_utils.h"
25
25
26
26
#include <dlfcn.h>
27
+ #include <errno.h>
27
28
28
29
/* getpid() */
29
30
#include <unistd.h>
@@ -55,6 +56,7 @@ typedef enum
55
56
} GConnectFlags ;
56
57
gulong (* g_signal_connect_data )(gpointer instance , const gchar * detailed_signal , GCallback c_handler , gpointer data , GClosureNotify destroy_data , GConnectFlags connect_flags );
57
58
void (* g_object_unref )(gpointer object );
59
+ gchar * (* g_mkdtemp )(gchar * template );
58
60
59
61
#define g_signal_connect (instance , detailed_signal , c_handler , data ) \
60
62
g_signal_connect_data ((instance), (detailed_signal), (c_handler), (data), NULL, (GConnectFlags) 0)
@@ -248,6 +250,9 @@ static bool init_gtk(void)
248
250
gtk_check_menu_item_get_active = dlsym (libgtk , "gtk_check_menu_item_get_active" );
249
251
gtk_widget_get_sensitive = dlsym (libgtk , "gtk_widget_get_sensitive" );
250
252
253
+ /* Technically these are GLib or GObject functions, but we can find
254
+ * them via GDK */
255
+ g_mkdtemp = dlsym (libgdk , "g_mkdtemp" );
251
256
g_signal_connect_data = dlsym (libgdk , "g_signal_connect_data" );
252
257
g_object_unref = dlsym (libgdk , "g_object_unref" );
253
258
@@ -270,6 +275,7 @@ static bool init_gtk(void)
270
275
!gtk_menu_shell_append ||
271
276
!gtk_menu_shell_insert ||
272
277
!gtk_widget_destroy ||
278
+ !g_mkdtemp ||
273
279
!g_signal_connect_data ||
274
280
!g_object_unref ||
275
281
!app_indicator_new ||
@@ -319,9 +325,12 @@ struct SDL_TrayEntry {
319
325
SDL_TrayMenu * submenu ;
320
326
};
321
327
328
+ #define ICON_DIR_TEMPLATE "/tmp/SDL-tray-XXXXXX"
329
+
322
330
struct SDL_Tray {
323
331
AppIndicator * indicator ;
324
332
SDL_TrayMenu * menu ;
333
+ char icon_dir [sizeof (ICON_DIR_TEMPLATE )];
325
334
char icon_path [256 ];
326
335
};
327
336
@@ -343,19 +352,19 @@ static void call_callback(GtkMenuItem *item, gpointer ptr)
343
352
}
344
353
}
345
354
346
- /* Since AppIndicator deals only in filenames, which are inherently subject to
347
- timing attacks, don't bother generating a secure filename. */
348
- static bool get_tmp_filename (char * buffer , size_t size )
355
+ static bool new_tmp_filename (SDL_Tray * tray )
349
356
{
350
357
static int count = 0 ;
351
358
352
- if (size < 64 ) {
353
- return SDL_SetError ("Can't create temporary file for icon: size %u < 64" , (unsigned int )size );
354
- }
359
+ int would_have_written = SDL_snprintf (tray -> icon_path , sizeof (tray -> icon_path ), "%s/%d.bmp" , tray -> icon_dir , count ++ );
355
360
356
- int would_have_written = SDL_snprintf (buffer , size , "/tmp/sdl_appindicator_icon_%d_%d.bmp" , getpid (), count ++ );
361
+ if (would_have_written > 0 && ((unsigned ) would_have_written ) < sizeof (tray -> icon_path ) - 1 ) {
362
+ return true;
363
+ }
357
364
358
- return would_have_written > 0 && would_have_written < size - 1 ;
365
+ tray -> icon_path [0 ] = '\0' ;
366
+ SDL_SetError ("Failed to format new temporary filename" );
367
+ return false;
359
368
}
360
369
361
370
static const char * get_appindicator_id (void )
@@ -402,8 +411,16 @@ SDL_Tray *SDL_CreateTray(SDL_Surface *icon, const char *tooltip)
402
411
}
403
412
404
413
SDL_memset ((void * ) tray , 0 , sizeof (* tray ));
414
+ SDL_strlcpy (tray -> icon_dir , ICON_DIR_TEMPLATE , sizeof (tray -> icon_dir ));
415
+ if (!g_mkdtemp (tray -> icon_dir )) {
416
+ SDL_SetError ("Cannot create directory for tray icon: %s" , strerror (errno ));
417
+ return NULL ;
418
+ }
419
+
420
+ if (!new_tmp_filename (tray )) {
421
+ return NULL ;
422
+ }
405
423
406
- get_tmp_filename (tray -> icon_path , sizeof (tray -> icon_path ));
407
424
SDL_SaveBMP (icon , tray -> icon_path );
408
425
409
426
tray -> indicator = app_indicator_new (get_appindicator_id (), tray -> icon_path ,
@@ -424,8 +441,7 @@ void SDL_SetTrayIcon(SDL_Tray *tray, SDL_Surface *icon)
424
441
425
442
/* AppIndicator caches the icon files; always change filename to avoid caching */
426
443
427
- if (icon ) {
428
- get_tmp_filename (tray -> icon_path , sizeof (tray -> icon_path ));
444
+ if (icon && new_tmp_filename (tray )) {
429
445
SDL_SaveBMP (icon , tray -> icon_path );
430
446
app_indicator_set_icon (tray -> indicator , tray -> icon_path );
431
447
} else {
@@ -677,6 +693,10 @@ void SDL_DestroyTray(SDL_Tray *tray)
677
693
SDL_RemovePath (tray -> icon_path );
678
694
}
679
695
696
+ if (* tray -> icon_dir ) {
697
+ SDL_RemovePath (tray -> icon_dir );
698
+ }
699
+
680
700
if (tray -> indicator ) {
681
701
g_object_unref (tray -> indicator );
682
702
}
0 commit comments