~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
45 by mvo
* added basic "interactive-update-hooks" support
5
#include <libintl.h>
97 by mvo
* debian/changelog:
6
#include <sys/wait.h>
479 by Michael Vogt
when checking apt/dpkg logs, glob() for the old(er)
7
#include <glob.h>
45 by mvo
* added basic "interactive-update-hooks" support
8
476 by Michael Vogt
fix -Wall errors
9
#include <glib.h>
10
#include <glib/gstdio.h>
11
352 by Michael Vogt
* show a warning icon if the last refresh of the
12
#include <sys/types.h>
13
#include <sys/stat.h>
14
#include <unistd.h>
476 by Michael Vogt
fix -Wall errors
15
#include <stdlib.h>
451 by Michael Vogt
* src/update.c:
16
#include <dbus/dbus-glib.h>
352 by Michael Vogt
* show a warning icon if the last refresh of the
17
45 by mvo
* added basic "interactive-update-hooks" support
18
#include "update-notifier.h"
19
#include "update.h"
20
21
#define UPGRADE_CHECKER PACKAGE_LIB_DIR"/update-notifier/apt-check"
22
266 by Michael Vogt
* src/update-notifier.{c,h}:
23
// command, description, desktopfile, needs_gksu
359.2.1 by Michael Vogt
* port the gnomevfs code to gio - we need to get rid of
24
const char* actions[][4] = {
207.1.4 by Sebastian Heinlein
* Wording fixes
25
   { "/usr/bin/update-manager", N_("Show updates"), 
476 by Michael Vogt
fix -Wall errors
26
     "/usr/share/applications/update-manager.desktop", 
27
     GINT_TO_POINTER(FALSE) },
266 by Michael Vogt
* src/update-notifier.{c,h}:
28
237 by Michael Vogt
* src/update.c:
29
   { "/usr/sbin/synaptic --dist-upgrade-mode --non-interactive --hide-main-window -o Synaptic::AskRelated=true",
476 by Michael Vogt
fix -Wall errors
30
     N_("Install all updates"), "/usr/share/applications/synaptic.desktop", 
31
     GINT_TO_POINTER(TRUE)
340 by Michael Vogt
* code cleanups
32
   },
33
   { "/usr/sbin/synaptic --update-at-startup --non-interactive --hide-main-window", 
476 by Michael Vogt
fix -Wall errors
34
     N_("Check for updates"), "/usr/share/applications/synaptic.desktop", 
35
     GINT_TO_POINTER(TRUE) },
207.1.4 by Sebastian Heinlein
* Wording fixes
36
   { "/usr/sbin/synaptic", N_("Start package manager"), 
476 by Michael Vogt
fix -Wall errors
37
     "/usr/share/applications/synaptic.desktop", 
38
     GINT_TO_POINTER(TRUE)},
207.1.4 by Sebastian Heinlein
* Wording fixes
39
   { NULL, NULL, NULL }
45 by mvo
* added basic "interactive-update-hooks" support
40
};
41
429 by Michael Vogt
add gconf "/apps/update-notifier/auto_launch" option that
42
enum { 
43
   NOTIFICATION_DEFAULT, 
44
   NOTIFICATION_IGNORE, 
45
   NOTIFICATION_SHOW_UPDATES 
46
};
45 by mvo
* added basic "interactive-update-hooks" support
47
452 by Michael Vogt
rework the debug options and support --debug-inotify,
48
static inline void
49
g_debug_update(const char *msg, ...)
445 by Michael Vogt
* src/update-notifier.c:
50
{
452 by Michael Vogt
rework the debug options and support --debug-inotify,
51
   va_list va;
454 by Michael Vogt
fix crash in --debug mode (LP: #348883)
52
   va_start(va, msg);
53
   g_logv("update",G_LOG_LEVEL_DEBUG, msg, va);
54
   va_end(va);
445 by Michael Vogt
* src/update-notifier.c:
55
}
56
45 by mvo
* added basic "interactive-update-hooks" support
57
static gboolean
329 by Michael Vogt
* use GtkStatusIcon instead of EggTrayIcon, that makes
58
activate_cb (GtkWidget *widget, 
59
	     TrayApplet *ta)
45 by mvo
* added basic "interactive-update-hooks" support
60
{
382.1.1 by Muhammad Ameen
fixed bug synaptic bug 274562
61
   UpdateTrayAppletPrivate *priv = (UpdateTrayAppletPrivate*)ta->user_data;
62
   int index = priv->apt_is_running ? 3 : 0;
375 by Michael Vogt
* src/update.c:
63
   
64
   // on double click we get two activate signals, so slow down things
65
   // here a bit to avoid double starting
66
   static time_t last_action = 0;
67
   if (time(NULL) - last_action > 1) 
68
      invoke (actions[index][0], actions[index][2], (long)actions[index][3]);
69
   last_action = time(NULL);
208 by Michael Vogt
* -Wall clean now
70
   return TRUE;
45 by mvo
* added basic "interactive-update-hooks" support
71
}
72
73
static gboolean
329.1.1 by Michael Vogt
src/update.c:
74
popup_cb (GtkStatusIcon *status_icon,
75
	  guint          button,
76
	  guint          activate_time,
77
	  TrayApplet     *un)
45 by mvo
* added basic "interactive-update-hooks" support
78
{
329.1.1 by Michael Vogt
src/update.c:
79
   gtk_menu_set_screen (GTK_MENU (un->menu),
80
			gtk_status_icon_get_screen(un->tray_icon));
81
   gtk_menu_popup (GTK_MENU (un->menu), NULL, NULL, 
82
		   gtk_status_icon_position_menu, un->tray_icon,
83
		   button, activate_time);
329 by Michael Vogt
* use GtkStatusIcon instead of EggTrayIcon, that makes
84
   return TRUE;
45 by mvo
* added basic "interactive-update-hooks" support
85
}
86
87
void
88
update_trayicon_update_tooltip (TrayApplet *ta, int num_upgrades)
89
{
90
   //g_print("update_tooltip: %p %p %p\n", ta, ta->tooltip, ta->eventbox);
91
   gchar *updates;
92
341 by Michael Vogt
* fix incorrect tooltip when package manager was
93
   updates = g_strdup_printf(ngettext("There is %i update available",
94
				      "There are %i updates available",
95
				      num_upgrades),
96
			     num_upgrades);
329 by Michael Vogt
* use GtkStatusIcon instead of EggTrayIcon, that makes
97
   gtk_status_icon_set_tooltip(ta->tray_icon, updates);
64 by mvo
* src/update.c: ngettext() fix
98
   g_free(updates);
45 by mvo
* added basic "interactive-update-hooks" support
99
}
100
101
102
void 
103
cb_action(GObject *self, void *user_data)
104
{
208 by Michael Vogt
* -Wall clean now
105
   TrayApplet *ta = user_data;
45 by mvo
* added basic "interactive-update-hooks" support
106
	
208 by Michael Vogt
* -Wall clean now
107
   int i = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(self), "action"));
340 by Michael Vogt
* code cleanups
108
   invoke (actions[i][0], _(actions[i][2]), (long)actions[i][3]);
59 by mvo
* debian/changelog: updated
109
208 by Michael Vogt
* -Wall clean now
110
   UpdateTrayAppletPrivate *priv = (UpdateTrayAppletPrivate*)ta->user_data;
111
   gconf_client_set_int(priv->gconf, GCONF_KEY_DEFAULT_ACTION, i, NULL);
45 by mvo
* added basic "interactive-update-hooks" support
112
}
113
134 by mvo
* data/apt-check:
114
void 
115
cb_preferences(GObject *self, void *user_data)
45 by mvo
* added basic "interactive-update-hooks" support
116
{
306 by Michael Vogt
- fix software-properties call (LP#93909)
117
   invoke_with_gksu("/usr/bin/software-properties-gtk",
283 by Martin Pitt
* src/update-notifier.h: Add a third argument to invoke_with_gksu which uses
118
		    "/usr/share/applications/software-properties.desktop",
119
		    FALSE);    
45 by mvo
* added basic "interactive-update-hooks" support
120
}
121
134 by mvo
* data/apt-check:
122
void 
157 by mvo
* src/update.c:
123
cb_toggled_show_notifications(GObject *self, void *data)
134 by mvo
* data/apt-check:
124
{
157 by mvo
* src/update.c:
125
      TrayApplet *ta = (TrayApplet*)data;
208 by Michael Vogt
* -Wall clean now
126
      UpdateTrayAppletPrivate *priv = (UpdateTrayAppletPrivate*)ta->user_data;
127
134 by mvo
* data/apt-check:
128
      gboolean b = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(self));
208 by Michael Vogt
* -Wall clean now
129
      gconf_client_set_bool(priv->gconf, GCONF_KEY_NO_UPDATE_NOTIFICATIONS, 
130
			    !b,NULL);
131
      
132
133
      NotifyNotification *n = priv->active_notification;
157 by mvo
* src/update.c:
134
      if(n != NULL) {
174 by mvo
* ported to the new libnotify API
135
	 notify_notification_close(n, NULL);
208 by Michael Vogt
* -Wall clean now
136
	 priv->active_notification = NULL;
157 by mvo
* src/update.c:
137
      }
134 by mvo
* data/apt-check:
138
}
139
140
45 by mvo
* added basic "interactive-update-hooks" support
141
void
59 by mvo
* debian/changelog: updated
142
update_trayicon_create_menu(TrayApplet *ta)
45 by mvo
* added basic "interactive-update-hooks" support
143
{
144
	GtkWidget *menuitem;
145
	int i;
146
59 by mvo
* debian/changelog: updated
147
	ta->menu = gtk_menu_new ();
45 by mvo
* added basic "interactive-update-hooks" support
148
149
	for(i=0;actions[i][0]!=NULL;i++) {
573 by Michael Vogt
merged from debian
150
	    if (!g_file_test(actions[i][2], G_FILE_TEST_EXISTS))
151
	        continue;
45 by mvo
* added basic "interactive-update-hooks" support
152
	   menuitem = gtk_menu_item_new_with_label (_(actions[i][1]));
573 by Michael Vogt
merged from debian
153
59 by mvo
* debian/changelog: updated
154
	   gtk_menu_shell_append (GTK_MENU_SHELL (ta->menu), menuitem);
208 by Michael Vogt
* -Wall clean now
155
	   g_object_set_data(G_OBJECT(menuitem), "action", GINT_TO_POINTER(i));
45 by mvo
* added basic "interactive-update-hooks" support
156
	   g_signal_connect(G_OBJECT(menuitem), "activate", 
59 by mvo
* debian/changelog: updated
157
			    G_CALLBACK(cb_action), ta);
45 by mvo
* added basic "interactive-update-hooks" support
158
	}
159
160
	menuitem = gtk_separator_menu_item_new();
59 by mvo
* debian/changelog: updated
161
	gtk_menu_shell_append (GTK_MENU_SHELL (ta->menu), menuitem);
45 by mvo
* added basic "interactive-update-hooks" support
162
134 by mvo
* data/apt-check:
163
	menuitem = gtk_check_menu_item_new_with_label(_("Show notifications"));
208 by Michael Vogt
* -Wall clean now
164
	UpdateTrayAppletPrivate *priv = (UpdateTrayAppletPrivate*)ta->user_data;
165
	gboolean b = gconf_client_get_bool(priv->gconf,
134 by mvo
* data/apt-check:
166
					   GCONF_KEY_NO_UPDATE_NOTIFICATIONS, 
167
					   NULL);
168
	gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem), !b);
169
	gtk_menu_shell_append (GTK_MENU_SHELL (ta->menu), menuitem);
170
	g_signal_connect(G_OBJECT(menuitem), "toggled", 
171
			 G_CALLBACK(cb_toggled_show_notifications), ta);
172
	
173
476 by Michael Vogt
fix -Wall errors
174
	menuitem = gtk_image_menu_item_new_from_stock (GTK_STOCK_PREFERENCES, NULL);
573 by Michael Vogt
merged from debian
175
	if (g_file_test("/usr/bin/software-properties-gtk", G_FILE_TEST_EXISTS))
176
	    gtk_menu_shell_append (GTK_MENU_SHELL (ta->menu), menuitem);
45 by mvo
* added basic "interactive-update-hooks" support
177
	g_signal_connect(G_OBJECT(menuitem), "activate", 
59 by mvo
* debian/changelog: updated
178
			 G_CALLBACK(cb_preferences), (void*)ta);
45 by mvo
* added basic "interactive-update-hooks" support
179
59 by mvo
* debian/changelog: updated
180
	gtk_widget_show_all (ta->menu);
45 by mvo
* added basic "interactive-update-hooks" support
181
}
182
94 by mvo
* src/update-notifier.c:
183
/* this tells the trayicon that apt is downloading something */
134 by mvo
* data/apt-check:
184
void 
185
update_apt_is_running(TrayApplet *ta, gboolean is_running)
94 by mvo
* src/update-notifier.c:
186
{
452 by Michael Vogt
rework the debug options and support --debug-inotify,
187
   g_debug_update("update_apt_is_running: %i\n",is_running);
437 by Michael Vogt
src/update.c: do not show the tray icon if apt is running in auto_launch mode
188
   if(ta == NULL)
189
      return;
190
448 by Michael Vogt
fix corner cases when the update icon still
191
   // update internal status
192
   UpdateTrayAppletPrivate *priv = (UpdateTrayAppletPrivate*)ta->user_data;
193
   priv->apt_is_running = is_running;
194
437 by Michael Vogt
src/update.c: do not show the tray icon if apt is running in auto_launch mode
195
   // if the user wants auto-launch mode, do not show the icon
196
   // the auto launch stuff will do its magic later
197
   if(gconf_client_get_bool(priv->gconf, GCONF_KEY_AUTO_LAUNCH, NULL))
198
      return;
208 by Michael Vogt
* -Wall clean now
199
351 by Michael Vogt
* use icon theme names "software-update-available" and
200
   if(is_running) {
356 by Michael Vogt
* src/update.c:
201
202
      // gray out the icon if apt is running, we do this only once,
203
      // after the first time, the storage_type changes from ICON_NAME to
204
      // IMAGE_PIXBUF
205
      if(gtk_status_icon_get_storage_type(ta->tray_icon) == GTK_IMAGE_ICON_NAME) {
206
	 GdkPixbuf *src = gtk_icon_theme_load_icon(gtk_icon_theme_get_default(),
207
						   gtk_status_icon_get_icon_name(ta->tray_icon),
208
						   gtk_status_icon_get_size(ta->tray_icon), 
209
						   0, 
210
						   NULL);
211
	 GdkPixbuf *inactive = gdk_pixbuf_copy(src);
212
	 gdk_pixbuf_saturate_and_pixelate(src, inactive, 0.0, FALSE);
213
	 gtk_status_icon_set_from_pixbuf(ta->tray_icon, inactive);
214
	 g_object_unref(src);
215
	 g_object_unref(inactive);
216
      }
217
218
      // and update the tooltip
219
      gtk_status_icon_set_tooltip(ta->tray_icon, _("A package manager is working"));
220
      // and show it
221
      gtk_status_icon_set_visible(ta->tray_icon, TRUE);
222
223
      if(priv->active_notification != NULL) {
224
	 notify_notification_close(priv->active_notification, NULL);
225
	 priv->active_notification = NULL;
226
      }
351 by Michael Vogt
* use icon theme names "software-update-available" and
227
   } else {
329 by Michael Vogt
* use GtkStatusIcon instead of EggTrayIcon, that makes
228
      gtk_status_icon_set_from_icon_name(ta->tray_icon, ta->name);
351 by Michael Vogt
* use icon theme names "software-update-available" and
229
   }
94 by mvo
* src/update-notifier.c:
230
}
231
132 by mvo
* src/update.c:
232
// actually show the notification 
178 by mvo
* merged the changes from scott
233
static gint 
134 by mvo
* data/apt-check:
234
show_notification(gpointer user_data)
132 by mvo
* src/update.c:
235
{
236
   TrayApplet *ta = (TrayApplet *)user_data;
208 by Michael Vogt
* -Wall clean now
237
   UpdateTrayAppletPrivate *priv = (UpdateTrayAppletPrivate*)ta->user_data;
238
239
   // apt is runing, no point in showing a notification
240
   if(priv->apt_is_running) 
241
      return TRUE;
132 by mvo
* src/update.c:
242
365 by Michael Vogt
* src/update.c, src/crash.c, src/hooks.c:
243
   // check if the update-icon is still visible (in the delay time a 
244
   // update may already have been performed)
245
   if(!gtk_status_icon_get_visible(ta->tray_icon))
246
      return FALSE;
247
329 by Michael Vogt
* use GtkStatusIcon instead of EggTrayIcon, that makes
248
   GdkRectangle area;
249
   gtk_status_icon_get_geometry(ta->tray_icon, NULL, &area, NULL);
132 by mvo
* src/update.c:
250
251
   // no usefull coordiante yet, do another timeout
329 by Michael Vogt
* use GtkStatusIcon instead of EggTrayIcon, that makes
252
   if(area.x <= 0 || area.y <= 0 || area.width <= 0 || area.height <= 0)
132 by mvo
* src/update.c:
253
      return TRUE;
254
144 by mvo
* debian/control:
255
   // now show a notification handle 
423 by Michael Vogt
* src/update.{cc,h}:
256
   gchar *updates;
257
   updates = g_strdup_printf(ngettext("There is %i update available. "
258
				      "Click on the notification "
259
				      "icon to show the "
260
				      "available update.",
261
				      "There are %i updates available. "
262
				      "Click on the notification "
263
				      "icon to show the "
264
				      "available updates.",
265
				      priv->num_upgrades), 
266
			     priv->num_upgrades);
329 by Michael Vogt
* use GtkStatusIcon instead of EggTrayIcon, that makes
267
   NotifyNotification *n = notify_notification_new_with_status_icon(
268
			      _("Software updates available"),
423 by Michael Vogt
* src/update.{cc,h}:
269
			      updates,
329 by Michael Vogt
* use GtkStatusIcon instead of EggTrayIcon, that makes
270
			      NULL, 
271
			      ta->tray_icon);
423 by Michael Vogt
* src/update.{cc,h}:
272
184 by mvo
* src/update.c:
273
   GdkPixbuf* pix= gtk_icon_theme_load_icon(gtk_icon_theme_get_default(), 
274
					    GTK_STOCK_DIALOG_INFO, 48,0,NULL);
275
   notify_notification_set_icon_from_pixbuf (n, pix);
276
   g_object_unref(pix);
174 by mvo
* ported to the new libnotify API
277
   notify_notification_set_timeout (n, 60*1000);
278
   notify_notification_show(n, NULL);
157 by mvo
* src/update.c:
279
   // save the notification handle
208 by Michael Vogt
* -Wall clean now
280
   priv->active_notification = n;
132 by mvo
* src/update.c:
281
282
   // remove this from the timeout now
423 by Michael Vogt
* src/update.{cc,h}:
283
   g_free(updates);
132 by mvo
* src/update.c:
284
   return FALSE;
285
}
286
352 by Michael Vogt
* show a warning icon if the last refresh of the
287
void 
288
show_error(TrayApplet *ta, gchar *error_str)
351 by Michael Vogt
* use icon theme names "software-update-available" and
289
{
290
   gtk_status_icon_set_tooltip(ta->tray_icon, error_str);
291
   gtk_status_icon_set_from_icon_name(ta->tray_icon, "dialog-error");
292
   gtk_status_icon_set_visible(ta->tray_icon, TRUE);
293
}
294
352 by Michael Vogt
* show a warning icon if the last refresh of the
295
static gboolean
296
outdated_nag(TrayApplet *ta)
297
{
298
   struct stat buf;
360 by Michael Vogt
* src/update.c, debian/15update-stamp:
299
   if ((stat("/var/lib/apt/periodic/update-success-stamp", &buf) == 0) &&
352 by Michael Vogt
* show a warning icon if the last refresh of the
300
       (time(NULL) - buf.st_mtime > OUTDATED_NAG_AGE) ) {
301
      gtk_status_icon_set_visible (ta->tray_icon, TRUE);
510 by Michael Vogt
* src/update.c:
302
      ta->name = "gtk-dialog-warning-panel";
303
      GdkPixbuf *src = gtk_icon_theme_load_icon(gtk_icon_theme_get_default(),
304
						ta->name, 48, 
305
						GTK_ICON_LOOKUP_GENERIC_FALLBACK, 
306
						NULL);
307
      gtk_status_icon_set_from_pixbuf(ta->tray_icon, src);
308
      g_object_unref(src);
352 by Michael Vogt
* show a warning icon if the last refresh of the
309
      gtk_status_icon_set_tooltip(ta->tray_icon,
310
				  _("The update information is outdated. "
311
				    "This may be caused by network "
373 by Michael Vogt
* src/update.c:
312
				    "problems or by a repository that "
313
				    "is no longer available. "
314
				    "Please update manually "
359 by Michael Vogt
* src/update.c:
315
				    "by clicking on this icon and then "
378 by Michael Vogt
wording fixes (LP: #254313), thanks to Gabor Kelemen
316
				    "selecting 'Check for updates' and "
317
				    "check if some of the listed "
318
				    "repositories fail."
352 by Michael Vogt
* show a warning icon if the last refresh of the
319
				 ));
320
   }
321
   return FALSE;
322
}
323
451 by Michael Vogt
* src/update.c:
324
// use ubuntu-system-service (if available) to check
325
// if the dpkg lock is taken currently or not
326
//
327
// if uncertain, return FALSE 
328
static gboolean
329
dpkg_lock_is_taken ()
330
{
331
   DBusGConnection *connection;
332
   GError *error;
333
   DBusGProxy *proxy;
334
   gboolean locked = FALSE;
335
  
336
   error = NULL;
337
   connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
338
   if (connection == NULL) {
452 by Michael Vogt
rework the debug options and support --debug-inotify,
339
      g_debug_update ("Failed to open connection to bus: %s\n", error->message);
451 by Michael Vogt
* src/update.c:
340
      g_error_free (error);
341
      return FALSE;
342
   }
343
344
  proxy = dbus_g_proxy_new_for_name (connection,
345
                                     "com.ubuntu.SystemService",
346
				     "/",
347
				     "com.ubuntu.SystemService");
348
  error = NULL;
349
  if (!dbus_g_proxy_call (proxy, "is_package_system_locked", &error, 
350
			  G_TYPE_INVALID,
351
                          G_TYPE_BOOLEAN, &locked, G_TYPE_INVALID)) {
452 by Michael Vogt
rework the debug options and support --debug-inotify,
352
     g_debug_update ("error during dbus call: %s\n", error->message);
451 by Michael Vogt
* src/update.c:
353
     g_error_free (error);
501 by Michael Vogt
- Fallback to HAL if possible to reboot (LP: #437333)
354
     g_object_unref (proxy);
451 by Michael Vogt
* src/update.c:
355
     return FALSE;
356
  }
501 by Michael Vogt
- Fallback to HAL if possible to reboot (LP: #437333)
357
  g_object_unref (proxy);
358
452 by Michael Vogt
rework the debug options and support --debug-inotify,
359
  g_debug_update ("is_package_system_locked: %i", locked);
451 by Michael Vogt
* src/update.c:
360
  return locked;
361
}
362
476 by Michael Vogt
fix -Wall errors
363
#if 0
470 by Michael Vogt
code cleanup, add auto_launch_security_now() method, add running_on_battery() method (not used right now)
364
// ask devicekit.Power if we run on battery
365
static gboolean
366
running_on_battery ()
367
{
368
   DBusGConnection *connection;
369
   GError *error;
370
   DBusGProxy *proxy;
371
   gboolean on_battery = FALSE;
372
  
373
   error = NULL;
374
   connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
375
   if (connection == NULL) {
376
      g_debug_update ("Failed to open connection to bus: %s\n", error->message);
377
      g_error_free (error);
378
      return FALSE;
379
   }
380
381
  proxy = dbus_g_proxy_new_for_name (connection,
382
				     "org.freedesktop.DeviceKit.Power", 
383
				     "/org/freedesktop/DeviceKit/Power",
384
				     "org.freedesktop.DBus.Properties");
385
  error = NULL;
386
  if (!dbus_g_proxy_call (proxy, "Get", &error, 
387
			  G_TYPE_STRING, "org.freedesktop.DeviceKit.Power", 
388
			  G_TYPE_STRING, "on_battery",
389
			  G_TYPE_INVALID,
390
                          G_TYPE_BOOLEAN, &on_battery, 
391
			  G_TYPE_INVALID)) {
392
     g_debug_update ("failed Get dbus call: %s\n", 
393
		     error?error->message:"no error given");
394
     if(error)
395
	g_error_free (error);
396
     return FALSE;
397
  }
398
  g_debug_update ("on_battery: %i", on_battery);
399
  return on_battery;
400
}
476 by Michael Vogt
fix -Wall errors
401
#endif
470 by Michael Vogt
code cleanup, add auto_launch_security_now() method, add running_on_battery() method (not used right now)
402
403
static gboolean
575 by Michael Vogt
src/update.c: move check for unattended-security-updates into its own function
404
security_updates_are_installed_unattended()
470 by Michael Vogt
code cleanup, add auto_launch_security_now() method, add running_on_battery() method (not used right now)
405
{
471 by Michael Vogt
when running in auto-launch mode, check if security
406
   int ret;
407
   GError *error = NULL;
408
409
   // run apt_check.py in "check if we install updates unattended" mode
410
   // a exit status > 0 indicates that its unattended-upgrades is used
411
   if ( g_file_test ("/usr/bin/unattended-upgrades", 
412
		     G_FILE_TEST_IS_EXECUTABLE) ) {
576 by Michael Vogt
* src/update.c:
413
      char *cmd[] = { "/usr/bin/nice",
414
		      "/usr/bin/ionice", "-c3",
415
		      UPGRADE_CHECKER, 
416
		      "--security-updates-unattended",	      
417
		      NULL };
418
471 by Michael Vogt
when running in auto-launch mode, check if security
419
      if (g_spawn_sync("/", cmd, NULL, 0, NULL, NULL, 
420
		       NULL, NULL, &ret, &error)) {
421
	 g_debug("--security-updates-unattended: %i\n", WEXITSTATUS(ret));
422
	 if( WEXITSTATUS(ret) > 0 )
575 by Michael Vogt
src/update.c: move check for unattended-security-updates into its own function
423
	    return TRUE;
471 by Michael Vogt
when running in auto-launch mode, check if security
424
      } else if (error) {
425
	 g_print("error: %s\n", error->message);
426
      }
427
   }
575 by Michael Vogt
src/update.c: move check for unattended-security-updates into its own function
428
   return FALSE;
429
}
430
431
// check if the security auto launch interval is over
432
// and if the user is not using auto install of security
433
// updates
434
static gboolean
435
auto_launch_security_now(UpdateTrayAppletPrivate *priv, 
436
			 time_t now, 
437
			 time_t last_launch)
438
{
439
440
   // no security updates
441
   if (priv->num_security == 0)
442
      return FALSE;
443
	 
444
   // security updates, but already launched recently
445
   if ((last_launch + AUTOLAUNCH_MINIMAL_SECURITY_INTERVAL) > now) {
446
      g_debug_update("security updates, but update-manager was launched "
447
		     "within the AUTOLAUNCH_MINIMAL_SECURITY_INTERVAL\n");
448
      return FALSE;
449
   }
450
   
451
   // if security updates are installed unattended, there is nothing
452
   // to do for us
453
   if (security_updates_are_installed_unattended())
454
      return FALSE;
471 by Michael Vogt
when running in auto-launch mode, check if security
455
470 by Michael Vogt
code cleanup, add auto_launch_security_now() method, add running_on_battery() method (not used right now)
456
   g_debug_update("security updates, auto-launching");
457
   return TRUE;
458
}
459
479 by Michael Vogt
when checking apt/dpkg logs, glob() for the old(er)
460
// check the logs of dpkg and apt for timestamps, the idea
461
// is to not auto launch if dpkg/apt were run manually by the
462
// user
463
static time_t
464
newest_log_file_timestamp()
465
{
466
   struct stat buf;
467
   int i, j;
468
   time_t newest_log_stamp = 0;
469
470
   char *log_glob[] = { "/var/log/dpkg.log*",
471
		    "/var/log/apt/term.log*",
472
		    NULL };
473
474
   for (i=0; log_glob[i] != NULL; i++) 
475
   {
476
      glob_t pglob;
477
      if(glob(log_glob[i], 0, NULL, &pglob) != 0) {
478
	 g_warning("error from glob %s\n", log_glob[i]);
479
	 continue;
480
      }
481
      for(j=0;j < pglob.gl_pathc; j++) {
482
483
	 const char *log = pglob.gl_pathv[j];
484
	 if(g_stat(log, &buf) <0) {
485
	    g_warning("can't stat %s\n", log);
486
	    continue;
487
	 }
488
	 if(buf.st_size == 0) {
489
	    g_warning("log file empty (logrotate?) %s\n", log);
490
	    continue;
491
	 }
492
	 time_t mtime = buf.st_mtime;
493
	 g_debug_update ("mtime from %s: %i (%s)\n", log, mtime, ctime(&mtime));
494
	 time_t bctime = buf.st_ctime;
495
	 g_debug_update ("ctime from %s: %i (%s)\n", log, bctime, ctime(&bctime));
496
	 newest_log_stamp = MAX(MAX(mtime, bctime), newest_log_stamp);
497
	 g_debug_update ("last_launch from %s: %i (%s)\n", log, newest_log_stamp, ctime(&newest_log_stamp));
498
      }
499
      globfree(&pglob);
500
   }
501
   return newest_log_stamp;
502
}
503
443 by Michael Vogt
* src/update.c:
504
// check if the auto launch interval is over and its 
451 by Michael Vogt
* src/update.c:
505
// time to launch again and if the dpkg lock is currently 
506
// not taken
432 by Michael Vogt
add "/apps/update-notifier/regular_auto_launch_interval" gconf
507
static gboolean 
508
auto_launch_now (UpdateTrayAppletPrivate *priv)
509
{
510
   int interval_days = 0;
476 by Michael Vogt
fix -Wall errors
511
   time_t last_launch = 0;
432 by Michael Vogt
add "/apps/update-notifier/regular_auto_launch_interval" gconf
512
451 by Michael Vogt
* src/update.c:
513
   if (dpkg_lock_is_taken())
514
      return FALSE;
515
470 by Michael Vogt
code cleanup, add auto_launch_security_now() method, add running_on_battery() method (not used right now)
516
#if 0 // disabled because we need more cleverness here in order to cover
517
      // the case where people always work on battery (and charge overnight)
518
   if (running_on_battery())
519
      return FALSE;
520
#endif
521
432 by Michael Vogt
add "/apps/update-notifier/regular_auto_launch_interval" gconf
522
   // when checking for regular updates honor the 
523
   // regular_auto_launch_interval
524
   interval_days = gconf_client_get_int(priv->gconf,
525
					GCONF_KEY_AUTO_LAUNCH_INTERVAL, 
526
					NULL);
452 by Michael Vogt
rework the debug options and support --debug-inotify,
527
   g_debug_update ("interval_days from gconf: %i\n", interval_days);
445 by Michael Vogt
* src/update-notifier.c:
528
432 by Michael Vogt
add "/apps/update-notifier/regular_auto_launch_interval" gconf
529
   if (interval_days <= 0) 
530
      return TRUE;
531
443 by Michael Vogt
* src/update.c:
532
   // check last launch time 
432 by Michael Vogt
add "/apps/update-notifier/regular_auto_launch_interval" gconf
533
   last_launch = gconf_client_get_int(priv->gconf,
446 by Michael Vogt
use the gconf /apps/update-manager/launch_time key
534
				      GCONF_KEY_LAST_LAUNCH,
432 by Michael Vogt
add "/apps/update-notifier/regular_auto_launch_interval" gconf
535
				      NULL);
457 by Michael Vogt
* src/update.c:
536
   g_debug_update ("last_launch from gconf: %i (%s)\n", last_launch, ctime(&last_launch));
443 by Michael Vogt
* src/update.c:
537
460 by Michael Vogt
add AUTOLAUNCH_MINIMAL_SECURITY_INTERVAL (LP: #369198)
538
   time_t now = time(NULL);
470 by Michael Vogt
code cleanup, add auto_launch_security_now() method, add running_on_battery() method (not used right now)
539
   if (auto_launch_security_now(priv, now, last_launch))
540
      return TRUE;
460 by Michael Vogt
add AUTOLAUNCH_MINIMAL_SECURITY_INTERVAL (LP: #369198)
541
479 by Michael Vogt
when checking apt/dpkg logs, glob() for the old(er)
542
   time_t log_files = newest_log_file_timestamp();
543
   last_launch = MAX(log_files, last_launch);
443 by Michael Vogt
* src/update.c:
544
457 by Michael Vogt
* src/update.c:
545
   g_debug_update("time now %i (%s), delta: %i", now, ctime(&now), now-last_launch);
546
   if ((last_launch + (24*60*60*interval_days)) < now) {
452 by Michael Vogt
rework the debug options and support --debug-inotify,
547
      g_debug_update ("need to auto launch");
432 by Michael Vogt
add "/apps/update-notifier/regular_auto_launch_interval" gconf
548
      return TRUE;
445 by Michael Vogt
* src/update-notifier.c:
549
   }
550
432 by Michael Vogt
add "/apps/update-notifier/regular_auto_launch_interval" gconf
551
   return FALSE;
552
}
553
45 by mvo
* added basic "interactive-update-hooks" support
554
gboolean
555
update_check (TrayApplet *ta)
556
{
386 by Michael Vogt
* src/update.c, src/update-notifier.c:
557
   if(ta == NULL)
558
      return FALSE;
559
452 by Michael Vogt
rework the debug options and support --debug-inotify,
560
   g_debug_update ("update_check()\n");
208 by Michael Vogt
* -Wall clean now
561
   UpdateTrayAppletPrivate *priv = (UpdateTrayAppletPrivate*)ta->user_data;
132 by mvo
* src/update.c:
562
423 by Michael Vogt
* src/update.{cc,h}:
563
   priv->num_upgrades = 0;
564
   priv->num_security = 0;
97 by mvo
* debian/changelog:
565
   int exit_status = 0;
589 by Michael Vogt
* src/update.c:
566
   GError *error = NULL;
97 by mvo
* debian/changelog:
567
576 by Michael Vogt
* src/update.c:
568
   char *cmd[] = { "/usr/bin/nice",
569
		   "/usr/bin/ionice", "-c3",
570
		   UPGRADE_CHECKER, 
571
		   NULL };
104 by mvo
* data/apt-check, src/update.c:
572
   char *ret;
97 by mvo
* debian/changelog:
573
574
   if(g_spawn_sync(NULL, cmd, NULL,  
575
		   G_SPAWN_STDOUT_TO_DEV_NULL, 
104 by mvo
* data/apt-check, src/update.c:
576
		   NULL, NULL, NULL, &ret,
577
		   &exit_status, &error)) {
359.1.1 by Michael Vogt
- do not display a error when running on the live-cd
578
579
      // check if we are running from the live-cd, it
580
      // symlinks apt-check to /bin/true
581
      if(exit_status == 0 && strlen(ret) == 0 &&
582
	 g_file_test (UPGRADE_CHECKER, G_FILE_TEST_IS_SYMLINK) ) {
583
	 g_free(ret);
584
	 return TRUE;
585
      }
586
130 by mvo
* report cache errors to the user
587
      // read the value from childs stderr, E: indicates a problem
588
      if(ret[0] == 'E') {
356 by Michael Vogt
* src/update.c:
589
	 GString *error = g_string_new("");
222 by Michael Vogt
* report errors from apt-check to the frontend
590
	 if(strlen(ret) > 3) 
351 by Michael Vogt
* use icon theme names "software-update-available" and
591
	    g_string_append_printf(error,
592
				   _("An error occurred, please run "
222 by Michael Vogt
* report errors from apt-check to the frontend
593
				      "Package Manager from the "
320 by Michael Vogt
* fix spelling mistakes (LP#64485)
594
				      "right-click menu or apt-get in "
222 by Michael Vogt
* report errors from apt-check to the frontend
595
				      "a terminal to see what is wrong.\n"
617.1.1 by Brian Murray
The text "This usually means" is always appended so add in a space and a period to ensure proper punctuation
596
				      "The error message was: '%s'. "),
222 by Michael Vogt
* report errors from apt-check to the frontend
597
				    &ret[2]);
598
	 else
352 by Michael Vogt
* show a warning icon if the last refresh of the
599
	    g_string_append(error, _("An error occurred, please run "
222 by Michael Vogt
* report errors from apt-check to the frontend
600
				      "Package Manager from the "
320 by Michael Vogt
* fix spelling mistakes (LP#64485)
601
				      "right-click menu or apt-get in "
222 by Michael Vogt
* report errors from apt-check to the frontend
602
				      "a terminal to see what is wrong."));
352 by Michael Vogt
* show a warning icon if the last refresh of the
603
	 g_string_append(error, _("This usually means that your installed "
351 by Michael Vogt
* use icon theme names "software-update-available" and
604
				    "packages have unmet dependencies"));
605
	 show_error(ta, error->str);
606
	 g_string_free(error, TRUE);
130 by mvo
* report cache errors to the user
607
	 g_free(ret);
608
	 return TRUE;
609
	 
351 by Michael Vogt
* use icon theme names "software-update-available" and
610
      }
352 by Michael Vogt
* show a warning icon if the last refresh of the
611
351 by Michael Vogt
* use icon theme names "software-update-available" and
612
      // we get "number_of_upgrades;number_of_security_upgrades" 
613
      // (e.g. "15;2")
614
      gchar **ret_array = g_strsplit(ret, ";", 2);
615
      if(g_strv_length(ret_array) < 2)  {
362 by Michael Vogt
finialize as 0.70.4
616
	 show_error(ta, _("A problem occurred when checking for the updates."));
351 by Michael Vogt
* use icon theme names "software-update-available" and
617
 	 g_free(ret);
618
	 g_strfreev(ret_array);
619
	 return TRUE;
620
      }
423 by Michael Vogt
* src/update.{cc,h}:
621
      priv->num_upgrades = atoi(ret_array[0]);
622
      priv->num_security = atoi(ret_array[1]);
104 by mvo
* data/apt-check, src/update.c:
623
      g_free(ret);
351 by Michael Vogt
* use icon theme names "software-update-available" and
624
      g_strfreev(ret_array);
104 by mvo
* data/apt-check, src/update.c:
625
   } else
97 by mvo
* debian/changelog:
626
      g_warning("Error launching %s", UPGRADE_CHECKER);
45 by mvo
* added basic "interactive-update-hooks" support
627
   
461 by Michael Vogt
remove some debug output
628
   g_debug_update("%s returned %i (security: %i)", UPGRADE_CHECKER, priv->num_upgrades, priv->num_security);
453 by Michael Vogt
update.c: better debug, debian/control: add suggests to ubuntu-system-servce
629
423 by Michael Vogt
* src/update.{cc,h}:
630
   if (priv->num_upgrades == 0) {
352 by Michael Vogt
* show a warning icon if the last refresh of the
631
632
      // check if the periodic file is very old
633
      struct stat buf;
360 by Michael Vogt
* src/update.c, debian/15update-stamp:
634
      if ((stat("/var/lib/apt/periodic/update-success-stamp", &buf) == 0) &&
352 by Michael Vogt
* show a warning icon if the last refresh of the
635
	  (time(NULL) - buf.st_mtime > OUTDATED_NAG_AGE) ) 
476 by Michael Vogt
fix -Wall errors
636
	 g_timeout_add_seconds(OUTDATED_NAG_WAIT, (GSourceFunc)outdated_nag, ta);
352 by Michael Vogt
* show a warning icon if the last refresh of the
637
331 by Michael Vogt
src/update.c:
638
      gtk_status_icon_set_visible (ta->tray_icon, FALSE);
208 by Michael Vogt
* -Wall clean now
639
      
640
      if(priv->active_notification != NULL) {
641
	 notify_notification_close(priv->active_notification, NULL);
642
	 priv->active_notification = NULL; 
157 by mvo
* src/update.c:
643
      }
131 by mvo
* debian/control:
644
      return TRUE;
645
   } 
646
423 by Michael Vogt
* src/update.{cc,h}:
647
   if (priv->num_security == 0)
351 by Michael Vogt
* use icon theme names "software-update-available" and
648
      ta->name = "software-update-available";
649
   else
650
      ta->name = "software-update-urgent";
651
   gtk_status_icon_set_from_icon_name(ta->tray_icon, ta->name);
652
341 by Michael Vogt
* fix incorrect tooltip when package manager was
653
   // update the tooltip
423 by Michael Vogt
* src/update.{cc,h}:
654
   update_trayicon_update_tooltip(ta, priv->num_upgrades);
341 by Michael Vogt
* fix incorrect tooltip when package manager was
655
448 by Michael Vogt
fix corner cases when the update icon still
656
   // check if the user wants to see the icon or launch
657
   // the default action
658
   if(gconf_client_get_bool(priv->gconf,
659
			    GCONF_KEY_AUTO_LAUNCH, NULL)) 
660
   {
661
      gtk_status_icon_set_visible(ta->tray_icon, FALSE);
662
      if (auto_launch_now(priv)) 
663
      {
664
	 g_spawn_command_line_async("nice ionice -c3 update-manager "
665
				    "--no-focus-on-map", NULL);
666
      }
667
      return TRUE;
668
   }
669
334 by Michael Vogt
* fix crash in leftover from pre-GtkStatusIcon code (LP: #127965)
670
   // if we are already visible, skip the rest
671
   if(gtk_status_icon_get_visible (ta->tray_icon))
672
      return TRUE;
673
448 by Michael Vogt
fix corner cases when the update icon still
674
   // show the icon
675
   gtk_status_icon_set_visible(ta->tray_icon, TRUE);
676
   
677
   // the user does not no notification messages
208 by Michael Vogt
* -Wall clean now
678
   if(gconf_client_get_bool(priv->gconf,
448 by Michael Vogt
fix corner cases when the update icon still
679
			    GCONF_KEY_NO_UPDATE_NOTIFICATIONS, NULL))
680
      return TRUE;
681
682
   // show the notification with some delay. otherwise on a login
683
   // the origin of the window is 0,0 and that looks ugly
563 by Michael Vogt
src/update.c: use g_timeout_add_seconds instead of g_timeout_add
684
   g_timeout_add_seconds(5, show_notification, ta);
448 by Michael Vogt
fix corner cases when the update icon still
685
45 by mvo
* added basic "interactive-update-hooks" support
686
   return TRUE;
687
}
688
689
134 by mvo
* data/apt-check:
690
void 
691
update_tray_icon_init(TrayApplet *ta)
45 by mvo
* added basic "interactive-update-hooks" support
692
{
208 by Michael Vogt
* -Wall clean now
693
   // create the private data struct
694
   UpdateTrayAppletPrivate *priv = g_new0(UpdateTrayAppletPrivate, 1);
695
   priv->gconf = gconf_client_get_default();
696
   priv->apt_is_running = FALSE;
697
   priv->active_notification = NULL;
698
   ta->user_data = priv;
699
700
   // connect the signals we need
701
   g_signal_connect (G_OBJECT(ta->tray_icon),
329 by Michael Vogt
* use GtkStatusIcon instead of EggTrayIcon, that makes
702
		     "activate",
703
		     G_CALLBACK (activate_cb),
208 by Michael Vogt
* -Wall clean now
704
		     ta);
705
   g_signal_connect (G_OBJECT(ta->tray_icon),
329 by Michael Vogt
* use GtkStatusIcon instead of EggTrayIcon, that makes
706
		     "popup-menu",
707
		     G_CALLBACK (popup_cb),
208 by Michael Vogt
* -Wall clean now
708
		     ta);
709
710
   /* Menu initialization */
711
   update_trayicon_create_menu (ta);
712
   
713
   /* Check for updates for the first time */
714
   update_check (ta);
45 by mvo
* added basic "interactive-update-hooks" support
715
}