~ubuntu-branches/ubuntu/utopic/xfce4-power-manager/utopic-proposed

« back to all changes in this revision

Viewing changes to .pc/0001-Solaris-specific-code-for-determining-the-start-time.patch/src/xfpm-polkit.c

  • Committer: Package Import Robot
  • Author(s): Lionel Le Folgoc
  • Date: 2012-04-03 22:15:05 UTC
  • mfrom: (2.3.8)
  • Revision ID: package-import@ubuntu.com-20120403221505-2dvza7w2d97zb7qn
Tags: 1.0.11-0ubuntu1
* New upstream bugfix release.
* debian/patches:
  - 0001-Solaris-specific-code-for-determining-the-start-time.patch,
    02_fix-notify-detect.patch,
    07_fix_broken_empty_icon_battery.patch: dropped, included upstream.
  - xubuntu_fix-status-icon-other-devices.patch: refreshed to apply cleanly.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * * Copyright (C) 2009-2011 Ali <aliov@xfce.org>
3
 
 *
4
 
 * Licensed under the GNU General Public License Version 2
5
 
 *
6
 
 * This program is free software; you can redistribute it and/or modify
7
 
 * it under the terms of the GNU General Public License as published by
8
 
 * the Free Software Foundation; either version 2 of the License, or
9
 
 * (at your option) any later version.
10
 
 *
11
 
 * This program is distributed in the hope that it will be useful,
12
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 
 * GNU General Public License for more details.
15
 
 *
16
 
 * You should have received a copy of the GNU General Public License
17
 
 * along with this program; if not, write to the Free Software
18
 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19
 
 */
20
 
 
21
 
#ifdef HAVE_CONFIG_H
22
 
#include <config.h>
23
 
#endif
24
 
 
25
 
#include <stdio.h>
26
 
#include <stdlib.h>
27
 
#include <string.h>
28
 
 
29
 
#ifdef HAVE_UNISTD_H
30
 
#include <unistd.h>
31
 
#endif
32
 
 
33
 
#include <sys/types.h>
34
 
 
35
 
#if defined(__FreeBSD__)
36
 
#include <sys/stat.h>
37
 
#else
38
 
#include <sys/param.h>
39
 
#include <sys/sysctl.h>
40
 
#include <sys/user.h>
41
 
#endif
42
 
 
43
 
#include <errno.h>
44
 
 
45
 
#include <dbus/dbus-glib.h>
46
 
 
47
 
#include "xfpm-polkit.h"
48
 
#include "xfpm-debug.h"
49
 
 
50
 
#include "xfpm-common.h"
51
 
 
52
 
static void xfpm_polkit_finalize   (GObject *object);
53
 
 
54
 
#define XFPM_POLKIT_GET_PRIVATE(o) \
55
 
(G_TYPE_INSTANCE_GET_PRIVATE ((o), XFPM_TYPE_POLKIT, XfpmPolkitPrivate))
56
 
 
57
 
struct XfpmPolkitPrivate
58
 
{
59
 
    DBusGConnection   *bus;
60
 
 
61
 
#ifdef ENABLE_POLKIT
62
 
    DBusGProxy        *proxy;
63
 
    GValueArray       *subject;
64
 
    GHashTable        *details;
65
 
    GHashTable        *subject_hash;
66
 
 
67
 
    GType              subject_gtype;
68
 
    GType              details_gtype;
69
 
    GType              result_gtype;
70
 
 
71
 
    gulong             destroy_id;
72
 
    gboolean           subject_valid;
73
 
#endif
74
 
};
75
 
 
76
 
enum
77
 
{
78
 
    AUTH_CHANGED,
79
 
    LAST_SIGNAL
80
 
};
81
 
 
82
 
static guint signals [LAST_SIGNAL] = { 0 };
83
 
 
84
 
G_DEFINE_TYPE (XfpmPolkit, xfpm_polkit, G_TYPE_OBJECT)
85
 
 
86
 
#ifdef ENABLE_POLKIT
87
 
#if defined(__FreeBSD__)
88
 
/**
89
 
 * Taken from polkitunixprocess.c code to get process start
90
 
 * time from pid.
91
 
 *
92
 
 * Copyright (C) 2008 Red Hat, Inc.
93
 
 *
94
 
 **/
95
 
static gboolean
96
 
get_kinfo_proc (pid_t pid, struct kinfo_proc *p)
97
 
{
98
 
    int mib[4];
99
 
    size_t len;
100
 
    
101
 
    len = 4;
102
 
    sysctlnametomib ("kern.proc.pid", mib, &len);
103
 
    
104
 
    len = sizeof (struct kinfo_proc);
105
 
    mib[3] = pid;
106
 
    
107
 
    if (sysctl (mib, 4, p, &len, NULL, 0) == -1)
108
 
        return FALSE;
109
 
 
110
 
    return TRUE;
111
 
}
112
 
#endif /*if defined(__FreeBSD__)*/
113
 
 
114
 
static guint64
115
 
get_start_time_for_pid (pid_t pid)
116
 
{
117
 
    guint64 start_time;
118
 
#if !defined(__FreeBSD__)
119
 
    gchar *filename;
120
 
    gchar *contents;
121
 
    size_t length;
122
 
    gchar **tokens;
123
 
    guint num_tokens;
124
 
    gchar *p;
125
 
    gchar *endp;
126
 
  
127
 
    start_time = 0;
128
 
    contents = NULL;
129
 
    
130
 
    filename = g_strdup_printf ("/proc/%d/stat", pid);
131
 
    
132
 
    if (!g_file_get_contents (filename, &contents, &length, NULL))
133
 
        goto out;
134
 
 
135
 
    /* start time is the token at index 19 after the '(process name)' entry - since only this
136
 
     * field can contain the ')' character, search backwards for this to avoid malicious
137
 
     * processes trying to fool us
138
 
     */
139
 
    p = strrchr (contents, ')');
140
 
    if (p == NULL)
141
 
    {
142
 
        goto out;
143
 
    }
144
 
    
145
 
    p += 2; /* skip ') ' */
146
 
 
147
 
    if (p - contents >= (int) length)
148
 
    {
149
 
        g_warning ("Error parsing file %s", filename);
150
 
        goto out;
151
 
    }
152
 
    
153
 
    tokens = g_strsplit (p, " ", 0);
154
 
    
155
 
    num_tokens = g_strv_length (tokens);
156
 
    
157
 
    if (num_tokens < 20)
158
 
    {
159
 
        g_warning ("Error parsing file %s", filename);
160
 
        goto out;
161
 
    }
162
 
 
163
 
    start_time = strtoull (tokens[19], &endp, 10);
164
 
    if (endp == tokens[19])
165
 
    {
166
 
        g_warning ("Error parsing file %s", filename);
167
 
        goto out;
168
 
    }
169
 
    g_strfreev (tokens);
170
 
 
171
 
 out:
172
 
    g_free (filename);
173
 
    g_free (contents);
174
 
    
175
 
#else /*if !defined(__FreeBSD__)*/
176
 
 
177
 
    struct kinfo_proc p;
178
 
    
179
 
    start_time = 0;
180
 
 
181
 
    if (! get_kinfo_proc (pid, &p))
182
 
    {
183
 
        g_warning ("Error obtaining start time for %d (%s)",
184
 
                   (gint) pid,
185
 
                   g_strerror (errno));
186
 
        goto out;
187
 
    }
188
 
 
189
 
    start_time = (guint64) p.ki_start.tv_sec;
190
 
    
191
 
out:
192
 
#endif
193
 
    
194
 
    return start_time;
195
 
}
196
 
#endif /*ENABLE_POLKIT*/
197
 
 
198
 
 
199
 
#ifdef ENABLE_POLKIT
200
 
static gboolean
201
 
xfpm_polkit_free_data (gpointer data)
202
 
{
203
 
    XfpmPolkit *polkit;
204
 
    
205
 
    polkit = XFPM_POLKIT (data);
206
 
 
207
 
    g_assert (polkit->priv->subject_valid);
208
 
 
209
 
    XFPM_DEBUG ("Destroying Polkit data");
210
 
 
211
 
    g_hash_table_destroy (polkit->priv->details);
212
 
    g_hash_table_destroy (polkit->priv->subject_hash);
213
 
    g_value_array_free   (polkit->priv->subject);
214
 
    
215
 
    polkit->priv->details      = NULL;
216
 
    polkit->priv->subject_hash = NULL;
217
 
    polkit->priv->subject      = NULL;
218
 
 
219
 
    polkit->priv->destroy_id = 0;
220
 
    polkit->priv->subject_valid = FALSE;
221
 
    
222
 
    return FALSE;
223
 
}
224
 
 
225
 
static void
226
 
xfpm_polkit_init_data (XfpmPolkit *polkit)
227
 
{
228
 
    //const gchar *consolekit_cookie;
229
 
    GValue hash_elem = { 0 };
230
 
    //gboolean subject_created = FALSE;
231
 
 
232
 
    if (polkit->priv->subject_valid)
233
 
        return;
234
 
    
235
 
    /**
236
 
     * This variable should be set by the session manager or by 
237
 
     * the login manager (gdm?). under clean Xfce environment
238
 
     * it is set by the session manager (4.8 and above)  
239
 
     * since we don't have a login manager, yet!
240
 
     **/
241
 
     /*
242
 
      * 
243
 
      * Disable for the moment
244
 
      * 
245
 
    consolekit_cookie = g_getenv ("XDG_SESSION_COOKIE");
246
 
  
247
 
    if ( consolekit_cookie )
248
 
    {
249
 
        DBusGProxy *proxy;
250
 
        GError *error = NULL;
251
 
        gboolean ret;
252
 
        gchar *consolekit_session;
253
 
        
254
 
        proxy  = dbus_g_proxy_new_for_name_owner (polkit->priv->bus,
255
 
                                                  "org.freedesktop.ConsoleKit",
256
 
                                                  "/org/freedesktop/ConsoleKit/Manager",
257
 
                                                  "org.freedesktop.ConsoleKit.Manager",
258
 
                                                  NULL);
259
 
 
260
 
        if ( proxy )
261
 
        {
262
 
            ret = dbus_g_proxy_call (proxy, "GetSessionForCookie", &error,
263
 
                                     G_TYPE_STRING, consolekit_cookie,
264
 
                                     G_TYPE_INVALID,
265
 
                                     DBUS_TYPE_G_OBJECT_PATH, &consolekit_session,
266
 
                                     G_TYPE_INVALID);
267
 
            
268
 
            if ( G_LIKELY (ret) )
269
 
            {
270
 
                GValue val  = { 0 };
271
 
                
272
 
                polkit->priv->subject = g_value_array_new (2);
273
 
                polkit->priv->subject_hash = g_hash_table_new_full (g_str_hash, 
274
 
                                                                    g_str_equal, 
275
 
                                                                    g_free, 
276
 
                                                                    NULL);
277
 
                g_value_init (&val, G_TYPE_STRING);
278
 
                g_value_set_string (&val, "unix-session");
279
 
                g_value_array_append (polkit->priv->subject, &val);
280
 
                
281
 
                g_value_unset (&val);
282
 
                g_value_init (&val, G_TYPE_STRING);
283
 
                g_value_set_string (&val, consolekit_session);
284
 
                
285
 
                g_hash_table_insert (polkit->priv->subject_hash, 
286
 
                                     g_strdup ("session-id"), 
287
 
                                     &val);
288
 
                
289
 
                g_free (consolekit_session);
290
 
                XFPM_DEBUG ("Using ConsoleKit session Polkit subject");
291
 
                subject_created = TRUE;
292
 
            }
293
 
            g_object_unref (proxy);
294
 
        }
295
 
        else if (error)
296
 
        {
297
 
            g_warning ("'GetSessionForCookie' failed : %s", error->message);
298
 
            g_error_free (error);
299
 
        }
300
 
        
301
 
    }
302
 
    */
303
 
    
304
 
    //if ( subject_created == FALSE )
305
 
    {
306
 
        gint pid;
307
 
        guint64 start_time;
308
 
    
309
 
        pid = getpid ();
310
 
        
311
 
        start_time = get_start_time_for_pid (pid);
312
 
        
313
 
        if ( G_LIKELY (start_time != 0 ) )
314
 
        {
315
 
            GValue val = { 0 }, pid_val = { 0 }, start_time_val = { 0 };
316
 
            
317
 
            polkit->priv->subject = g_value_array_new (2);
318
 
            polkit->priv->subject_hash = g_hash_table_new_full (g_str_hash, 
319
 
                                                                g_str_equal, 
320
 
                                                                g_free, 
321
 
                                                                NULL);
322
 
        
323
 
            g_value_init (&val, G_TYPE_STRING);
324
 
            g_value_set_string (&val, "unix-process");
325
 
            g_value_array_append (polkit->priv->subject, &val);
326
 
            
327
 
            g_value_unset (&val);
328
 
            
329
 
            g_value_init (&pid_val, G_TYPE_UINT);
330
 
            g_value_set_uint (&pid_val, pid);
331
 
            g_hash_table_insert (polkit->priv->subject_hash, 
332
 
                                 g_strdup ("pid"), &pid_val);
333
 
            
334
 
            g_value_init (&start_time_val, G_TYPE_UINT64);
335
 
            g_value_set_uint64 (&start_time_val, start_time);
336
 
            g_hash_table_insert (polkit->priv->subject_hash, 
337
 
                                 g_strdup ("start-time"), &start_time_val);
338
 
            
339
 
            XFPM_DEBUG ("Using unix session polkit subject");
340
 
        }
341
 
        else
342
 
        {
343
 
            g_warning ("Unable to create polkit subject");
344
 
        }
345
 
    }
346
 
    
347
 
    g_value_init (&hash_elem, 
348
 
                  dbus_g_type_get_map ("GHashTable", 
349
 
                                       G_TYPE_STRING, 
350
 
                                       G_TYPE_VALUE));
351
 
    
352
 
    g_value_set_static_boxed (&hash_elem, polkit->priv->subject_hash);
353
 
    g_value_array_append (polkit->priv->subject, &hash_elem);
354
 
    
355
 
    /**
356
 
     * Polkit details, will leave it empty.
357
 
     **/
358
 
    polkit->priv->details = g_hash_table_new_full (g_str_hash, 
359
 
                                                   g_str_equal, 
360
 
                                                   g_free, 
361
 
                                                   g_free);
362
 
    
363
 
    /*Clean these data after 1 minute*/
364
 
    polkit->priv->destroy_id = 
365
 
        g_timeout_add_seconds (60, (GSourceFunc) xfpm_polkit_free_data, polkit);
366
 
    
367
 
    polkit->priv->subject_valid = TRUE;
368
 
}
369
 
#endif /*ENABLE_POLKIT*/
370
 
 
371
 
static gboolean
372
 
xfpm_polkit_check_auth_intern (XfpmPolkit *polkit, const gchar *action_id)
373
 
{
374
 
#ifdef ENABLE_POLKIT
375
 
    GValueArray *result;
376
 
    GValue result_val = { 0 };
377
 
    GError *error = NULL;
378
 
    gboolean is_authorized = FALSE;
379
 
    gboolean ret;
380
 
    
381
 
    /**
382
 
     * <method name="CheckAuthorization">      
383
 
     *   <arg type="(sa{sv})" name="subject" direction="in"/>      
384
 
     *   <arg type="s" name="action_id" direction="in"/>           
385
 
     *   <arg type="a{ss}" name="details" direction="in"/>         
386
 
     *   <arg type="u" name="flags" direction="in"/>               
387
 
     *   <arg type="s" name="cancellation_id" direction="in"/>     
388
 
     *   <arg type="(bba{ss})" name="result" direction="out"/>     
389
 
     * </method>
390
 
     *
391
 
     **/
392
 
    
393
 
    g_return_val_if_fail (polkit->priv->proxy != NULL, FALSE);
394
 
    g_return_val_if_fail (polkit->priv->subject_valid, FALSE);
395
 
     
396
 
    result = g_value_array_new (0);
397
 
    
398
 
    ret = dbus_g_proxy_call (polkit->priv->proxy, "CheckAuthorization", &error,
399
 
                             polkit->priv->subject_gtype, polkit->priv->subject,
400
 
                             G_TYPE_STRING, action_id,
401
 
                             polkit->priv->details_gtype, polkit->priv->details,
402
 
                             G_TYPE_UINT, 0, 
403
 
                             G_TYPE_STRING, NULL,
404
 
                             G_TYPE_INVALID,
405
 
                             polkit->priv->result_gtype, &result,
406
 
                             G_TYPE_INVALID);
407
 
    
408
 
    if ( G_LIKELY (ret) )
409
 
    {
410
 
        g_value_init (&result_val, polkit->priv->result_gtype);
411
 
        g_value_set_static_boxed (&result_val, result);
412
 
        
413
 
        dbus_g_type_struct_get (&result_val,
414
 
                                0, &is_authorized,
415
 
                                G_MAXUINT);
416
 
        g_value_unset (&result_val);
417
 
    }
418
 
    else if ( error )
419
 
    {
420
 
        g_warning ("'CheckAuthorization' failed with %s", error->message);
421
 
        g_error_free (error);
422
 
    }
423
 
 
424
 
    g_value_array_free (result);
425
 
    
426
 
    XFPM_DEBUG ("Action=%s is authorized=%s", action_id, xfpm_bool_to_string (is_authorized));
427
 
    
428
 
    return is_authorized;
429
 
#endif /*ENABLE_POLKIT*/
430
 
    return TRUE;
431
 
}
432
 
 
433
 
#ifdef ENABLE_POLKIT
434
 
static void
435
 
xfpm_polkit_changed_cb (DBusGProxy *proxy, XfpmPolkit *polkit)
436
 
{
437
 
    XFPM_DEBUG ("Auth changed");
438
 
    g_signal_emit (G_OBJECT (polkit), signals [AUTH_CHANGED], 0);
439
 
}
440
 
#endif
441
 
 
442
 
static void
443
 
xfpm_polkit_class_init (XfpmPolkitClass *klass)
444
 
{
445
 
    GObjectClass *object_class = G_OBJECT_CLASS (klass);
446
 
 
447
 
    object_class->finalize = xfpm_polkit_finalize;
448
 
 
449
 
    signals [AUTH_CHANGED] = 
450
 
        g_signal_new ("auth-changed",
451
 
                      XFPM_TYPE_POLKIT,
452
 
                      G_SIGNAL_RUN_LAST,
453
 
                      G_STRUCT_OFFSET(XfpmPolkitClass, auth_changed),
454
 
                      NULL, NULL,
455
 
                      g_cclosure_marshal_VOID__VOID,
456
 
                      G_TYPE_NONE, 0, G_TYPE_NONE);
457
 
 
458
 
    g_type_class_add_private (klass, sizeof (XfpmPolkitPrivate));
459
 
}
460
 
 
461
 
static void
462
 
xfpm_polkit_init (XfpmPolkit *polkit)
463
 
{
464
 
    GError *error = NULL;
465
 
    
466
 
    polkit->priv = XFPM_POLKIT_GET_PRIVATE (polkit);
467
 
 
468
 
#ifdef ENABLE_POLKIT
469
 
    polkit->priv->destroy_id   = 0;
470
 
    polkit->priv->subject_valid   = FALSE;
471
 
    polkit->priv->proxy        = NULL;
472
 
    polkit->priv->subject      = NULL;
473
 
    polkit->priv->details      = NULL;
474
 
    polkit->priv->subject_hash = NULL;
475
 
    
476
 
    polkit->priv->subject_gtype = 
477
 
        dbus_g_type_get_struct ("GValueArray", 
478
 
                                G_TYPE_STRING, 
479
 
                                dbus_g_type_get_map ("GHashTable", 
480
 
                                                     G_TYPE_STRING, 
481
 
                                                     G_TYPE_VALUE),
482
 
                                G_TYPE_INVALID);
483
 
    
484
 
    polkit->priv->details_gtype = dbus_g_type_get_map ("GHashTable", 
485
 
                                                       G_TYPE_STRING, 
486
 
                                                       G_TYPE_STRING);
487
 
    
488
 
    polkit->priv->result_gtype =
489
 
        dbus_g_type_get_struct ("GValueArray", 
490
 
                                G_TYPE_BOOLEAN, 
491
 
                                G_TYPE_BOOLEAN, 
492
 
                                dbus_g_type_get_map ("GHashTable", 
493
 
                                                     G_TYPE_STRING, 
494
 
                                                     G_TYPE_STRING),
495
 
                                G_TYPE_INVALID);
496
 
#endif /*ENABLE_POLKIT*/
497
 
    
498
 
    polkit->priv->bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
499
 
    
500
 
    if ( error )
501
 
    {
502
 
        g_critical ("Error getting system bus connection : %s", error->message);
503
 
        g_error_free (error);
504
 
        goto out;
505
 
    }
506
 
 
507
 
#ifdef ENABLE_POLKIT
508
 
    polkit->priv->proxy = 
509
 
        dbus_g_proxy_new_for_name (polkit->priv->bus,
510
 
                                   "org.freedesktop.PolicyKit1",
511
 
                                   "/org/freedesktop/PolicyKit1/Authority",
512
 
                                   "org.freedesktop.PolicyKit1.Authority");
513
 
    
514
 
    if (G_LIKELY (polkit->priv->proxy) )
515
 
    {
516
 
        dbus_g_proxy_add_signal (polkit->priv->proxy, "Changed", G_TYPE_INVALID);
517
 
        dbus_g_proxy_connect_signal (polkit->priv->proxy, "Changed",
518
 
                                     G_CALLBACK (xfpm_polkit_changed_cb), polkit, NULL);
519
 
    }
520
 
    else
521
 
    {
522
 
        g_warning ("Failed to create proxy for 'org.freedesktop.PolicyKit1'");
523
 
    }
524
 
#endif /*ENABLE_POLKIT*/
525
 
 
526
 
out:
527
 
    ;
528
 
}
529
 
 
530
 
static void
531
 
xfpm_polkit_finalize (GObject *object)
532
 
{
533
 
    XfpmPolkit *polkit;
534
 
 
535
 
    polkit = XFPM_POLKIT (object);
536
 
 
537
 
#ifdef ENABLE_POLKIT
538
 
    if ( polkit->priv->proxy )
539
 
    {
540
 
        dbus_g_proxy_disconnect_signal (polkit->priv->proxy, "Changed",
541
 
                                        G_CALLBACK (xfpm_polkit_changed_cb), polkit);
542
 
        g_object_unref (polkit->priv->proxy);
543
 
    }
544
 
 
545
 
    if ( polkit->priv->subject_valid )
546
 
    {
547
 
        xfpm_polkit_free_data (polkit);
548
 
        if (polkit->priv->destroy_id != 0 )
549
 
            g_source_remove (polkit->priv->destroy_id);
550
 
    }
551
 
#endif /*ENABLE_POLKIT*/
552
 
 
553
 
 
554
 
    if ( polkit->priv->bus )
555
 
        dbus_g_connection_unref (polkit->priv->bus);
556
 
 
557
 
    G_OBJECT_CLASS (xfpm_polkit_parent_class)->finalize (object);
558
 
}
559
 
 
560
 
XfpmPolkit *
561
 
xfpm_polkit_get (void)
562
 
{
563
 
    static gpointer xfpm_polkit_obj = NULL;
564
 
    
565
 
    if ( G_LIKELY (xfpm_polkit_obj) )
566
 
    {
567
 
        g_object_ref (xfpm_polkit_obj);
568
 
    }
569
 
    else
570
 
    {
571
 
        xfpm_polkit_obj = g_object_new (XFPM_TYPE_POLKIT, NULL);
572
 
        g_object_add_weak_pointer (xfpm_polkit_obj, &xfpm_polkit_obj);
573
 
    }
574
 
    
575
 
    return XFPM_POLKIT (xfpm_polkit_obj);
576
 
}
577
 
 
578
 
gboolean xfpm_polkit_check_auth (XfpmPolkit *polkit, const gchar *action_id)
579
 
{
580
 
#ifdef ENABLE_POLKIT
581
 
    xfpm_polkit_init_data (polkit);
582
 
#endif
583
 
    return xfpm_polkit_check_auth_intern (polkit, action_id);
584
 
}