11
#include <glib/gstdio.h>
12
#include <libnotify/notify.h>
17
#include "update-notifier.h"
21
#include "trayappletui.h"
23
/* relative to the home dir */
24
#define HOOKS_SEEN_DEPRECATED ".update-notifier/hooks_seen"
25
/* relative to the XDG_CONFIG_HOME dir */
26
#define HOOKS_SEEN "update-notifier/hooks_seen"
28
/* used by e.g. the installer to mark stuff that's already done */
29
#define GLOBAL_HOOKS_SEEN "/etc/update-notifier/hooks_seen"
32
// the size of the md5 hash digest for the duplicated note detection
33
static const int DIGEST_SIZE=16;
36
g_debug_hooks(const char *msg, ...)
40
g_logv("hooks",G_LOG_LEVEL_DEBUG, msg, va);
44
// compare a HookFile with a filename and find the HookFile that matches
46
compare_hook_func(gconstpointer a, gconstpointer b)
48
//g_debug_hooks("compare: %s %s",(char*)(((HookFileSeen*)a)->filename),(char*)b);
52
return strcmp(((HookFile*)a)->filename, b);
55
// return the most recent mtime or ctime of the file
57
hook_file_time(const gchar *filename)
60
char *file = g_strdup_printf("%s/%s",HOOKS_DIR, filename);
61
if(g_stat(file, &buf) <0) {
62
g_warning("can't stat %s",file);
68
time_t mtime = buf.st_mtime;
69
time_t ctime = buf.st_ctime;
71
return mtime > ctime ? mtime : ctime;
75
hook_file_md5(const gchar *filename, guint8 *md5)
83
file = g_strdup_printf("%s/%s",HOOKS_DIR, filename);
86
g_warning("can't read %s",file);
90
checksum = g_checksum_new(G_CHECKSUM_MD5);
92
n = fread(buf, 1, sizeof(buf), f);
93
g_checksum_update(checksum, buf, n);
97
g_checksum_get_digest(checksum, md5, &n);
98
//g_debug_hooks("md5: %s -> '%s'", filename, md5);
101
g_checksum_free(checksum);
105
/* mark a given hook file as seen
106
(actually implemented to write out all the information we have)
109
hook_file_mark_as_seen(HookTrayAppletPrivate *priv, HookFile *hf)
111
g_debug_hooks("mark_hook_file_as_seen: %s", hf->filename);
114
guint8 md5[DIGEST_SIZE];
115
hook_file_md5(hf->filename, md5);
120
// update the time (extra paranoia, shouldn't be needed)
121
hf->mtime = hook_file_time(hf->filename);
123
// write out the list of known files
124
gchar *filename = g_strdup_printf("%s/%s",
125
g_get_user_config_dir(),
127
FILE *f = fopen(filename, "w");
129
g_warning("Something went wrong writing the user's hook file");
133
// write out all the hooks that are seen
135
// and any hooks that are not yet seen but have the same md5sum
136
// as the one just marked (avoids showing duplicated hooks effectively).
138
// For hooks with the same md5sum use the mtime of the just displayed hook
139
GList *elm = g_list_first(priv->hook_files);
140
for(;elm != NULL; elm = g_list_next(elm)) {
141
HookFile *e = (HookFile*)elm->data;
142
g_debug_hooks("will write out: %s (%s)",e->filename, e->md5);
143
if(e->seen == TRUE) {
144
g_debug_hooks("e->seen: %s %li %x", e->filename,e->mtime, (int)(e->cmd_run));
145
fprintf(f,"%s %li %x\n", e->filename, e->mtime, (int)(e->cmd_run));
146
} else if(memcmp(e->md5,md5,DIGEST_SIZE) == 0) {
148
fprintf(f,"%s %li %x\n", e->filename,hf->mtime, (int)(e->cmd_run));
149
g_debug_hooks("same md5: %s %li %x",e->filename,hf->mtime,(int)(e->cmd_run));
159
/* mark a given HookFile as run */
161
mark_hook_file_as_run(HookTrayAppletPrivate *priv, HookFile *hf)
166
g_debug_hooks("mark_hook_file_as_run: %s",hf->filename);
173
/* get the language code in a static allocated buffer
174
* short_form: only return the languagecode if true, otherwise
175
* languagecode_countrycode
178
get_lang_code(gboolean short_form)
180
/* make own private copy */
181
static gchar locale[51];
182
strncpy(locale, setlocale(LC_MESSAGES, NULL), 50);
184
// FIXME: we need to be more inteligent here
185
// _and_ we probably want to look into the "LANGUAGE" enviroment too
196
* get a i18n field of the rfc822 header
197
* Return Value: a pointer that must not be freed (part of the rfc822 struct)
200
hook_file_lookup_i18n(struct rfc822_header *rfc822, char *field)
202
gchar *s, *entry, *text;
204
/* first check for langpacks, then i18n fields */
205
entry = rfc822_header_lookup(rfc822, "GettextDomain");
207
text = rfc822_header_lookup(rfc822, field);
208
s = dgettext(entry, text);
213
/* try $field-$languagecode_$countrycode.$codeset first */
214
s = g_strdup_printf("%s-%s.%s", field, get_lang_code(FALSE), nl_langinfo(CODESET));
215
entry = rfc822_header_lookup(rfc822, s);
216
//g_debug_hooks("Looking for: %s ; found: %s",s,entry);
221
/* try $field-$languagecode_$countrycode (and assume utf-8) */
222
s = g_strdup_printf("%s-%s", field, get_lang_code(FALSE));
223
entry = rfc822_header_lookup(rfc822, s);
224
//g_debug_hooks("Looking for: %s ; found: %s",s,entry);
229
/* try $field-$languagecode.$codeset next */
230
s = g_strdup_printf("%s-%s.%s", field, get_lang_code(TRUE), nl_langinfo(CODESET));
231
//g_debug_hooks("Looking for: %s ; found: %s",s,entry);
232
entry = rfc822_header_lookup(rfc822, s);
237
/* try $field-$languagecode (and assume utf-8 codeset) */
238
s = g_strdup_printf("%s-%s", field, get_lang_code(TRUE));
239
//g_debug_hooks("Looking for: %s ; found: %s",s,entry);
240
entry = rfc822_header_lookup(rfc822, s);
245
/* now try translating it with gettext */
246
entry = rfc822_header_lookup(rfc822, field);
251
hook_description_get_summary(struct rfc822_header *rfc822)
253
char *summary = hook_file_lookup_i18n(rfc822, "Name");
258
hook_description_get_description(struct rfc822_header *rfc822)
260
char *description = hook_file_lookup_i18n(rfc822, "Description");
265
* show the given hook file
268
show_next_hook(TrayApplet *ta, GList *hooks)
270
//g_debug_hooks("show_next_hook()");
272
HookTrayAppletPrivate *priv = (HookTrayAppletPrivate *)ta->user_data;
276
char *hook_file = NULL;
278
// find the next unseen hook
279
GList *elm = g_list_first(hooks);
280
for(;elm != NULL; elm = g_list_next(elm)) {
281
hf = (HookFile*)elm->data;
282
if(hf->seen == FALSE) {
283
hook_file = hf->filename;
284
//g_debug_hooks("next_hook is: %s",hook_file);
289
if(hook_file == NULL) {
290
g_debug_hooks("no unseen hookfile found in hook list of len (%i)",
291
g_list_length(hooks));
295
/* if there's another unseen hook, show the "next" button */
296
gboolean show_next_button = FALSE;
298
for(elm = g_list_next(elm); elm != NULL; elm = g_list_next(elm)) {
299
if(((HookFile*)elm->data)->seen == FALSE) {
300
show_next_button = TRUE;
306
gtk_widget_show(priv->button_next);
308
gtk_widget_hide(priv->button_next);
310
char *filename = g_strdup_printf("%s%s",HOOKS_DIR,hook_file);
312
/* setup the message */
313
GtkTextBuffer *buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(priv->textview_hook));
314
FILE *f = fopen(filename, "r");
316
g_warning("can't open %s", filename);
320
struct rfc822_header *rfc822 = rfc822_parse_stanza(f);
322
char *cmd = rfc822_header_lookup(rfc822, "Command");
323
char *term = rfc822_header_lookup(rfc822, "Terminal");
325
term = g_strstrip(term);
326
g_object_set_data(G_OBJECT(priv->button_run),"cmd", g_strdup(cmd));
327
g_object_set_data(G_OBJECT(priv->button_run),"term", g_strdup(term));
328
g_object_set_data(G_OBJECT(priv->button_run),"hook_file", hf);
330
gtk_widget_show(priv->button_run);
332
gtk_widget_hide(priv->button_run);
334
char *title_str = hook_file_lookup_i18n(rfc822, "Title");
335
if(title_str != NULL) {
336
gchar *s = g_strdup_printf("<span weight=\"bold\" size=\"larger\">%s</span>", title_str);
337
gtk_label_set_markup(GTK_LABEL(priv->label_title), s);
340
char *summary = hook_description_get_summary(rfc822);
341
char *descr = hook_description_get_description(rfc822);
344
s = g_strdup_printf("%s\n\n%s\n",gettext(summary), gettext(descr));
345
gtk_text_buffer_set_text(buf, s, -1);
346
// set the name to bold
347
GtkTextIter start, end;
348
gtk_text_buffer_get_iter_at_offset(buf, &start, 0);
349
gtk_text_buffer_get_iter_at_offset(buf, &end, g_utf8_strlen(gettext(summary),-1));
350
gtk_text_buffer_apply_tag_by_name(buf, "bold_tag", &start, &end);
353
s = g_strdup_printf("%s\n",gettext(descr));
354
gtk_text_buffer_set_text(buf, s, -1);
357
// set button name (if needed)
358
char *b = hook_file_lookup_i18n(rfc822, "ButtonText");
360
gtk_button_set_label(GTK_BUTTON (priv->button_run), b);
362
gtk_button_set_label(GTK_BUTTON (priv->button_run), _("_Run this action now"));
368
rfc822_header_free_all(rfc822);
370
/* mark the current hook file as seen */
371
g_object_set_data(G_OBJECT(priv->button_next), "HookFile", hf);
377
void on_button_run_clicked(GtkWidget *self, gpointer *data)
379
//g_debug_hooks("cb_button_run()");
382
TrayApplet *ta = (TrayApplet *)data;
383
HookTrayAppletPrivate *priv = (HookTrayAppletPrivate *)ta->user_data;
385
/* mark the current hook file as run */
386
HookFile *hf = g_object_get_data(G_OBJECT(self), "hook_file");
387
mark_hook_file_as_run(priv, hf);
389
gchar *cmd = g_object_get_data(G_OBJECT(self), "cmd");
390
gchar *term = g_object_get_data(G_OBJECT(self), "term");
393
g_warning("cmd is NULL");
397
if(term != NULL && !g_ascii_strncasecmp(term, "true",-1)) {
398
cmdline = g_strdup_printf("x-terminal-emulator -e %s",cmd);
400
cmdline = g_strdup(cmd);
402
g_spawn_command_line_async(cmdline, NULL);
406
void on_button_next_clicked(GtkWidget *self, gpointer *data)
408
g_debug_hooks("cb_button_next()");
409
TrayApplet *ta = (TrayApplet *)data;
410
HookTrayAppletPrivate *priv = (HookTrayAppletPrivate *)ta->user_data;
413
hf = (HookFile*)g_object_get_data(G_OBJECT(self),"HookFile");
415
g_warning("button_next called without HookFile");
420
hook_file_mark_as_seen(priv, hf);
422
if(priv->hook_files != NULL)
423
show_next_hook(ta, priv->hook_files);
427
on_insert_text(GtkTextBuffer *buffer,
428
GtkTextIter *iter_end,
433
GtkTextIter iter, match_start, match_end, match_tmp;
435
// get where we start
436
gtk_text_buffer_get_iter_at_offset(buffer, &iter,
437
gtk_text_iter_get_offset(iter_end) - g_utf8_strlen(text,-1));
438
// search for http:// uris
439
while(gtk_text_iter_forward_search(&iter,
440
"http://", GTK_TEXT_SEARCH_VISIBLE_ONLY,
441
&match_start, &match_end, iter_end)) {
442
match_tmp = match_end;
443
// we found a uri, iterate it until the end is found
444
while(gtk_text_iter_forward_char(&match_tmp)) {
445
gchar *s = gtk_text_iter_get_text(&match_end,&match_tmp);
448
char c = s[strlen(s)-1];
449
if(c == ' ' || c == ')' || c == ']' || c == '\n' || c == '\t' || c == '>')
451
match_end = match_tmp;
453
gchar *url = gtk_text_iter_get_text(&match_start, &match_end);
454
//g_print("url: '%s'\n",url);
456
tag = gtk_text_buffer_create_tag(buffer, NULL,
458
"underline", PANGO_UNDERLINE_SINGLE,
460
g_object_set_data(G_OBJECT(tag), "url", url);
461
gtk_text_buffer_apply_tag(buffer, tag, &match_start, &match_end);
467
on_event_after(GtkWidget *widget,
468
GdkEventButton *event,
471
if(event->type != GDK_BUTTON_RELEASE)
473
if(event->button != 1)
476
gtk_text_view_window_to_buffer_coords(GTK_TEXT_VIEW(widget),
477
GTK_TEXT_WINDOW_WIDGET,
481
gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(widget), &iter, x, y);
482
GSList *tags = gtk_text_iter_get_tags(&iter);
483
for( ; tags != NULL ; tags = tags->next) {
484
gchar *url = g_object_get_data(G_OBJECT(tags->data), "url");
486
//g_print("click: '%s'\n",url);
487
char *argv[] = { "/usr/bin/gnome-open", url, NULL };
488
g_spawn_async(NULL, argv, NULL, 0, NULL, NULL, NULL, NULL);
495
show_hooks(TrayApplet *ta, gboolean focus_on_map)
497
HookTrayAppletPrivate *priv = (HookTrayAppletPrivate *)ta->user_data;
499
GError *error = NULL;
501
g_debug_hooks("show_hooks()");
503
builder = gtk_builder_new ();
506
if (!gtk_builder_add_from_file (builder, UIDIR"hooks-dialog.ui", &error)) {
507
g_warning ("Couldn't load builder file: %s", error->message);
508
g_error_free (error);
511
gtk_builder_connect_signals (builder, (gpointer)ta);
513
priv->dialog_hooks = GTK_WIDGET (gtk_builder_get_object (builder, "dialog_hooks"));
514
gtk_window_set_title (GTK_WINDOW (priv->dialog_hooks), _("Information available"));
515
assert (priv->dialog_hooks);
516
priv->label_title = GTK_WIDGET (gtk_builder_get_object (builder, "label_title"));
517
assert (priv->label_title);
518
priv->textview_hook = GTK_WIDGET (gtk_builder_get_object (builder, "textview_hook"));
519
assert (priv->textview_hook);
520
priv->button_run = GTK_WIDGET (gtk_builder_get_object (builder, "button_run"));
521
assert (priv->button_run);
522
priv->button_next = GTK_WIDGET (gtk_builder_get_object (builder, "button_next"));
523
assert (priv->button_next);
525
g_object_unref (G_OBJECT (builder));
528
GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->textview_hook));
529
gtk_text_buffer_create_tag (buf, "bold_tag",
530
"scale", PANGO_SCALE_LARGE,
531
"weight", PANGO_WEIGHT_BOLD,
533
g_signal_connect_after (G_OBJECT (buf), "insert-text",
534
G_CALLBACK (on_insert_text), NULL);
535
g_signal_connect_after (G_OBJECT (priv->textview_hook), "event-after",
536
G_CALLBACK (on_event_after), NULL);
538
gtk_window_set_focus_on_map (GTK_WINDOW (priv->dialog_hooks), focus_on_map);
540
// if show_next_hook() fails for some reason don't do anything
541
if(!show_next_hook(ta, priv->hook_files))
544
int res = gtk_dialog_run (GTK_DIALOG (priv->dialog_hooks));
545
if(res == GTK_RESPONSE_CLOSE) {
546
// mark the currently current hookfile as seen
548
hf = (HookFile*)g_object_get_data (G_OBJECT (priv->button_next), "HookFile");
550
g_warning("show_hooks called without HookFile");
555
hook_file_mark_as_seen(priv, hf);
556
check_update_hooks(ta);
560
g_clear_pointer (&priv->dialog_hooks, gtk_widget_destroy);
561
priv->label_title = NULL;
562
priv->textview_hook = NULL;
563
priv->button_run = NULL;
564
priv->button_next = NULL;
568
button_release_cb (GtkWidget *widget,
571
HookTrayAppletPrivate *priv = (HookTrayAppletPrivate*)ta->user_data;
573
if(priv->active_notification != NULL) {
574
notify_notification_close(priv->active_notification, NULL);
575
g_clear_object(&priv->active_notification);
578
//g_debug_hooks("left click on hook applet");
579
show_hooks(ta, TRUE);
584
is_hook_relevant(const gchar *hook_file)
586
g_debug_hooks("is_hook_relevant(): %s", hook_file);
589
char *filename = g_strdup_printf("%s%s",HOOKS_DIR,hook_file);
590
FILE *f = fopen(filename, "r");
592
// can't open, can't be relevant
595
struct rfc822_header *rfc822 = rfc822_parse_stanza(f);
597
// check if its a note that is relevant only for admin users
598
// (this is the default)
599
gchar *b = rfc822_header_lookup(rfc822, "OnlyAdminUsers");
600
if(b == NULL || g_ascii_strncasecmp(b, "true",-1) == 0) {
601
if (!in_admin_group())
605
// check the DontShowAfterReboot flag
606
b = rfc822_header_lookup(rfc822, "DontShowAfterReboot");
607
if(b != NULL && g_ascii_strncasecmp(b, "true",-1) == 0) {
608
g_debug_hooks("found DontShowAfterReboot");
610
// read the uptime information
611
double uptime=0, idle=0;
613
int fd = open("/proc/uptime", 0);
614
int local_n = read(fd, buf, sizeof(buf)-1);
616
char *savelocale = setlocale(LC_NUMERIC, NULL);
617
setlocale(LC_NUMERIC,"C");
618
sscanf(buf, "%lf %lf", &uptime,&idle);
620
setlocale(LC_NUMERIC,savelocale);
622
time_t mtime = hook_file_time(hook_file);
623
time_t now = time(NULL);
625
g_debug_hooks("now: %li mtime: %li uptime: %f",now,mtime,uptime);
626
g_debug_hooks("diff: %li uptime: %f",now-mtime,uptime);
627
if((int)uptime > 0 && (now - mtime) > (int)uptime) {
628
g_debug_hooks("not relevant because of reboot: %s",hook_file);
631
g_debug_hooks("hook is relevant");
635
// check for DisplayIf test
636
b = rfc822_header_lookup(rfc822, "DisplayIf");
638
g_debug_hooks("found DisplayIf command: '%s'", b);
639
int exitc = system(b);
640
g_debug_hooks("'%s' returned: %i", b, exitc);
645
rfc822_header_free_all(rfc822);
649
static gboolean show_notification(void *data)
651
TrayApplet *ta = (TrayApplet*)data;
652
HookTrayAppletPrivate *priv = (HookTrayAppletPrivate*)ta->user_data;
654
if(!tray_applet_ui_get_visible(ta))
657
if((priv->dialog_hooks && gtk_widget_get_visible(priv->dialog_hooks)) ||
658
priv->active_notification != NULL)
661
NotifyNotification *n;
663
n = notify_notification_new(
664
_("Information available"),
665
_("Click on the notification icon"
666
" to show the available information.\n"),
669
pix = gtk_icon_theme_load_icon(gtk_icon_theme_get_default(),
670
GTK_STOCK_DIALOG_INFO, 48,0,NULL);
671
notify_notification_set_icon_from_pixbuf (n, pix);
673
notify_notification_set_timeout (n, 60*1000);
674
notify_notification_show(n, NULL);
675
if (priv->active_notification)
676
g_object_unref(priv->active_notification);
677
priv->active_notification = n;
682
gboolean check_update_hooks(TrayApplet *ta)
687
const gchar *hook_file;
689
g_debug_hooks("check_update_hooks()");
690
HookTrayAppletPrivate *priv = (HookTrayAppletPrivate*)ta->user_data;
692
dir=g_dir_open(HOOKS_DIR, 0, NULL);
694
g_warning("can't read %s directory",HOOKS_DIR);
698
g_debug_hooks("reading '%s' dir", HOOKS_DIR);
699
int unseen_count = 0;
700
while((hook_file=g_dir_read_name(dir)) != NULL) {
701
g_debug_hooks("investigating file '%s'", hook_file);
703
// check if the hook still applies (for e.g. DontShowAfterReboot)
704
if(!is_hook_relevant(hook_file)) {
705
g_debug_hooks("not relevant: '%s'",hook_file);
708
// see if we already know about this hook filename
709
elm = g_list_find_custom(priv->hook_files,hook_file,
712
// not seen before, add to the list
714
g_debug_hooks("never seen before: %s",hook_file);
715
HookFile *t = g_new0(HookFile, 1);
716
t->filename = strdup(hook_file);
717
t->mtime = hook_file_time(hook_file);
718
hook_file_md5(hook_file, t->md5);
721
priv->hook_files = g_list_append(priv->hook_files, (gpointer)t);
722
// init elm with the just added record (will be needed below)
723
elm = g_list_find_custom(priv->hook_files,hook_file,
728
// this is the hook file information we have (either because it was
729
// availabe already or because we added it)
730
hf = (HookFile*)elm->data;
732
// file has changed since we last saw it
733
time_t new_mtime = hook_file_time(hook_file);
734
if(new_mtime > hf->mtime) {
735
g_debug_hooks("newer mtime: %s (%li > %li))",hook_file, new_mtime, hf->mtime);
739
// we have not seen it yet (because e.g. it was just added)
740
if(hf->seen == FALSE) {
741
g_debug_hooks("the file '%s' was NOT SEEN yet",hook_file);
743
// update mtime (because we haven't seen the old one and there
745
hf->mtime = new_mtime;
747
// check if there is already another notification that is
751
// if so, we don't increase the unseen count as all identical
752
// ones will maked as unseen at onces
753
gboolean md5match = FALSE;
754
GList *x = g_list_first(priv->hook_files);
756
HookFile *e = (HookFile*)x->data;
758
(e->seen == FALSE) &&
759
(memcmp(hf->md5,e->md5,DIGEST_SIZE)==0) )
761
g_debug_hooks("%s (%s) was seen also in %s (%s)",
762
hf->filename, hf->md5, e->filename, e->md5);
768
g_debug_hooks("%s increases unseen_count",hf->filename);
772
g_debug_hooks("already seen: '%s'",hook_file);
776
//g_debug_hooks("hooks: %i (new: %i)", g_list_length(hook_files), unseen_count);
778
if (unseen_count > 0) {
779
// we only do a dialog
780
g_debug_hooks("showing hooks with focus on map == FALSE");
781
show_hooks(ta, FALSE);
784
tray_applet_ui_destroy (ta);
790
hook_read_seen_file(HookTrayAppletPrivate *priv, const char* filename)
795
FILE *f = fopen(filename, "r");
799
g_debug_hooks("reading hook_file: %s ", filename);
801
while(fscanf(f, "%s %i %i",buf,&time,&was_run) == 3) {
803
// first check if the file actually exists, if not skip it
804
// (may already be delete when e.g. a package was removed)
805
char *filename = g_strdup_printf("%s%s",HOOKS_DIR,buf);
806
gboolean res = g_file_test(filename, G_FILE_TEST_EXISTS);
811
// now check if we already have that filename in the list
812
GList *elm = g_list_find_custom(priv->hook_files,buf,
815
g_debug_hooks("hookfile: %s already in the list", buf);
817
// we have that file already in the list with a newer mtime,
818
// than the file in the config file. ignore the config file
819
HookFile *exisiting = (HookFile *)elm->data;
820
// and it's more current
821
if(exisiting->mtime > time) {
822
g_debug_hooks("existing is newer, ignoring the read one");
826
// we have it in the list, but the the file in the list is older
827
// than the one in the config file. use this config-file instead
828
// and update the values in the list
829
exisiting->cmd_run = was_run;
830
exisiting->seen = TRUE;
831
exisiting->mtime = time;
832
hook_file_md5(exisiting->filename,exisiting->md5);
835
// not in the list yet
836
// add the just read hook file to the list
837
g_debug_hooks("got: %s %i %i ",buf,time,was_run);
838
t = g_new0(HookFile, 1);
839
t->filename = strdup(buf);
841
t->cmd_run = was_run;
843
hook_file_md5(t->filename,t->md5);
845
priv->hook_files = g_list_append(priv->hook_files, (gpointer)t);
852
init_already_seen_hooks(TrayApplet *ta)
854
g_debug_hooks("init_already_seen_hooks");
856
HookTrayAppletPrivate* priv = (HookTrayAppletPrivate*)ta->user_data;
857
char *filename, *old_filename;
859
// init with default value
860
priv->hook_files = NULL;
862
// read global hook file
863
hook_read_seen_file(priv, GLOBAL_HOOKS_SEEN);
865
filename = g_strdup_printf("%s/%s",
866
g_get_user_config_dir(),
868
// compat with the previous version
869
old_filename = g_strdup_printf("%s/%s",
871
HOOKS_SEEN_DEPRECATED);
872
if (g_file_test(old_filename, G_FILE_TEST_IS_REGULAR)) {
873
g_rename(old_filename, filename);
875
// read user hook file
876
hook_read_seen_file(priv,filename);
878
g_free(old_filename);
883
void hook_tray_icon_init(TrayApplet *ta)
885
HookTrayAppletPrivate *priv = g_new0(HookTrayAppletPrivate, 1);
886
ta->user_data = priv;
888
/* read already seen hooks */
889
init_already_seen_hooks(ta);
891
/* Check for hooks */
892
check_update_hooks(ta);