~ubuntu-core-dev/update-notifier/ubuntu

78 by mvo
* src/*.c: added #include "config.h" (/me <- stupid for forgeting it)
1
#ifdef HAVE_CONFIG_H
2
#include "config.h"
3
#endif
4
340 by Michael Vogt
* code cleanups
5
#include <fcntl.h>
476 by Michael Vogt
fix -Wall errors
6
#include <unistd.h>
7
#include <stdlib.h>
8
143 by mvo
* various include fixes
9
#include <glib.h>
10
#include <gtk/gtk.h>
11
#include <glib/gstdio.h>
210 by Michael Vogt
* added a notification on hooks
12
#include <libnotify/notify.h>
143 by mvo
* various include fixes
13
14
#include <locale.h>
390 by Michael Vogt
* src/hooks.c:
15
#include <langinfo.h>
143 by mvo
* various include fixes
16
17
#include "update-notifier.h"
45 by mvo
* added basic "interactive-update-hooks" support
18
#include "hooks.h"
19
#include "rfc822.h"
20
#include "assert.h"
21
210 by Michael Vogt
* added a notification on hooks
22
45 by mvo
* added basic "interactive-update-hooks" support
23
/* relative to the home dir */
591 by Michael Vogt
apply xdg patches by Sebastian Geiger, many thanks
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"
168 by mvo
* src/hooks.c:
27
28
/* used by e.g. the installer to mark stuff that's already done */
128 by mvo
* debian/dirs:
29
#define GLOBAL_HOOKS_SEEN "/etc/update-notifier/hooks_seen"
125 by mvo
* src/hooks.c:
30
143 by mvo
* various include fixes
31
400 by Michael Vogt
* src/hooks.c:
32
// the size of the md5 hash digest for the duplicated note detection
33
static const int DIGEST_SIZE=16;
34
452 by Michael Vogt
rework the debug options and support --debug-inotify,
35
static inline void
36
g_debug_hooks(const char *msg, ...)
125 by mvo
* src/hooks.c:
37
{
452 by Michael Vogt
rework the debug options and support --debug-inotify,
38
   va_list va;
454 by Michael Vogt
fix crash in --debug mode (LP: #348883)
39
   va_start(va, msg);
40
   g_logv("hooks",G_LOG_LEVEL_DEBUG, msg, va);
41
   va_end(va);
125 by mvo
* src/hooks.c:
42
}
43
45 by mvo
* added basic "interactive-update-hooks" support
44
void hooks_trayicon_update_tooltip (TrayApplet *un, int num_hooks)
45
{
452 by Michael Vogt
rework the debug options and support --debug-inotify,
46
   g_debug_hooks("update_tooltip: %p ", un);
45 by mvo
* added basic "interactive-update-hooks" support
47
   gchar *updates;
48
317 by Michael Vogt
* implemented new "Title" key in the UpgradeHooks file
49
   updates = _("Information available");
45 by mvo
* added basic "interactive-update-hooks" support
50
329 by Michael Vogt
* use GtkStatusIcon instead of EggTrayIcon, that makes
51
   gtk_status_icon_set_tooltip(un->tray_icon, updates);
45 by mvo
* added basic "interactive-update-hooks" support
52
}
53
124 by mvo
* src/hooks.{c,h}:
54
125 by mvo
* src/hooks.c:
55
// compare a HookFile with a filename and find the HookFile that matches
45 by mvo
* added basic "interactive-update-hooks" support
56
gint compare_hook_func(gconstpointer a, gconstpointer b)
57
{
452 by Michael Vogt
rework the debug options and support --debug-inotify,
58
   //g_debug_hooks("compare: %s %s\n",(char*)(((HookFileSeen*)a)->filename),(char*)b);
161 by mvo
* src/hooks.c:
59
   g_assert(a);
60
   g_assert(b);
61
124 by mvo
* src/hooks.{c,h}:
62
   return strcmp(((HookFile*)a)->filename, b);
45 by mvo
* added basic "interactive-update-hooks" support
63
}
64
164 by mvo
* src/hooks.c:
65
// return the most recent mtime or ctime of the file
66
time_t hook_file_time(const gchar *filename)
45 by mvo
* added basic "interactive-update-hooks" support
67
{
124 by mvo
* src/hooks.{c,h}:
68
   struct stat buf;
69
   char *file = g_strdup_printf("%s/%s",HOOKS_DIR, filename);
70
   if(g_stat(file, &buf) <0) {
191 by mvo
* move a bunch of g_error -> g_warning
71
      g_warning("can't stat %s\n",file);
144 by mvo
* debian/control:
72
      g_free(file);
124 by mvo
* src/hooks.{c,h}:
73
      return 0;
74
   }
75
   g_free(file);
164 by mvo
* src/hooks.c:
76
77
   time_t mtime = buf.st_mtime;
78
   time_t ctime = buf.st_ctime;
79
80
   return mtime > ctime ? mtime : ctime;
45 by mvo
* added basic "interactive-update-hooks" support
81
}
82
476 by Michael Vogt
fix -Wall errors
83
gboolean hook_file_md5(const gchar *filename, guint8 *md5)
144 by mvo
* debian/control:
84
{
380.1.2 by Bruce Cowan
Removed custom MD5 code, make use of GChecksum, code a bit odd though.
85
   guchar buf[512];
144 by mvo
* debian/control:
86
   FILE *f;
87
   char *file;
476 by Michael Vogt
fix -Wall errors
88
   gsize n;
380.1.2 by Bruce Cowan
Removed custom MD5 code, make use of GChecksum, code a bit odd though.
89
   GChecksum *checksum;
144 by mvo
* debian/control:
90
91
   file = g_strdup_printf("%s/%s",HOOKS_DIR, filename);
92
   f = fopen(file,"r");
162 by mvo
* src/hooks.c:
93
   if(f == NULL) {
94
      g_warning("can't read %s\n",file);
144 by mvo
* debian/control:
95
      g_free(file);
96
      return FALSE;
97
   }
380.1.2 by Bruce Cowan
Removed custom MD5 code, make use of GChecksum, code a bit odd though.
98
   checksum = g_checksum_new(G_CHECKSUM_MD5);
144 by mvo
* debian/control:
99
   do {
380.1.2 by Bruce Cowan
Removed custom MD5 code, make use of GChecksum, code a bit odd though.
100
      n = fread(buf, 1, sizeof(buf), f);
101
      g_checksum_update(checksum, buf, n);
144 by mvo
* debian/control:
102
   } while(n > 0);
400 by Michael Vogt
* src/hooks.c:
103
   
104
   n=DIGEST_SIZE;
105
   g_checksum_get_digest(checksum, md5, &n);
452 by Michael Vogt
rework the debug options and support --debug-inotify,
106
   //g_debug_hooks("md5: %s -> '%s' ", filename, md5);
144 by mvo
* debian/control:
107
108
   g_free(file);
380.1.2 by Bruce Cowan
Removed custom MD5 code, make use of GChecksum, code a bit odd though.
109
   g_checksum_free(checksum);
144 by mvo
* debian/control:
110
   return TRUE;
111
}
112
125 by mvo
* src/hooks.c:
113
/* mark a given hook file as seen 
114
  (actually implemented to write out all the information we have)
115
*/
210 by Michael Vogt
* added a notification on hooks
116
gboolean hook_file_mark_as_seen(HookTrayAppletPrivate *priv, 
124 by mvo
* src/hooks.{c,h}:
117
				HookFile *hf)
45 by mvo
* added basic "interactive-update-hooks" support
118
{
452 by Michael Vogt
rework the debug options and support --debug-inotify,
119
   g_debug_hooks("mark_hook_file_as_seen: %s", hf->filename);
124 by mvo
* src/hooks.{c,h}:
120
144 by mvo
* debian/control:
121
   // copy the md5
476 by Michael Vogt
fix -Wall errors
122
   guint8 md5[DIGEST_SIZE];
208 by Michael Vogt
* -Wall clean now
123
   hook_file_md5(hf->filename, md5);
144 by mvo
* debian/control:
124
124 by mvo
* src/hooks.{c,h}:
125
   // mark as seen 
126
   hf->seen = TRUE;
127
167 by mvo
* src/hooks.c:
128
   // update the time (extra paranoia, shouldn't be needed)
129
   hf->mtime = hook_file_time(hf->filename);
130
124 by mvo
* src/hooks.{c,h}:
131
   // write out the list of known files
590 by Michael Vogt
* updated to use xdg config dirs
132
   gchar *filename = g_strdup_printf("%s/%s",
133
				     g_get_user_config_dir(),
134
				     HOOKS_SEEN);
124 by mvo
* src/hooks.{c,h}:
135
   FILE *f = fopen(filename, "w");
125 by mvo
* src/hooks.c:
136
   if(f==NULL) {
137
      g_warning("Something went wrong writing the users hook file");
45 by mvo
* added basic "interactive-update-hooks" support
138
      return FALSE;
125 by mvo
* src/hooks.c:
139
   }
144 by mvo
* debian/control:
140
167 by mvo
* src/hooks.c:
141
   // write out all the hooks that are seen 
142
   //
143
   // and any hooks that are not yet seen but have the same md5sum 
144
   // as the one just marked (avoids showing duplicated hooks effecivly). 
145
   //
146
   // For hooks with the same md5sum use the mtime of the just displayed hook
210 by Michael Vogt
* added a notification on hooks
147
   GList *elm = g_list_first(priv->hook_files);
124 by mvo
* src/hooks.{c,h}:
148
   for(;elm != NULL; elm = g_list_next(elm)) {
149
      HookFile *e = (HookFile*)elm->data;
452 by Michael Vogt
rework the debug options and support --debug-inotify,
150
      g_debug_hooks("will write out: %s (%s)",e->filename, e->md5);
167 by mvo
* src/hooks.c:
151
      if(e->seen == TRUE) {
452 by Michael Vogt
rework the debug options and support --debug-inotify,
152
	 g_debug_hooks("e->seen: %s %li %x", e->filename,e->mtime, (int)(e->cmd_run));
340 by Michael Vogt
* code cleanups
153
	 fprintf(f,"%s %li %x\n", e->filename, e->mtime, (int)(e->cmd_run));
400 by Michael Vogt
* src/hooks.c:
154
      } else if(memcmp(e->md5,md5,DIGEST_SIZE) == 0) {
144 by mvo
* debian/control:
155
	 e->seen = TRUE;
340 by Michael Vogt
* code cleanups
156
	 fprintf(f,"%s %li %x\n", e->filename,hf->mtime, (int)(e->cmd_run));
452 by Michael Vogt
rework the debug options and support --debug-inotify,
157
	 g_debug_hooks("same md5: %s %li %x",e->filename,hf->mtime,(int)(e->cmd_run));
125 by mvo
* src/hooks.c:
158
      }
124 by mvo
* src/hooks.{c,h}:
159
   }
45 by mvo
* added basic "interactive-update-hooks" support
160
161
   fclose(f);
162
   g_free(filename);
163
164
   return TRUE;
165
}
166
125 by mvo
* src/hooks.c:
167
/* mark a given HookFile as run */
210 by Michael Vogt
* added a notification on hooks
168
gboolean mark_hook_file_as_run(HookTrayAppletPrivate *priv, HookFile *hf)
45 by mvo
* added basic "interactive-update-hooks" support
169
{
138 by mvo
* src/update.c:
170
   if(hf == NULL)
171
      return FALSE;
172
452 by Michael Vogt
rework the debug options and support --debug-inotify,
173
   g_debug_hooks("mark_hook_file_as_run: %s",hf->filename);
124 by mvo
* src/hooks.{c,h}:
174
   hf->cmd_run = TRUE;
175
45 by mvo
* added basic "interactive-update-hooks" support
176
   return TRUE;
177
}
178
179
70 by mvo
* src/rfc822.h: added a comment explaining about the memory use
180
/* get the language code in a static allocated buffer
181
 * short_form: only return the languagecode if true, otherwise
182
 *             languagecode_countrycode
183
 */
184
char* get_lang_code(gboolean short_form)
185
{
186
   /* make own private copy */
187
   static gchar locale[51];
188
   strncpy(locale, setlocale(LC_MESSAGES, NULL), 50);
189
   
190
   // FIXME: we need to be more inteligent here
191
   // _and_ we probably want to look into the "LANGUAGE" enviroment too
192
   if(short_form) {
193
      locale[2] = 0;
194
      return locale;
195
   } else {
196
      locale[5] = 0;
197
      return locale;
198
   }
199
}
200
201
/*
202
 * get a i18n field of the rfc822 header
203
 * Return Value: a pointer that must not be freed (part of the rfc822 struct)
204
 */
205
char *hook_file_lookup_i18n(struct rfc822_header *rfc822, char *field)
206
{
296 by Michael Vogt
* src/hooks.c:
207
   gchar *s, *entry, *text;
208
209
   /* first check for langpacks, then i18n fields */
210
   entry = rfc822_header_lookup(rfc822, "GettextDomain");
211
   if(entry != NULL) {
212
      text =  rfc822_header_lookup(rfc822, field);
213
      s = dgettext(entry, text);
214
      if(text != s)
215
	 return s;
216
   }
70 by mvo
* src/rfc822.h: added a comment explaining about the memory use
217
390 by Michael Vogt
* src/hooks.c:
218
   /* try $field-$languagecode_$countrycode.$codeset first */
219
   s = g_strdup_printf("%s-%s.%s", field, get_lang_code(FALSE), nl_langinfo(CODESET));
220
   entry = rfc822_header_lookup(rfc822, s);
452 by Michael Vogt
rework the debug options and support --debug-inotify,
221
   //g_debug_hooks("Looking for: %s ; found: %s\n",s,entry);
390 by Michael Vogt
* src/hooks.c:
222
   g_free(s);
223
   if(entry != NULL)
224
      return entry;
225
226
   /* try $field-$languagecode_$countrycode (and assume utf-8) */
70 by mvo
* src/rfc822.h: added a comment explaining about the memory use
227
   s = g_strdup_printf("%s-%s", field, get_lang_code(FALSE));
228
   entry = rfc822_header_lookup(rfc822, s);
452 by Michael Vogt
rework the debug options and support --debug-inotify,
229
   //g_debug_hooks("Looking for: %s ; found: %s\n",s,entry);
70 by mvo
* src/rfc822.h: added a comment explaining about the memory use
230
   g_free(s);
231
   if(entry != NULL)
232
      return entry;
233
390 by Michael Vogt
* src/hooks.c:
234
   /* try $field-$languagecode.$codeset next */
235
   s = g_strdup_printf("%s-%s.%s", field, get_lang_code(TRUE), nl_langinfo(CODESET));
452 by Michael Vogt
rework the debug options and support --debug-inotify,
236
   //g_debug_hooks("Looking for: %s ; found: %s\n",s,entry);
390 by Michael Vogt
* src/hooks.c:
237
   entry = rfc822_header_lookup(rfc822, s);
238
   g_free(s);
239
   if(entry != NULL)
240
      return entry;
241
242
   /* try $field-$languagecode (and assume utf-8 codeset) */
70 by mvo
* src/rfc822.h: added a comment explaining about the memory use
243
   s = g_strdup_printf("%s-%s", field, get_lang_code(TRUE));
452 by Michael Vogt
rework the debug options and support --debug-inotify,
244
   //g_debug_hooks("Looking for: %s ; found: %s\n",s,entry);
70 by mvo
* src/rfc822.h: added a comment explaining about the memory use
245
   entry = rfc822_header_lookup(rfc822, s);
246
   g_free(s);
247
   if(entry != NULL)
248
      return entry;
249
153 by mvo
* configure.in:
250
   /* now try translating it with gettext */
251
   entry = rfc822_header_lookup(rfc822, field);
154 by mvo
* src/hooks.c:
252
   return entry;
253
}
254
255
char* hook_description_get_summary(struct rfc822_header *rfc822)
256
{
300 by Michael Vogt
* src/rfc822.c:
257
   char *summary = hook_file_lookup_i18n(rfc822, "Name");
154 by mvo
* src/hooks.c:
258
   return summary;
259
}
260
261
char* hook_description_get_description(struct rfc822_header *rfc822)
262
{
263
   char *description = hook_file_lookup_i18n(rfc822, "Description");
300 by Michael Vogt
* src/rfc822.c:
264
   return description;
70 by mvo
* src/rfc822.h: added a comment explaining about the memory use
265
}
266
267
/*
268
 * show the given hook file
269
 */
124 by mvo
* src/hooks.{c,h}:
270
gboolean show_next_hook(TrayApplet *ta, GList *hooks)
45 by mvo
* added basic "interactive-update-hooks" support
271
{
452 by Michael Vogt
rework the debug options and support --debug-inotify,
272
   //g_debug_hooks("show_next_hook()\n");
124 by mvo
* src/hooks.{c,h}:
273
210 by Michael Vogt
* added a notification on hooks
274
   HookTrayAppletPrivate *priv = (HookTrayAppletPrivate *)ta->user_data;
464.1.7 by seb128
use gtkbuilder for the hooks too
275
   GtkBuilder *builder = priv->gtk_builder;
45 by mvo
* added basic "interactive-update-hooks" support
276
464.1.7 by seb128
use gtkbuilder for the hooks too
277
   GtkWidget *title = GTK_WIDGET (gtk_builder_get_object(builder, "label_title"));
317 by Michael Vogt
* implemented new "Title" key in the UpgradeHooks file
278
   assert(title);
464.1.7 by seb128
use gtkbuilder for the hooks too
279
   GtkWidget *text = GTK_WIDGET (gtk_builder_get_object(builder, "textview_hook"));
45 by mvo
* added basic "interactive-update-hooks" support
280
   assert(text);
464.1.7 by seb128
use gtkbuilder for the hooks too
281
   GtkWidget *button_next = GTK_WIDGET (gtk_builder_get_object(builder, "button_next"));
45 by mvo
* added basic "interactive-update-hooks" support
282
   assert(button_next);
464.1.7 by seb128
use gtkbuilder for the hooks too
283
   GtkWidget *button_run = GTK_WIDGET (gtk_builder_get_object(builder, "button_run"));
45 by mvo
* added basic "interactive-update-hooks" support
284
   assert(button_run);
285
124 by mvo
* src/hooks.{c,h}:
286
   // init some vars
287
   HookFile *hf = NULL;
288
   char *hook_file = NULL;
289
290
   // find the next unseen hook
291
   GList *elm = g_list_first(hooks);
292
   for(;elm != NULL; elm = g_list_next(elm)) {
293
      hf = (HookFile*)elm->data;
294
      if(hf->seen == FALSE) {
295
	 hook_file = hf->filename;
452 by Michael Vogt
rework the debug options and support --debug-inotify,
296
	 //g_debug_hooks("next_hook is: %s\n",hook_file);
124 by mvo
* src/hooks.{c,h}:
297
	 break;
298
      }
299
   }
300
301
   if(hook_file == NULL) {
452 by Michael Vogt
rework the debug options and support --debug-inotify,
302
      g_debug_hooks("no unseen hookfile found in hook list of len (%i)",
162 by mvo
* src/hooks.c:
303
	      g_list_length(hooks));
167 by mvo
* src/hooks.c:
304
      return FALSE;
124 by mvo
* src/hooks.{c,h}:
305
   }
306
45 by mvo
* added basic "interactive-update-hooks" support
307
   char *filename = g_strdup_printf("%s%s",HOOKS_DIR,hook_file);
308
309
   /* setup the message */
310
   GtkTextBuffer *buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text));
311
   FILE *f = fopen(filename, "r");
312
   if(f == NULL) {
191 by mvo
* move a bunch of g_error -> g_warning
313
      g_warning("can't open %s", filename);
45 by mvo
* added basic "interactive-update-hooks" support
314
      g_free(filename);
167 by mvo
* src/hooks.c:
315
      return FALSE;
45 by mvo
* added basic "interactive-update-hooks" support
316
   }
317
   struct rfc822_header *rfc822 = rfc822_parse_stanza(f);
318
319
   char *cmd = rfc822_header_lookup(rfc822, "Command");
320
   char *term = g_strstrip(rfc822_header_lookup(rfc822, "Terminal"));
321
   g_object_set_data(G_OBJECT(button_run),"cmd", g_strdup(cmd));
322
   g_object_set_data(G_OBJECT(button_run),"term", g_strdup(term));
138 by mvo
* src/update.c:
323
   g_object_set_data(G_OBJECT(button_run),"hook_file", hf);
45 by mvo
* added basic "interactive-update-hooks" support
324
   if(cmd != NULL) {
325
      gtk_widget_show(button_run);
326
   } else {
327
      gtk_widget_hide(button_run);
328
   }
317 by Michael Vogt
* implemented new "Title" key in the UpgradeHooks file
329
   char *title_str = hook_file_lookup_i18n(rfc822, "Title");
330
   if(title_str != NULL) {
331
      gchar *s = g_strdup_printf("<span weight=\"bold\" size=\"larger\">%s</span>", title_str);
332
      gtk_label_set_markup(GTK_LABEL(title), s);
333
      g_free(s);
334
   }
154 by mvo
* src/hooks.c:
335
   char *summary = hook_description_get_summary(rfc822);
336
   char *descr = hook_description_get_description(rfc822);
383 by Michael Vogt
* src/hooks.c:
337
   char *s;
338
   if(summary) {
339
      s = g_strdup_printf("%s\n\n%s\n",gettext(summary), gettext(descr));
340
      gtk_text_buffer_set_text(buf, s, -1);
341
      // set the name to bold
342
      GtkTextIter start, end;
343
      gtk_text_buffer_get_iter_at_offset(buf, &start, 0);
344
      gtk_text_buffer_get_iter_at_offset(buf, &end, g_utf8_strlen(gettext(summary),-1));
345
      gtk_text_buffer_apply_tag_by_name(buf, "bold_tag", &start, &end);
346
347
   } else {
348
      s = g_strdup_printf("%s\n",gettext(descr));
349
      gtk_text_buffer_set_text(buf, s, -1);
350
   }
351
352
   // set button name (if needed)
353
   char *b = hook_file_lookup_i18n(rfc822, "ButtonText");
354
   if(b)
355
      gtk_button_set_label(GTK_BUTTON (button_run), b);
356
   else
357
      gtk_button_set_label(GTK_BUTTON (button_run), _("_Run this action now"));
126 by mvo
* debian/changelog,configure.in:
358
359
   // clean up
45 by mvo
* added basic "interactive-update-hooks" support
360
   fclose(f);
154 by mvo
* src/hooks.c:
361
   g_free(filename);
45 by mvo
* added basic "interactive-update-hooks" support
362
   g_free(s);
363
   rfc822_header_free_all(rfc822);
364
365
   /* mark the current hook file as seen */
124 by mvo
* src/hooks.{c,h}:
366
   g_object_set_data(G_OBJECT(button_next), "HookFile", hf);
367
368
   return TRUE;
45 by mvo
* added basic "interactive-update-hooks" support
369
}
370
371
464.1.7 by seb128
use gtkbuilder for the hooks too
372
void on_button_run_clicked(GtkWidget *self, gpointer *data)
45 by mvo
* added basic "interactive-update-hooks" support
373
{
452 by Michael Vogt
rework the debug options and support --debug-inotify,
374
   //g_debug_hooks("cb_button_run()\n");
138 by mvo
* src/update.c:
375
   gchar *cmdline;
45 by mvo
* added basic "interactive-update-hooks" support
376
377
   TrayApplet *ta = (TrayApplet *)data;
210 by Michael Vogt
* added a notification on hooks
378
   HookTrayAppletPrivate *priv = (HookTrayAppletPrivate *)ta->user_data;
45 by mvo
* added basic "interactive-update-hooks" support
379
380
   /* mark the current hook file as run */
138 by mvo
* src/update.c:
381
   HookFile *hf = g_object_get_data(G_OBJECT(self), "hook_file");
210 by Michael Vogt
* added a notification on hooks
382
   mark_hook_file_as_run(priv, hf);
45 by mvo
* added basic "interactive-update-hooks" support
383
384
   gchar *cmd = g_object_get_data(G_OBJECT(self), "cmd");
385
   gchar *term = g_object_get_data(G_OBJECT(self), "term");
386
387
   if(cmd == NULL) {
388
      g_warning("cmd is NULL\n");
389
      return;
390
   }
391
392
   if(term != NULL && !g_ascii_strncasecmp(term, "true",-1)) {
138 by mvo
* src/update.c:
393
      cmdline = g_strdup_printf("gnome-terminal -e %s",cmd);
394
   } else 
395
      cmdline = g_strdup(cmd);
396
397
   g_spawn_command_line_async(cmdline, NULL);
398
   g_free(cmdline);
45 by mvo
* added basic "interactive-update-hooks" support
399
}
400
464.1.7 by seb128
use gtkbuilder for the hooks too
401
void on_button_next_clicked(GtkWidget *self, gpointer *data)
45 by mvo
* added basic "interactive-update-hooks" support
402
{
452 by Michael Vogt
rework the debug options and support --debug-inotify,
403
   g_debug_hooks("cb_button_next()");
45 by mvo
* added basic "interactive-update-hooks" support
404
   TrayApplet *ta = (TrayApplet *)data;
210 by Michael Vogt
* added a notification on hooks
405
   HookTrayAppletPrivate *priv = (HookTrayAppletPrivate *)ta->user_data;
45 by mvo
* added basic "interactive-update-hooks" support
406
124 by mvo
* src/hooks.{c,h}:
407
   HookFile *hf;
408
   hf = (HookFile*)g_object_get_data(G_OBJECT(self),"HookFile");
409
   if(hf == NULL) {
410
      g_warning("button_next called without HookFile\n");
411
      return;
412
   }
413
   
414
   // mark as seen 
210 by Michael Vogt
* added a notification on hooks
415
   hook_file_mark_as_seen(priv, hf);
124 by mvo
* src/hooks.{c,h}:
416
   check_update_hooks(ta);
417
210 by Michael Vogt
* added a notification on hooks
418
   if(priv->hook_files != NULL)
419
      show_next_hook(ta, priv->hook_files);
45 by mvo
* added basic "interactive-update-hooks" support
420
}
421
434 by Michael Vogt
make the interactive upgrade hooks dialog open up immediately
422
void show_hooks(TrayApplet *ta, gboolean focus_on_map)
45 by mvo
* added basic "interactive-update-hooks" support
423
{
452 by Michael Vogt
rework the debug options and support --debug-inotify,
424
   g_debug_hooks("show_hooks()");
210 by Michael Vogt
* added a notification on hooks
425
   HookTrayAppletPrivate* priv = (HookTrayAppletPrivate *)ta->user_data;
45 by mvo
* added basic "interactive-update-hooks" support
426
464.1.7 by seb128
use gtkbuilder for the hooks too
427
   GtkBuilder *builder = priv->gtk_builder;
428
   GtkWidget *dia = GTK_WIDGET (gtk_builder_get_object(builder, "dialog_hooks"));
434 by Michael Vogt
make the interactive upgrade hooks dialog open up immediately
429
   gtk_window_set_title(GTK_WINDOW(dia), _("Information available"));
45 by mvo
* added basic "interactive-update-hooks" support
430
   assert(dia);
464.1.7 by seb128
use gtkbuilder for the hooks too
431
   GtkWidget *button_run = GTK_WIDGET (gtk_builder_get_object(builder, "button_run"));
45 by mvo
* added basic "interactive-update-hooks" support
432
   assert(button_run);
464.1.7 by seb128
use gtkbuilder for the hooks too
433
   GtkWidget *button_next = GTK_WIDGET (gtk_builder_get_object(builder, "button_next"));
124 by mvo
* src/hooks.{c,h}:
434
   assert(button_next);
435
434 by Michael Vogt
make the interactive upgrade hooks dialog open up immediately
436
   gtk_window_set_focus_on_map(GTK_WINDOW(dia), focus_on_map);
437
167 by mvo
* src/hooks.c:
438
   // if show_next_hook() fails for some reason don't do anything
210 by Michael Vogt
* added a notification on hooks
439
   if(!show_next_hook(ta, priv->hook_files))
167 by mvo
* src/hooks.c:
440
      return;
124 by mvo
* src/hooks.{c,h}:
441
45 by mvo
* added basic "interactive-update-hooks" support
442
   int res = gtk_dialog_run(GTK_DIALOG(dia));
443
   if(res == GTK_RESPONSE_CLOSE) {
124 by mvo
* src/hooks.{c,h}:
444
      // mark the currently current hookfile as seen
445
      HookFile *hf;
446
      hf = (HookFile*)g_object_get_data(G_OBJECT(button_next),"HookFile");
447
      if(hf == NULL) {
448
	 g_warning("show_hooks called without HookFile\n");
449
	 return;
450
      }
451
   
452
      // mark as seen 
210 by Michael Vogt
* added a notification on hooks
453
      hook_file_mark_as_seen(priv, hf);
124 by mvo
* src/hooks.{c,h}:
454
      check_update_hooks(ta);
45 by mvo
* added basic "interactive-update-hooks" support
455
   }
124 by mvo
* src/hooks.{c,h}:
456
45 by mvo
* added basic "interactive-update-hooks" support
457
   gtk_widget_hide(dia);
124 by mvo
* src/hooks.{c,h}:
458
}
45 by mvo
* added basic "interactive-update-hooks" support
459
124 by mvo
* src/hooks.{c,h}:
460
static gboolean
461
button_release_cb (GtkWidget *widget, 
462
		   TrayApplet *ta)
463
{
210 by Michael Vogt
* added a notification on hooks
464
   HookTrayAppletPrivate *priv = (HookTrayAppletPrivate*)ta->user_data;
465
329 by Michael Vogt
* use GtkStatusIcon instead of EggTrayIcon, that makes
466
   if(priv->active_notification != NULL) {
467
      notify_notification_close(priv->active_notification, NULL);
468
      priv->active_notification = NULL;
469
   }
470
   
452 by Michael Vogt
rework the debug options and support --debug-inotify,
471
   //g_debug_hooks("left click on hook applet\n");
434 by Michael Vogt
make the interactive upgrade hooks dialog open up immediately
472
   show_hooks(ta, TRUE);
329 by Michael Vogt
* use GtkStatusIcon instead of EggTrayIcon, that makes
473
   return TRUE;
45 by mvo
* added basic "interactive-update-hooks" support
474
}
475
138 by mvo
* src/update.c:
476
gboolean is_hook_relevant(const gchar *hook_file)
477
{
452 by Michael Vogt
rework the debug options and support --debug-inotify,
478
   g_debug_hooks("is_hook_relevant(): %s", hook_file);
138 by mvo
* src/update.c:
479
   gboolean res = TRUE;
480
481
   char *filename = g_strdup_printf("%s%s",HOOKS_DIR,hook_file);
482
   FILE *f = fopen(filename, "r");
483
   if(f == NULL) {
484
      // can't open, can't be relevant
485
      return FALSE; 
486
   }
487
   struct rfc822_header *rfc822 = rfc822_parse_stanza(f);
488
388 by Michael Vogt
* src/hooks.c:
489
   // check if its a note that is relevant only for admin users
490
   // (this is the default)
491
   gchar *b = rfc822_header_lookup(rfc822, "OnlyAdminUsers");
492
   if(b == NULL || g_ascii_strncasecmp(b, "true",-1) == 0) {
493
      if (!in_admin_group())
494
	 return FALSE;
495
   }
496
138 by mvo
* src/update.c:
497
   // check the DontShowAfterReboot flag
388 by Michael Vogt
* src/hooks.c:
498
   b = rfc822_header_lookup(rfc822, "DontShowAfterReboot");
138 by mvo
* src/update.c:
499
   if(b != NULL && g_ascii_strncasecmp(b, "true",-1) == 0) {
452 by Michael Vogt
rework the debug options and support --debug-inotify,
500
      g_debug_hooks("found DontShowAfterReboot");
138 by mvo
* src/update.c:
501
502
      // read the uptime information
503
      double uptime=0, idle=0;
504
      char buf[1024];
151 by mvo
* src/hooks.c:
505
      int fd = open("/proc/uptime", 0);
138 by mvo
* src/update.c:
506
      int local_n = read(fd, buf, sizeof(buf)-1);
507
      buf[local_n] = '\0';
508
      char *savelocale = setlocale(LC_NUMERIC, NULL);
509
      setlocale(LC_NUMERIC,"C");
510
      sscanf(buf, "%lf %lf", &uptime,&idle);
511
      close(fd);
512
      setlocale(LC_NUMERIC,savelocale);
513
164 by mvo
* src/hooks.c:
514
      time_t mtime = hook_file_time(hook_file);
138 by mvo
* src/update.c:
515
      time_t now = time(NULL);
516
452 by Michael Vogt
rework the debug options and support --debug-inotify,
517
      g_debug_hooks("now: %li mtime: %li uptime: %f",now,mtime,uptime);
518
      g_debug_hooks("diff: %li  uptime: %f",now-mtime,uptime);
138 by mvo
* src/update.c:
519
      if((int)uptime > 0 && (now - mtime) > (int)uptime) {
452 by Michael Vogt
rework the debug options and support --debug-inotify,
520
	 g_debug_hooks("not relevant because of reboot: %s",hook_file);
138 by mvo
* src/update.c:
521
	 res = FALSE;
211 by Michael Vogt
* added debugging support via --debug-hooks
522
      }  else
452 by Michael Vogt
rework the debug options and support --debug-inotify,
523
	 g_debug_hooks("hook is relevant");
138 by mvo
* src/update.c:
524
   }
525
   fclose(f);
144 by mvo
* debian/control:
526
297 by Michael Vogt
* src/hooks.c:
527
   // check for DisplayIf test
528
   b = rfc822_header_lookup(rfc822, "DisplayIf");
529
   if(b != NULL) {
452 by Michael Vogt
rework the debug options and support --debug-inotify,
530
      g_debug_hooks("found DisplayIf command: '%s'", b);
297 by Michael Vogt
* src/hooks.c:
531
      int exitc = system(b);
452 by Michael Vogt
rework the debug options and support --debug-inotify,
532
      g_debug_hooks("'%s' returned: %i", b, exitc);
300 by Michael Vogt
* src/rfc822.c:
533
      res = (exitc == 0);
297 by Michael Vogt
* src/hooks.c:
534
   }
144 by mvo
* debian/control:
535
138 by mvo
* src/update.c:
536
   g_free(filename);
537
   rfc822_header_free_all(rfc822);
538
   return res;
539
}
48 by mvo
* various fixes
540
215 by Michael Vogt
* now the notification for a hook with a delay
541
static gboolean show_notification(void *data)
542
{
543
   TrayApplet *ta = (TrayApplet*)data;
544
   HookTrayAppletPrivate *priv = (HookTrayAppletPrivate*)ta->user_data;
545
365 by Michael Vogt
* src/update.c, src/crash.c, src/hooks.c:
546
   if(!gtk_status_icon_get_visible(ta->tray_icon))
547
      return FALSE;
548
464.1.7 by seb128
use gtkbuilder for the hooks too
549
   GtkWidget *d = GTK_WIDGET (gtk_builder_get_object(priv->gtk_builder,"dialog_hooks"));
595.1.1 by Michael Terry
* Add --disable-deprecations configure flag to test for deprecated API use
550
   if((d && gtk_widget_get_visible(d)) || priv->active_notification != NULL)
340 by Michael Vogt
* code cleanups
551
      return FALSE;
215 by Michael Vogt
* now the notification for a hook with a delay
552
333 by Michael Vogt
* fix leftover from pre-GtkStatusIcon code (LP: #127965)
553
   GdkRectangle area;
554
   gtk_status_icon_get_geometry(ta->tray_icon, NULL, &area, NULL);
555
   // no usefull coordiante yet, do another timeout
556
   if(area.x <= 0 || area.y <= 0 || area.width <= 0 || area.height <= 0)
557
      return TRUE;
558
215 by Michael Vogt
* now the notification for a hook with a delay
559
   NotifyNotification *n;
560
   GdkPixbuf* pix;
334 by Michael Vogt
* fix crash in leftover from pre-GtkStatusIcon code (LP: #127965)
561
   n = notify_notification_new_with_status_icon(
562
			       _("Information available"),
207.1.4 by Sebastian Heinlein
* Wording fixes
563
			       _("Click on the notification icon"
564
				 " to show the available information.\n"),
215 by Michael Vogt
* now the notification for a hook with a delay
565
			       NULL, 
334 by Michael Vogt
* fix crash in leftover from pre-GtkStatusIcon code (LP: #127965)
566
			       ta->tray_icon);
215 by Michael Vogt
* now the notification for a hook with a delay
567
   
568
   pix = gtk_icon_theme_load_icon(gtk_icon_theme_get_default(), 
569
				  GTK_STOCK_DIALOG_INFO, 48,0,NULL);
570
   notify_notification_set_icon_from_pixbuf (n, pix);
571
   g_object_unref(pix);
572
   notify_notification_set_timeout (n, 60*1000);
573
   notify_notification_show(n, NULL);
574
   priv->active_notification = n;
317 by Michael Vogt
* implemented new "Title" key in the UpgradeHooks file
575
215 by Michael Vogt
* now the notification for a hook with a delay
576
   return FALSE;
577
}
578
45 by mvo
* added basic "interactive-update-hooks" support
579
gboolean check_update_hooks(TrayApplet *ta)
580
{
340 by Michael Vogt
* code cleanups
581
   GList *elm;
582
   HookFile *hf;
45 by mvo
* added basic "interactive-update-hooks" support
583
   GDir* dir;
584
   const gchar *hook_file;
585
452 by Michael Vogt
rework the debug options and support --debug-inotify,
586
   g_debug_hooks("check_update_hooks()");
340 by Michael Vogt
* code cleanups
587
   HookTrayAppletPrivate *priv = (HookTrayAppletPrivate*)ta->user_data;
588
45 by mvo
* added basic "interactive-update-hooks" support
589
   dir=g_dir_open(HOOKS_DIR, 0, NULL);
254 by Michael Vogt
* src/crash.c, src/hooks.c:
590
   if(dir == NULL) {
191 by mvo
* move a bunch of g_error -> g_warning
591
      g_warning("can't read %s directory\n",HOOKS_DIR);
254 by Michael Vogt
* src/crash.c, src/hooks.c:
592
      return FALSE;
593
   }
45 by mvo
* added basic "interactive-update-hooks" support
594
452 by Michael Vogt
rework the debug options and support --debug-inotify,
595
   g_debug_hooks("reading '%s' dir", HOOKS_DIR);
138 by mvo
* src/update.c:
596
   int unseen_count = 0;
45 by mvo
* added basic "interactive-update-hooks" support
597
   while((hook_file=g_dir_read_name(dir)) != NULL) {
452 by Michael Vogt
rework the debug options and support --debug-inotify,
598
      g_debug_hooks("investigating file '%s' ", hook_file); 
138 by mvo
* src/update.c:
599
600
      // check if the hook still applies (for e.g. DontShowAfterReboot)
211 by Michael Vogt
* added debugging support via --debug-hooks
601
      if(!is_hook_relevant(hook_file)) {
452 by Michael Vogt
rework the debug options and support --debug-inotify,
602
	 g_debug_hooks("not relevant: '%s'",hook_file);
138 by mvo
* src/update.c:
603
	 continue;
211 by Michael Vogt
* added debugging support via --debug-hooks
604
      }
124 by mvo
* src/hooks.{c,h}:
605
      // see if we already know about this hook filename
340 by Michael Vogt
* code cleanups
606
      elm = g_list_find_custom(priv->hook_files,hook_file,
124 by mvo
* src/hooks.{c,h}:
607
				      compare_hook_func);
163 by mvo
* src/hooks.c:
608
124 by mvo
* src/hooks.{c,h}:
609
      // not seen before, add to the list
610
      if(elm == NULL) {
452 by Michael Vogt
rework the debug options and support --debug-inotify,
611
	 g_debug_hooks("never seen before: %s",hook_file);
124 by mvo
* src/hooks.{c,h}:
612
	 HookFile *t = g_new0(HookFile, 1);
613
	 t->filename = strdup(hook_file);
164 by mvo
* src/hooks.c:
614
	 t->mtime = hook_file_time(hook_file);
144 by mvo
* debian/control:
615
	 hook_file_md5(hook_file, t->md5);
124 by mvo
* src/hooks.{c,h}:
616
	 t->cmd_run = FALSE;
617
	 t->seen = FALSE;
340 by Michael Vogt
* code cleanups
618
	 priv->hook_files = g_list_append(priv->hook_files, (gpointer)t);
163 by mvo
* src/hooks.c:
619
	 // init elm with the just added record (will be needed below)
210 by Michael Vogt
* added a notification on hooks
620
	 elm = g_list_find_custom(priv->hook_files,hook_file,
144 by mvo
* debian/control:
621
				  compare_hook_func);
622
	 assert(elm != NULL);
124 by mvo
* src/hooks.{c,h}:
623
      }
624
      
163 by mvo
* src/hooks.c:
625
      // this is the hook file information we have (either because it was
626
      // availabe already or because we added it)
340 by Michael Vogt
* code cleanups
627
      hf = (HookFile*)elm->data;
125 by mvo
* src/hooks.c:
628
163 by mvo
* src/hooks.c:
629
      // file has changed since we last saw it
164 by mvo
* src/hooks.c:
630
      time_t new_mtime = hook_file_time(hook_file);
163 by mvo
* src/hooks.c:
631
      if(new_mtime > hf->mtime) {
452 by Michael Vogt
rework the debug options and support --debug-inotify,
632
	 g_debug_hooks("newer mtime: %s (%li > %li))",hook_file, new_mtime, hf->mtime);
163 by mvo
* src/hooks.c:
633
	 hf->seen = FALSE;
634
      }
635
636
      // we have not seen it yet (because e.g. it was just added)
125 by mvo
* src/hooks.c:
637
      if(hf->seen == FALSE) {
452 by Michael Vogt
rework the debug options and support --debug-inotify,
638
	 g_debug_hooks("the file '%s' was NOT SEEN yet",hook_file);
144 by mvo
* debian/control:
639
162 by mvo
* src/hooks.c:
640
	 // update mtime (because we haven't seen the old one and there
641
	 // is a new one now)
163 by mvo
* src/hooks.c:
642
	 hf->mtime = new_mtime;
162 by mvo
* src/hooks.c:
643
144 by mvo
* debian/control:
644
	 // check if there is already another notification that is 
645
	 // a) not this one
646
	 // b) not seen yet
647
	 // c) the same
648
	 // if so, we don't increase the unseen count as all identical
649
	 // ones will maked as unseen at onces
650
	 gboolean md5match = FALSE;
210 by Michael Vogt
* added a notification on hooks
651
	 GList *x = g_list_first(priv->hook_files);
144 by mvo
* debian/control:
652
	 while(x!=NULL) {
653
	    HookFile *e = (HookFile*)x->data;
654
	    if((elm != x)  &&
655
	       (e->seen == FALSE) &&
400 by Michael Vogt
* src/hooks.c:
656
	       (memcmp(hf->md5,e->md5,DIGEST_SIZE)==0) )
144 by mvo
* debian/control:
657
	      {
452 by Michael Vogt
rework the debug options and support --debug-inotify,
658
		 g_debug_hooks("%s (%s) was seen also in %s (%s)\n",
162 by mvo
* src/hooks.c:
659
			 hf->filename, hf->md5, e->filename, e->md5);
144 by mvo
* debian/control:
660
		 md5match = TRUE;
661
	      }
662
	    x = g_list_next(x);
663
	 }
664
	 if(!md5match) {
452 by Michael Vogt
rework the debug options and support --debug-inotify,
665
	    g_debug_hooks("%s increases unseen_count\n",hf->filename);
144 by mvo
* debian/control:
666
	    unseen_count++;
667
	 }
211 by Michael Vogt
* added debugging support via --debug-hooks
668
      } else 
452 by Michael Vogt
rework the debug options and support --debug-inotify,
669
	 g_debug_hooks("already seen: '%s'",hook_file);
45 by mvo
* added basic "interactive-update-hooks" support
670
   }
671
   g_dir_close(dir);
672
452 by Michael Vogt
rework the debug options and support --debug-inotify,
673
   //g_debug_hooks("hooks: %i (new: %i)", g_list_length(hook_files), unseen_count);
45 by mvo
* added basic "interactive-update-hooks" support
674
464.1.7 by seb128
use gtkbuilder for the hooks too
675
   GtkBuilder *builder = priv->gtk_builder;
676
   GtkWidget *button_next = GTK_WIDGET (gtk_builder_get_object(builder, "button_next"));
124 by mvo
* src/hooks.{c,h}:
677
   assert(button_next);
45 by mvo
* added basic "interactive-update-hooks" support
678
434 by Michael Vogt
make the interactive upgrade hooks dialog open up immediately
679
   // check if we do a notification or a dialog
680
   GConfClient *gconf = gconf_client_get_default();
681
   if(gconf_client_get_bool(gconf, GCONF_KEY_AUTO_LAUNCH, NULL)) {
452 by Michael Vogt
rework the debug options and support --debug-inotify,
682
      g_debug_hooks("showing hooks with focus on map == FALSE");
434 by Michael Vogt
make the interactive upgrade hooks dialog open up immediately
683
      if (unseen_count < 2)
684
	 gtk_widget_hide(button_next);
685
      else
686
	 gtk_widget_show(button_next);
687
      show_hooks(ta, FALSE);
688
      return TRUE;
689
   }
690
691
   // no dialog, do the notification
692
   if((unseen_count > 0) && !gtk_status_icon_get_visible (ta->tray_icon))
215 by Michael Vogt
* now the notification for a hook with a delay
693
      g_timeout_add(5000, show_notification, ta);
210 by Michael Vogt
* added a notification on hooks
694
138 by mvo
* src/update.c:
695
   switch(unseen_count) {
125 by mvo
* src/hooks.c:
696
   case 0:
329 by Michael Vogt
* use GtkStatusIcon instead of EggTrayIcon, that makes
697
      gtk_status_icon_set_visible (ta->tray_icon, FALSE);
45 by mvo
* added basic "interactive-update-hooks" support
698
      gtk_widget_hide(button_next);
125 by mvo
* src/hooks.c:
699
      break;
700
   case 1:
329 by Michael Vogt
* use GtkStatusIcon instead of EggTrayIcon, that makes
701
      gtk_status_icon_set_visible (ta->tray_icon, TRUE);
125 by mvo
* src/hooks.c:
702
      gtk_widget_hide(button_next);
703
      break;
704
   default:
329 by Michael Vogt
* use GtkStatusIcon instead of EggTrayIcon, that makes
705
      gtk_status_icon_set_visible (ta->tray_icon, TRUE);
45 by mvo
* added basic "interactive-update-hooks" support
706
      gtk_widget_show(button_next);
125 by mvo
* src/hooks.c:
707
      break;
45 by mvo
* added basic "interactive-update-hooks" support
708
   }
138 by mvo
* src/update.c:
709
   hooks_trayicon_update_tooltip (ta, unseen_count);
45 by mvo
* added basic "interactive-update-hooks" support
710
711
   return TRUE;
712
}
713
210 by Michael Vogt
* added a notification on hooks
714
void hook_read_seen_file(HookTrayAppletPrivate *priv, const char* filename)
45 by mvo
* added basic "interactive-update-hooks" support
715
{
340 by Michael Vogt
* code cleanups
716
   HookFile *t;
45 by mvo
* added basic "interactive-update-hooks" support
717
   char buf[512];
718
   int time, was_run;
719
   FILE *f = fopen(filename, "r");
720
   if(f==NULL)
161 by mvo
* src/hooks.c:
721
      return;
128 by mvo
* debian/dirs:
722
452 by Michael Vogt
rework the debug options and support --debug-inotify,
723
   g_debug_hooks("reading hook_file: %s ", filename);
128 by mvo
* debian/dirs:
724
45 by mvo
* added basic "interactive-update-hooks" support
725
   while(fscanf(f, "%s %i %i",buf,&time,&was_run) == 3) {
129 by mvo
* src/hooks.c:
726
167 by mvo
* src/hooks.c:
727
      // first check if the file actually exists, if not skip it
728
      // (may already be delete when e.g. a package was removed)
729
      char *filename = g_strdup_printf("%s%s",HOOKS_DIR,buf);
730
      gboolean res = g_file_test(filename, G_FILE_TEST_EXISTS);
731
      g_free(filename);
732
      if(!res)
733
	 continue;
734
129 by mvo
* src/hooks.c:
735
      // now check if we already have that filename in the list
210 by Michael Vogt
* added a notification on hooks
736
      GList *elm = g_list_find_custom(priv->hook_files,buf,
129 by mvo
* src/hooks.c:
737
				      compare_hook_func);
738
      if(elm != NULL) {
452 by Michael Vogt
rework the debug options and support --debug-inotify,
739
	 g_debug_hooks("hookfile: %s already in the list", buf);
161 by mvo
* src/hooks.c:
740
741
	 // we have that file already in the list with a newer mtime,
742
	 // than the file in the config file. ignore the config file
129 by mvo
* src/hooks.c:
743
	 HookFile *exisiting = (HookFile *)elm->data;
744
	 // and it's more current
745
	 if(exisiting->mtime > time) {
452 by Michael Vogt
rework the debug options and support --debug-inotify,
746
	    g_debug_hooks("existing is newer, ignoring the read one\n");
129 by mvo
* src/hooks.c:
747
	    continue;
748
	 }
749
161 by mvo
* src/hooks.c:
750
	 // we have it in the list, but the the file in the list is older
167 by mvo
* src/hooks.c:
751
	 // than the one in the config file. use this config-file instead
752
	 // and update the values in the list
161 by mvo
* src/hooks.c:
753
	 exisiting->cmd_run = was_run;
167 by mvo
* src/hooks.c:
754
	 exisiting->seen = TRUE;
161 by mvo
* src/hooks.c:
755
	 exisiting->mtime = time;
162 by mvo
* src/hooks.c:
756
	 hook_file_md5(exisiting->filename,exisiting->md5);
757
161 by mvo
* src/hooks.c:
758
      } else {
167 by mvo
* src/hooks.c:
759
	 // not in the list yet
161 by mvo
* src/hooks.c:
760
	 // add the just read hook file to the list
452 by Michael Vogt
rework the debug options and support --debug-inotify,
761
	 g_debug_hooks("got: %s %i %i ",buf,time,was_run);
340 by Michael Vogt
* code cleanups
762
	 t = g_new0(HookFile, 1);
161 by mvo
* src/hooks.c:
763
	 t->filename = strdup(buf);
764
	 t->mtime = time;
765
	 t->cmd_run = was_run;
766
	 t->seen = TRUE;
162 by mvo
* src/hooks.c:
767
	 hook_file_md5(t->filename,t->md5);
768
340 by Michael Vogt
* code cleanups
769
	 priv->hook_files = g_list_append(priv->hook_files, (gpointer)t);
129 by mvo
* src/hooks.c:
770
      }
45 by mvo
* added basic "interactive-update-hooks" support
771
   }
128 by mvo
* debian/dirs:
772
   fclose(f);
773
}
774
434 by Michael Vogt
make the interactive upgrade hooks dialog open up immediately
775
gboolean 
776
init_already_seen_hooks(TrayApplet *ta)
128 by mvo
* debian/dirs:
777
{
452 by Michael Vogt
rework the debug options and support --debug-inotify,
778
   g_debug_hooks("init_already_seen_hooks");
129 by mvo
* src/hooks.c:
779
210 by Michael Vogt
* added a notification on hooks
780
   HookTrayAppletPrivate* priv = (HookTrayAppletPrivate*)ta->user_data;
590 by Michael Vogt
* updated to use xdg config dirs
781
   char *filename, *old_filename;
128 by mvo
* debian/dirs:
782
145 by mvo
* updated hungarian translation
783
   // init with default value
210 by Michael Vogt
* added a notification on hooks
784
   priv->hook_files = NULL;  
128 by mvo
* debian/dirs:
785
786
   // read global hook file
590 by Michael Vogt
* updated to use xdg config dirs
787
   hook_read_seen_file(priv, GLOBAL_HOOKS_SEEN);
129 by mvo
* src/hooks.c:
788
   
590 by Michael Vogt
* updated to use xdg config dirs
789
   filename = g_strdup_printf("%s/%s", 
790
			      g_get_user_config_dir(),
791
			      HOOKS_SEEN);
792
   // compat with the previous version
793
   old_filename = g_strdup_printf("%s/%s", 
794
				  g_get_home_dir(),
591 by Michael Vogt
apply xdg patches by Sebastian Geiger, many thanks
795
				  HOOKS_SEEN_DEPRECATED);
590 by Michael Vogt
* updated to use xdg config dirs
796
   if (g_file_test(old_filename, G_FILE_TEST_IS_REGULAR)) {
797
     g_rename(old_filename, filename);
798
   }
128 by mvo
* debian/dirs:
799
   // read user hook file
210 by Michael Vogt
* added a notification on hooks
800
   hook_read_seen_file(priv,filename);
45 by mvo
* added basic "interactive-update-hooks" support
801
   g_free(filename);
128 by mvo
* debian/dirs:
802
45 by mvo
* added basic "interactive-update-hooks" support
803
   return TRUE;
804
}
805
271 by Michael Vogt
* src/hooks.c:
806
static void
807
on_insert_text(GtkTextBuffer *buffer,
808
	       GtkTextIter   *iter_end,
809
	       gchar         *text,
810
	       gint           arg3,
811
	       gpointer       user_data)
812
{
340 by Michael Vogt
* code cleanups
813
   GtkTextIter iter, match_start, match_end, match_tmp;
271 by Michael Vogt
* src/hooks.c:
814
815
   // get where we start
816
   gtk_text_buffer_get_iter_at_offset(buffer, &iter,
817
				      gtk_text_iter_get_offset(iter_end) - g_utf8_strlen(text,-1));
818
   // search for http:// uris
819
   while(gtk_text_iter_forward_search(&iter, 
820
				      "http://",  GTK_TEXT_SEARCH_VISIBLE_ONLY, 
821
				      &match_start, &match_end, iter_end))  {
822
      match_tmp = match_end;
823
      // we found a uri, iterate it until the end is found
824
      while(gtk_text_iter_forward_char(&match_tmp)) {
825
	 gchar *s = gtk_text_iter_get_text(&match_end,&match_tmp);
826
	 if(strlen(s) < 1)
827
	    break;
828
	 char c = s[strlen(s)-1];
829
	 if(c == ' ' || c == ')' || c == ']' || c == '\n' || c == '\t' || c == '>')
830
	    break;
831
	 match_end = match_tmp;
832
      }
833
      gchar *url = gtk_text_iter_get_text(&match_start, &match_end);
834
      //g_print("url: '%s'\n",url);
835
      GtkTextTag *tag;
836
      tag = gtk_text_buffer_create_tag(buffer, NULL,
837
				       "foreground","blue",
838
				       "underline", PANGO_UNDERLINE_SINGLE,
839
				       NULL);
840
      g_object_set_data(G_OBJECT(tag), "url", url);
841
      gtk_text_buffer_apply_tag(buffer, tag, &match_start, &match_end);
842
      iter = match_end;
843
   }
844
}
845
846
static void
847
on_event_after(GtkWidget *widget,
848
	       GdkEventButton  *event,
849
	       gpointer   user_data)      
850
{
851
   if(event->type != GDK_BUTTON_RELEASE)
852
      return;
853
   if(event->button != 1)
854
      return;
855
   gint x,y;
856
   gtk_text_view_window_to_buffer_coords(GTK_TEXT_VIEW(widget),
857
					 GTK_TEXT_WINDOW_WIDGET,
858
					 event->x, event->y,
859
					 &x, &y);
860
   GtkTextIter iter;
861
   gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(widget), &iter, x, y);
862
   GSList *tags = gtk_text_iter_get_tags(&iter);
863
   for( ; tags != NULL ; tags = tags->next) {
864
      gchar *url = g_object_get_data(G_OBJECT(tags->data), "url");
865
      if(url != NULL) {
866
	 //g_print("click: '%s'\n",url);
867
	 char *argv[] = { "/usr/bin/gnome-open", url, NULL };
868
	 g_spawn_async(NULL, argv, NULL, 0, NULL, NULL, NULL, NULL);
869
	 break;
870
      }
871
   }
872
}
45 by mvo
* added basic "interactive-update-hooks" support
873
874
void hook_tray_icon_init(TrayApplet *ta)
875
{
464.1.7 by seb128
use gtkbuilder for the hooks too
876
   GError* error = NULL;
877
   GtkBuilder* builder = gtk_builder_new ();
878
210 by Michael Vogt
* added a notification on hooks
879
   HookTrayAppletPrivate *priv = g_new0(HookTrayAppletPrivate, 1);
880
   ta->user_data = priv;
464.1.7 by seb128
use gtkbuilder for the hooks too
881
882
   if (!gtk_builder_add_from_file (builder, UIDIR"hooks-dialog.ui", &error)) {
476 by Michael Vogt
fix -Wall errors
883
      g_warning ("Couldn't load builder file: %s", error->message);
884
      g_error_free (error);
464.1.7 by seb128
use gtkbuilder for the hooks too
885
   }
886
887
   assert(builder);
888
   priv->gtk_builder = builder;
889
   gtk_builder_connect_signals (builder, (gpointer)ta);
45 by mvo
* added basic "interactive-update-hooks" support
890
891
   /* show dialog on click */
892
   g_signal_connect (G_OBJECT(ta->tray_icon),
329 by Michael Vogt
* use GtkStatusIcon instead of EggTrayIcon, that makes
893
		     "activate",
45 by mvo
* added basic "interactive-update-hooks" support
894
		     G_CALLBACK (button_release_cb),
895
		     ta);
896
126 by mvo
* debian/changelog,configure.in:
897
   // create a bold tag
464.1.7 by seb128
use gtkbuilder for the hooks too
898
   GtkWidget *text = GTK_WIDGET (gtk_builder_get_object(builder, "textview_hook"));
126 by mvo
* debian/changelog,configure.in:
899
   GtkTextBuffer *buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text));
900
   gtk_text_buffer_create_tag (buf, "bold_tag",
901
			       "scale", PANGO_SCALE_LARGE, 
902
			       "weight", PANGO_WEIGHT_BOLD,
903
			       NULL);  
271 by Michael Vogt
* src/hooks.c:
904
   g_signal_connect_after(G_OBJECT(buf), "insert-text", 
905
			  G_CALLBACK(on_insert_text), NULL);
906
   g_signal_connect_after(G_OBJECT(text), "event-after", 
907
			  G_CALLBACK(on_event_after), NULL);
126 by mvo
* debian/changelog,configure.in:
908
909
45 by mvo
* added basic "interactive-update-hooks" support
910
   /* read already seen hooks */
911
   init_already_seen_hooks(ta);
912
   
913
   /* Check for hooks */
914
   check_update_hooks(ta);
915
}