PolicyKit: Branch 'master'

David Zeuthen david at kemper.freedesktop.org
Sun Apr 22 18:13:17 PDT 2007


 configure.in                        |   14 +
 policy/polkit-example-action.policy |   34 +-
 polkit-grant/polkit-grant.c         |   13 -
 polkit-grant/polkit-grant.h         |    2 
 polkit/Makefile.am                  |    2 
 polkit/polkit-context.c             |   27 ++
 polkit/polkit-context.h             |   31 +-
 polkit/polkit-error.c               |    6 
 polkit/polkit-policy-cache.c        |   40 ++-
 polkit/polkit-policy-cache.h        |   25 +-
 polkit/polkit-policy-default.c      |  155 ++++++-------
 polkit/polkit-policy-default.h      |   17 -
 polkit/polkit-policy-file-entry.c   |  189 +++++++++++++++-
 polkit/polkit-policy-file-entry.h   |   11 
 polkit/polkit-policy-file.c         |  420 +++++++++++++++++++++++++++++++-----
 polkit/polkit-policy-file.h         |    4 
 tools/Makefile.am                   |    5 
 tools/polkit-list-actions.c         |  143 ++++++++++++
 tools/polkit-policy-file-validate.c |    2 
 19 files changed, 934 insertions(+), 206 deletions(-)

New commits:
diff-tree b9cf5bca49a2a1fc68002c2a315d94a3adaed51e (from 5cfae846d1c2b0cbef3dcebc909e2846bcc3cc4b)
Author: David Zeuthen <davidz at redhat.com>
Date:   Sun Apr 22 21:13:17 2007 -0400

    switch to XML for policy definition files and introduce descriptions
    
    Descriptions will be subject to i18n/l10n efforts at some point.
    
    Also add a new tool polkit-list-actions.

diff --git a/configure.in b/configure.in
index ae55f16..2eb6b95 100644
--- a/configure.in
+++ b/configure.in
@@ -127,6 +127,20 @@ AC_SUBST(DBUS_LIBS)
 
 AC_CHECK_FUNCS(getgrouplist)
 
+EXPAT_LIB=""
+AC_ARG_WITH(expat, [  --with-expat=<dir>      Use expat from here],
+                      [
+                      expat=$withval
+                      CPPFLAGS="$CPPFLAGS -I$withval/include"
+                      LDFLAGS="$LDFLAGS -L$withval/lib"
+                      ]
+                      )
+AC_CHECK_HEADERS(expat.h, [AC_DEFINE(HAVE_EXPAT_H)], 
+		 [AC_MSG_ERROR([Can't find expat.h. Please install expat.])])
+AC_CHECK_LIB(expat,XML_ParserCreate,[EXPAT_LIBS="-lexpat"],
+	     [AC_MSG_ERROR([Can't find expat library. Please install expat.])])
+AC_SUBST(EXPAT_LIBS)
+
 # DocBook Documentation
 
 AC_MSG_CHECKING([whether to build DocBook documentation])
diff --git a/policy/polkit-example-action.policy b/policy/polkit-example-action.policy
index 5204398..761ccf3 100644
--- a/policy/polkit-example-action.policy
+++ b/policy/polkit-example-action.policy
@@ -1,15 +1,23 @@
-# -*- Conf -*-
-#
-# Example privilege definitions...
+<!DOCTYPE policyconfig PUBLIC
+ "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">
+<policyconfig>
 
-[Action polkit-example-privilege]
-AllowRemoteInactive=no
-AllowRemoteActive=auth_root_keep_session
-AllowLocalInactive=auth_self_keep_always
-AllowLocalActive=yes
+  <group id="polkit-example">
+    <description>PolicyKit examples</description>
+    <description_short>PolicyKit</description_short>
 
-[Action polkit-example-privilege2]
-AllowRemoteInactive=no
-AllowRemoteActive=auth_root_keep_session
-AllowLocalInactive=auth_self_keep_always
-AllowLocalActive=yes
+    <policy id="polkit-example-frobnicate">
+      <description>Frobnicate devices</description>
+      <missing>System policy prevents frobnicating the device '%s'.</missing>
+      <apply_to_all_mnemonic>Apply to all _frobnicatable devices</apply_to_all_mnemonic>
+      <defaults>
+        <allow_remote_inactive>no</allow_remote_inactive>
+        <allow_remote_active>no</allow_remote_active>
+        <allow_local_inactive>no</allow_local_inactive>
+        <allow_local_active>auth_self_keep_always</allow_local_active>
+      </defaults>
+    </policy>
+
+  </group>
+</policyconfig>
diff --git a/polkit-grant/polkit-grant.c b/polkit-grant/polkit-grant.c
index 0197aa9..d73a0aa 100644
--- a/polkit-grant/polkit-grant.c
+++ b/polkit-grant/polkit-grant.c
@@ -221,11 +221,17 @@ polkit_grant_set_functions (PolKitGrant 
 void
 polkit_grant_child_func (PolKitGrant *polkit_grant, pid_t pid, int exit_code)
 {
+        polkit_bool_t input_was_bogus;
         g_return_if_fail (polkit_grant != NULL);
         g_return_if_fail (polkit_grant->auth_in_progress);
 
+        if (exit_code >= 2)
+                input_was_bogus = TRUE;
+        else
+                input_was_bogus = FALSE;
+
         polkit_grant->success = (exit_code == 0);
-        polkit_grant->func_done (polkit_grant, polkit_grant->success, polkit_grant->user_data);
+        polkit_grant->func_done (polkit_grant, polkit_grant->success, input_was_bogus, polkit_grant->user_data);
 }
 
 
@@ -355,8 +361,9 @@ polkit_grant_cancel_auth (PolKitGrant *p
 
         pid = polkit_grant->child_pid;
         polkit_grant->child_pid = 0;
-        kill (pid, SIGTERM);
-        polkit_grant->func_done (polkit_grant, FALSE, polkit_grant->user_data);        
+        if (pid > 0)
+                kill (pid, SIGTERM);
+        polkit_grant->func_done (polkit_grant, FALSE, FALSE, polkit_grant->user_data);        
 }
 
 /**
diff --git a/polkit-grant/polkit-grant.h b/polkit-grant/polkit-grant.h
index 0339f3d..cc04d42 100644
--- a/polkit-grant/polkit-grant.h
+++ b/polkit-grant/polkit-grant.h
@@ -196,6 +196,7 @@ typedef PolKitResult (*PolKitGrantOverri
  * PolKitGrantDone:
  * @polkit_grant: the grant object
  * @gained_privilege: whether the privilege was obtained
+ * @invalid_data: whether the input data was bogus (not including bad passwords)
  * @user_data: user data pointed as passed into polkit_grant_set_functions()
  *
  * This function is called when the granting process ends; either if
@@ -204,6 +205,7 @@ typedef PolKitResult (*PolKitGrantOverri
  **/
 typedef void (*PolKitGrantDone) (PolKitGrant *polkit_grant,
                                  polkit_bool_t gained_privilege,
+                                 polkit_bool_t invalid_data,
                                  void *user_data);
 
 /**
diff --git a/polkit/Makefile.am b/polkit/Makefile.am
index 0b3bbb1..5313952 100644
--- a/polkit/Makefile.am
+++ b/polkit/Makefile.am
@@ -53,7 +53,7 @@ libpolkit_la_SOURCES =                  
 	polkit-utils.h			polkit-utils.c			\
 	polkit-module.h			polkit-module.c
 
-libpolkit_la_LIBADD = @GLIB_LIBS@ -ldl
+libpolkit_la_LIBADD = @GLIB_LIBS@ @EXPAT_LIBS@ -ldl
 
 libpolkit_la_LDFLAGS = -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
 
diff --git a/polkit/polkit-context.c b/polkit/polkit-context.c
index a1248fd..0e17aa2 100644
--- a/polkit/polkit-context.c
+++ b/polkit/polkit-context.c
@@ -76,6 +76,8 @@ struct PolKitContext
         PolKitPolicyCache *priv_cache;
 
         GSList *modules;
+
+        polkit_bool_t load_descriptions;
 };
 
 /**
@@ -377,6 +379,8 @@ polkit_context_unref (PolKitContext *pk_
  * second) to avoid doing many expensive operations (such as
  * reconfiguring all ACL's for all devices) within a very short
  * timeframe.
+ *
+ * This method must be called before polkit_context_init().
  **/
 void
 polkit_context_set_config_changed (PolKitContext                *pk_context, 
@@ -395,6 +399,8 @@ polkit_context_set_config_changed (PolKi
  * @remove_watch_func: the function that the PolicyKit library can invoke to stop watching a file
  * 
  * Register a functions that PolicyKit can use for watching files.
+ *
+ * This method must be called before polkit_context_init().
  **/
 void
 polkit_context_set_file_monitor (PolKitContext                        *pk_context, 
@@ -406,6 +412,23 @@ polkit_context_set_file_monitor (PolKitC
         pk_context->file_monitor_remove_watch_func = remove_watch_func;
 }
 
+/**
+ * polkit_context_set_load_descriptions:
+ * @pk_context: the context
+ * 
+ * Set whether policy descriptions should be loaded. By default these
+ * are not loaded to keep memory use down. 
+ *
+ * This method must be called before polkit_context_init().
+ **/
+void
+polkit_context_set_load_descriptions  (PolKitContext *pk_context)
+{
+        g_return_if_fail (pk_context != NULL);
+        pk_context->load_descriptions = TRUE;
+}
+
+extern PolKitPolicyCache     *_polkit_policy_cache_new       (const char *dirname, polkit_bool_t load_descriptions, PolKitError **error);
 
 /**
  * polkit_context_get_policy_cache:
@@ -426,7 +449,9 @@ polkit_context_get_policy_cache (PolKitC
                 _pk_debug ("Populating cache from directory %s", pk_context->policy_dir);
 
                 error = NULL;
-                pk_context->priv_cache = polkit_policy_cache_new (pk_context->policy_dir, &error);
+                pk_context->priv_cache = _polkit_policy_cache_new (pk_context->policy_dir, 
+                                                                   pk_context->load_descriptions, 
+                                                                   &error);
                 if (pk_context->priv_cache == NULL) {
                         g_warning ("Error loading policy files from %s: %s", 
                                    pk_context->policy_dir, polkit_error_get_error_message (error));
diff --git a/polkit/polkit-context.h b/polkit/polkit-context.h
index 5963abe..13d53bf 100644
--- a/polkit/polkit-context.h
+++ b/polkit/polkit-context.h
@@ -135,13 +135,14 @@ typedef void (*PolKitContextFileMonitorR
 
 PolKitContext *polkit_context_new                (void);
 void           polkit_context_set_config_changed (PolKitContext                        *pk_context, 
-                                                     PolKitContextConfigChangedCB          cb, 
-                                                     void                                 *user_data);
+                                                  PolKitContextConfigChangedCB          cb, 
+                                                  void                                 *user_data);
 void           polkit_context_set_file_monitor   (PolKitContext                        *pk_context, 
-                                                     PolKitContextFileMonitorAddWatch      add_watch_func,
-                                                     PolKitContextFileMonitorRemoveWatch   remove_watch_func);
+                                                  PolKitContextFileMonitorAddWatch      add_watch_func,
+                                                  PolKitContextFileMonitorRemoveWatch   remove_watch_func);
+void           polkit_context_set_load_descriptions (PolKitContext                        *pk_context);
 polkit_bool_t  polkit_context_init               (PolKitContext                        *pk_context, 
-                                                     PolKitError                         **error);
+                                                  PolKitError                         **error);
 PolKitContext *polkit_context_ref                (PolKitContext                        *pk_context);
 void           polkit_context_unref              (PolKitContext                        *pk_context);
 
@@ -161,25 +162,25 @@ typedef void (*PolKitSeatVisitorCB) (Pol
 
 PolKitResult
 polkit_context_get_seat_resource_association (PolKitContext       *pk_context,
-                                                 PolKitSeatVisitorCB  visitor,
-                                                 void                *user_data);
+                                              PolKitSeatVisitorCB  visitor,
+                                              void                *user_data);
 
 PolKitResult
 polkit_context_is_resource_associated_with_seat (PolKitContext   *pk_context,
-                                                    PolKitResource  *resource,
-                                                    PolKitSeat      *seat);
+                                                 PolKitResource  *resource,
+                                                 PolKitSeat      *seat);
 
 PolKitResult
 polkit_context_can_session_access_resource (PolKitContext   *pk_context,
-                                               PolKitAction *action,
-                                               PolKitResource  *resource,
-                                               PolKitSession   *session);
+                                            PolKitAction    *action,
+                                            PolKitResource  *resource,
+                                            PolKitSession   *session);
 
 PolKitResult
 polkit_context_can_caller_access_resource (PolKitContext   *pk_context,
-                                              PolKitAction *action,
-                                              PolKitResource  *resource,
-                                              PolKitCaller    *caller);
+                                           PolKitAction    *action,
+                                           PolKitResource  *resource,
+                                           PolKitCaller    *caller);
 
 #endif /* POLKIT_CONTEXT_H */
 
diff --git a/polkit/polkit-error.c b/polkit/polkit-error.c
index cec8cc4..0d20c69 100644
--- a/polkit/polkit-error.c
+++ b/polkit/polkit-error.c
@@ -47,6 +47,7 @@
 
 #include "polkit-types.h"
 #include "polkit-error.h"
+#include "polkit-debug.h"
 
 /**
  * PolKitError:
@@ -123,7 +124,7 @@ polkit_error_set_error (PolKitError **er
         va_list args;
         PolKitError *e;
 
-        if (*error == NULL)
+        if (error == NULL)
                 return;
 
         e = g_new0 (PolKitError, 1);
@@ -135,6 +136,3 @@ polkit_error_set_error (PolKitError **er
 
         *error = e;
 }
-
-
-
diff --git a/polkit/polkit-policy-cache.c b/polkit/polkit-policy-cache.c
index dc9a93a..461583d 100644
--- a/polkit/polkit-policy-cache.c
+++ b/polkit/polkit-policy-cache.c
@@ -74,17 +74,10 @@ _append_entry (PolKitPolicyFile       *p
         policy_cache->priv_entries = g_slist_append (policy_cache->priv_entries, policy_file_entry);
 }
 
-/**
- * polkit_policy_cache_new:
- * @dirname: directory containing policy files
- * @error: location to return error
- * 
- * Create a new #PolKitPolicyCache object and load information from policy files.
- * 
- * Returns: #NULL if @error was set, otherwise the #PolKitPolicyCache object
- **/
+extern PolKitPolicyCache *_polkit_policy_cache_new       (const char *dirname, polkit_bool_t load_descriptions, PolKitError **error);
+
 PolKitPolicyCache *
-polkit_policy_cache_new (const char *dirname, PolKitError **error)
+_polkit_policy_cache_new (const char *dirname, polkit_bool_t load_descriptions, PolKitError **error)
 {
         const char *file;
         GDir *dir;
@@ -117,7 +110,7 @@ polkit_policy_cache_new (const char *dir
                 path = g_strdup_printf ("%s/%s", dirname, file);
 
                 _pk_debug ("Loading %s", path);
-                pf = polkit_policy_file_new (path, error);
+                pf = polkit_policy_file_new (path, load_descriptions, error);
                 g_free (path);
 
                 if (pf == NULL) {
@@ -246,3 +239,28 @@ polkit_policy_cache_get_entry (PolKitPol
 out:
         return pfe;
 }
+
+/**
+ * polkit_policy_cache_foreach:
+ * @policy_cache: the policy cache
+ * @callback: callback function
+ * @user_data: user data to pass to callback function
+ * 
+ * Visit all entries in the policy cache.
+ **/
+void
+polkit_policy_cache_foreach (PolKitPolicyCache *policy_cache, 
+                             PolKitPolicyCacheForeachFunc callback,
+                             void *user_data)
+{
+        GSList *i;
+        PolKitPolicyFileEntry *pfe;
+
+        g_return_if_fail (policy_cache != NULL);
+        g_return_if_fail (callback != NULL);
+
+        for (i = policy_cache->priv_entries; i != NULL; i = g_slist_next (i)) {
+                pfe = i->data;
+                callback (policy_cache, pfe, user_data);
+        }
+}
diff --git a/polkit/polkit-policy-cache.h b/polkit/polkit-policy-cache.h
index 7ed7e4d..c7d89c5 100644
--- a/polkit/polkit-policy-cache.h
+++ b/polkit/polkit-policy-cache.h
@@ -37,13 +37,26 @@
 struct PolKitPolicyCache;
 typedef struct PolKitPolicyCache PolKitPolicyCache;
 
-PolKitPolicyCache *polkit_policy_cache_new                   (const char *dirname, PolKitError **error);
-PolKitPolicyCache *polkit_policy_cache_ref                   (PolKitPolicyCache *policy_cache);
-void               polkit_policy_cache_unref                 (PolKitPolicyCache *policy_cache);
-void               polkit_policy_cache_debug                 (PolKitPolicyCache *policy_cache);
+/**
+ * PolKitPolicyCacheForeachFunc:
+ * @policy_cache: the policy cache
+ * @entry: an entry in the cache - do not unref
+ * @user_data: user data passed to polkit_policy_cache_foreach()
+ *
+ * Callback function for polkit_policy_cache_foreach().
+ **/
+typedef void (*PolKitPolicyCacheForeachFunc) (PolKitPolicyCache *policy_cache,
+                                              PolKitPolicyFileEntry *entry,
+                                              void *user_data);
 
-PolKitPolicyFileEntry* polkit_policy_cache_get_entry (PolKitPolicyCache *policy_cache,
-                                                         PolKitAction      *action);
+PolKitPolicyCache     *polkit_policy_cache_ref       (PolKitPolicyCache *policy_cache);
+void                   polkit_policy_cache_unref     (PolKitPolicyCache *policy_cache);
+void                   polkit_policy_cache_debug     (PolKitPolicyCache *policy_cache);
+PolKitPolicyFileEntry* polkit_policy_cache_get_entry (PolKitPolicyCache *policy_cache, 
+                                                      PolKitAction *action);
+void                   polkit_policy_cache_foreach   (PolKitPolicyCache *policy_cache, 
+                                                      PolKitPolicyCacheForeachFunc callback,
+                                                      void *user_data);
 
 #endif /* POLKIT_POLICY_CACHE_H */
 
diff --git a/polkit/polkit-policy-default.c b/polkit/polkit-policy-default.c
index 8ab2110..074fb93 100644
--- a/polkit/polkit-policy-default.c
+++ b/polkit/polkit-policy-default.c
@@ -63,96 +63,26 @@ struct PolKitPolicyDefault
         PolKitResult default_local_active;
 };
 
-static gboolean
-parse_default (const char *key, char *s, const char *group, PolKitResult* target, PolKitError **error)
-{
-        gboolean ret;
-
-        ret = polkit_result_from_string_representation (s, target);
-        if (!ret) {
-                int n;
-                char *s2;
-                GString *str;
-
-                str = g_string_new (NULL);
-                for (n = 0; n < POLKIT_RESULT_N_RESULTS; n++) {
-                        if (n == POLKIT_RESULT_NOT_AUTHORIZED_TO_KNOW)
-                                continue;
-
-                        if (str->len > 0) {
-                                g_string_append (str, ", ");
-                        }
-                        g_string_append (str, polkit_result_to_string_representation (n));
-                }
-                s2 = g_string_free (str, FALSE);
-
-                polkit_error_set_error (error, 
-                                        POLKIT_ERROR_POLICY_FILE_INVALID,
-                                        "Value '%s' is not allowed for key '%s' in group '%s'; "
-                                        "supported values are: %s", 
-                                        s, 
-                                        key,
-                                        group,
-                                        s2);
-                g_free (s2);
-        }
-        
-        g_free (s);
-        return ret;
-}
-
-extern PolKitPolicyDefault *_polkit_policy_default_new (GKeyFile *key_file, const char *action, PolKitError **error);
+extern PolKitPolicyDefault *_polkit_policy_default_new (PolKitResult defaults_allow_remote_inactive,
+                                                        PolKitResult defaults_allow_remote_active,
+                                                        PolKitResult defaults_allow_local_inactive,
+                                                        PolKitResult defaults_allow_local_active);
 
 PolKitPolicyDefault *
-_polkit_policy_default_new (GKeyFile *key_file, const char *action, PolKitError **error)
+_polkit_policy_default_new (PolKitResult defaults_allow_remote_inactive,
+                            PolKitResult defaults_allow_remote_active,
+                            PolKitResult defaults_allow_local_inactive,
+                            PolKitResult defaults_allow_local_active)
 {
-        const char *key;
-        const char *group;
-        char *s;
-        char buf[256];
         PolKitPolicyDefault *pd;
-        GError *g_error;
 
         pd = g_new0 (PolKitPolicyDefault, 1);
         pd->refcount = 1;
-
-        g_snprintf (buf, sizeof (buf), "Action %s", action);
-        group = buf;
-
-        g_error = NULL;
-        key = "AllowRemoteInactive";
-        if ((s = g_key_file_get_string (key_file, group, key, &g_error)) == NULL)
-                goto error;
-        if (!parse_default (key, s, group, &pd->default_remote_inactive, error))
-                goto error;
-        key = "AllowRemoteActive";
-        if ((s = g_key_file_get_string (key_file, group, key, &g_error)) == NULL)
-                goto error;
-        if (!parse_default (key, s, group, &pd->default_remote_active, error))
-                goto error;
-        key = "AllowLocalInactive";
-        if ((s = g_key_file_get_string (key_file, group, key, &g_error)) == NULL)
-                goto error;
-        if (!parse_default (key, s, group, &pd->default_local_inactive, error))
-                goto error;
-        key = "AllowLocalActive";
-        if ((s = g_key_file_get_string (key_file, group, key, &g_error)) == NULL)
-                goto error;
-        if (!parse_default (key, s, group, &pd->default_local_active, error))
-                goto error;
-
+        pd->default_remote_inactive = defaults_allow_remote_inactive;
+        pd->default_remote_active = defaults_allow_remote_active;
+        pd->default_local_inactive = defaults_allow_local_inactive;
+        pd->default_local_active = defaults_allow_local_active;
         return pd;
-error:
-        if (g_error != NULL) {
-                polkit_error_set_error (error, POLKIT_ERROR_POLICY_FILE_INVALID,
-                                        "Missing key in policy file: %s",
-                                        g_error->message);
-                g_error_free (g_error);
-        }
-
-        if (pd != NULL)
-                polkit_policy_default_ref (pd);
-        return NULL;
 }
 
 /**
@@ -320,3 +250,64 @@ polkit_policy_default_can_caller_access_
 out:
         return ret;
 }
+
+/**
+ * polkit_policy_default_get_allow_remote_inactive:
+ * @policy_default: the object
+ * 
+ * Get default policy.
+ * 
+ * Returns: default policy
+ **/
+PolKitResult
+polkit_policy_default_get_allow_remote_inactive (PolKitPolicyDefault *policy_default)
+{
+        g_return_val_if_fail (policy_default != NULL, POLKIT_RESULT_NO);
+        return policy_default->default_remote_inactive;
+}
+
+/**
+ * polkit_policy_default_get_allow_remote_active:
+ * @policy_default: the object
+ * 
+ * Get default policy.
+ * 
+ * Returns: default policy
+ **/
+PolKitResult
+polkit_policy_default_get_allow_remote_active (PolKitPolicyDefault *policy_default)
+{
+        g_return_val_if_fail (policy_default != NULL, POLKIT_RESULT_NO);
+        return policy_default->default_remote_active;
+}
+
+/**
+ * polkit_policy_default_get_allow_local_inactive:
+ * @policy_default: the object
+ * 
+ * Get default policy.
+ * 
+ * Returns: default policy
+ **/
+PolKitResult
+polkit_policy_default_get_allow_local_inactive (PolKitPolicyDefault *policy_default)
+{
+        g_return_val_if_fail (policy_default != NULL, POLKIT_RESULT_NO);
+        return policy_default->default_local_inactive;
+}
+
+/**
+ * polkit_policy_default_get_allow_local_active:
+ * @policy_default: the object
+ * 
+ * Get default policy.
+ * 
+ * Returns: default policy
+ **/
+PolKitResult
+polkit_policy_default_get_allow_local_active (PolKitPolicyDefault *policy_default)
+{
+        g_return_val_if_fail (policy_default != NULL, POLKIT_RESULT_NO);
+        return policy_default->default_local_active;
+}
+
diff --git a/polkit/polkit-policy-default.h b/polkit/polkit-policy-default.h
index 2dda732..9dad92c 100644
--- a/polkit/polkit-policy-default.h
+++ b/polkit/polkit-policy-default.h
@@ -45,13 +45,18 @@ void                    polkit_policy_de
 void                    polkit_policy_default_debug (PolKitPolicyDefault *policy_default);
 
 PolKitResult polkit_policy_default_can_session_access_resource (PolKitPolicyDefault *policy_default,
-                                                                   PolKitAction        *action,
-                                                                   PolKitResource         *resource,
-                                                                   PolKitSession          *session);
+                                                                PolKitAction        *action,
+                                                                PolKitResource         *resource,
+                                                                PolKitSession          *session);
 PolKitResult polkit_policy_default_can_caller_access_resource (PolKitPolicyDefault *policy_default,
-                                                                  PolKitAction        *action,
-                                                                  PolKitResource         *resource,
-                                                                  PolKitCaller           *caller);
+                                                               PolKitAction        *action,
+                                                               PolKitResource         *resource,
+                                                               PolKitCaller           *caller);
+
+PolKitResult polkit_policy_default_get_allow_remote_inactive (PolKitPolicyDefault *policy_default);
+PolKitResult polkit_policy_default_get_allow_remote_active (PolKitPolicyDefault *policy_default);
+PolKitResult polkit_policy_default_get_allow_local_inactive (PolKitPolicyDefault *policy_default);
+PolKitResult polkit_policy_default_get_allow_local_active (PolKitPolicyDefault *policy_default);
 
 /* TODO: export knobs for "default policy" */
 
diff --git a/polkit/polkit-policy-file-entry.c b/polkit/polkit-policy-file-entry.c
index 8e5c172..f72c87c 100644
--- a/polkit/polkit-policy-file-entry.c
+++ b/polkit/polkit-policy-file-entry.c
@@ -59,24 +59,55 @@ struct PolKitPolicyFileEntry
 {
         int refcount;
         char *action;
+        char *group;
         PolKitPolicyDefault *defaults;
-};
 
-PolKitPolicyFileEntry *
-_polkit_policy_file_entry_new (GKeyFile *key_file, const char *action, PolKitError **error);
+        char *group_description;
+        char *group_description_short;
+        char *policy_description;
+        char *policy_missing;
+        char *policy_apply_all_mnemonic;
+};
 
-extern PolKitPolicyDefault *_polkit_policy_default_new (GKeyFile *key_file, const char *action, PolKitError **error);
+extern void _polkit_policy_file_entry_set_descriptions (PolKitPolicyFileEntry *pfe,
+                                                        const char *group_description,
+                                                        const char *group_description_short,
+                                                        const char *policy_description,
+                                                        const char *policy_missing,
+                                                        const char *policy_apply_all_mnemonic);
+
+
+extern PolKitPolicyDefault *_polkit_policy_default_new (PolKitResult defaults_allow_remote_inactive,
+                                                        PolKitResult defaults_allow_remote_active,
+                                                        PolKitResult defaults_allow_local_inactive,
+                                                        PolKitResult defaults_allow_local_active);
+
+extern PolKitPolicyFileEntry *_polkit_policy_file_entry_new   (const char *action_group_id,
+                                                               const char *action_id, 
+                                                               PolKitResult defaults_allow_remote_inactive,
+                                                               PolKitResult defaults_allow_remote_active,
+                                                               PolKitResult defaults_allow_local_inactive,
+                                                               PolKitResult defaults_allow_local_active);
 
 extern PolKitPolicyFileEntry *
-_polkit_policy_file_entry_new (GKeyFile *key_file, const char *action, PolKitError **error)
+_polkit_policy_file_entry_new   (const char *action_group_id,
+                                 const char *action_id, 
+                                 PolKitResult defaults_allow_remote_inactive,
+                                 PolKitResult defaults_allow_remote_active,
+                                 PolKitResult defaults_allow_local_inactive,
+                                 PolKitResult defaults_allow_local_active)
 {
         PolKitPolicyFileEntry *pfe;
 
         pfe = g_new0 (PolKitPolicyFileEntry, 1);
         pfe->refcount = 1;
-        pfe->action = g_strdup (action);
+        pfe->action = g_strdup (action_id);
+        pfe->group = g_strdup (action_group_id);
 
-        pfe->defaults = _polkit_policy_default_new (key_file, action, error);
+        pfe->defaults = _polkit_policy_default_new (defaults_allow_remote_inactive,
+                                                    defaults_allow_remote_active,
+                                                    defaults_allow_local_inactive,
+                                                    defaults_allow_local_active);
         if (pfe->defaults == NULL)
                 goto error;
 
@@ -87,6 +118,127 @@ error:
         return NULL;
 }
 
+void 
+_polkit_policy_file_entry_set_descriptions (PolKitPolicyFileEntry *policy_file_entry,
+                                            const char *group_description,
+                                            const char *group_description_short,
+                                            const char *policy_description,
+                                            const char *policy_missing,
+                                            const char *policy_apply_all_mnemonic)
+{
+        g_return_if_fail (policy_file_entry != NULL);
+        policy_file_entry->group_description = g_strdup (group_description);
+        policy_file_entry->group_description_short = g_strdup (group_description_short);
+        policy_file_entry->policy_description = g_strdup (policy_description);
+        policy_file_entry->policy_missing = g_strdup (policy_missing);
+        policy_file_entry->policy_apply_all_mnemonic = g_strdup (policy_apply_all_mnemonic);
+}
+
+/**
+ * polkit_policy_file_get_group_description:
+ * @policy_file_entry: the object
+ * 
+ * Get the description of the group that this policy entry describes.
+ *
+ * Note, if polkit_context_set_load_descriptions() on the
+ * #PolKitContext object used to get this object wasn't called, this
+ * method will return #NULL.
+ * 
+ * Returns: string or #NULL if descriptions are not loaded - caller shall not free this string
+ **/
+const char *
+polkit_policy_file_get_group_description (PolKitPolicyFileEntry *policy_file_entry)
+{
+        g_return_val_if_fail (policy_file_entry != NULL, NULL);
+        return policy_file_entry->group_description;
+}
+
+/**
+ * polkit_policy_file_get_group_description_short:
+ * @policy_file_entry: the object
+ * 
+ * Get the short description of the group that this policy entry describes.
+ *
+ * Note, if polkit_context_set_load_descriptions() on the
+ * #PolKitContext object used to get this object wasn't called, this
+ * method will return #NULL.
+ * 
+ * Returns: string or #NULL if descriptions are not loaded - caller shall not free this string
+ **/
+const char *
+polkit_policy_file_get_group_description_short (PolKitPolicyFileEntry *policy_file_entry)
+{
+        g_return_val_if_fail (policy_file_entry != NULL, NULL);
+        return policy_file_entry->group_description_short;
+}
+
+/**
+ * polkit_policy_file_get_action_description:
+ * @policy_file_entry: the object
+ * 
+ * Get the description of the action that this policy entry describes.
+ *
+ * Note, if polkit_context_set_load_descriptions() on the
+ * #PolKitContext object used to get this object wasn't called, this
+ * method will return #NULL.
+ * 
+ * Returns: string or #NULL if descriptions are not loaded - caller shall not free this string
+ **/
+const char *
+polkit_policy_file_get_action_description (PolKitPolicyFileEntry *policy_file_entry)
+{
+        g_return_val_if_fail (policy_file_entry != NULL, NULL);
+        return policy_file_entry->policy_description;
+}
+
+/**
+ * polkit_policy_file_get_action_missing:
+ * @policy_file_entry: the object
+ * 
+ * Get a phrase, for the policy entry in question, that can be shown
+ * in the user interface explaining that the caller doesn't possess
+ * the privilege to perform the given action on the given resource.
+ *
+ * The returned string may contain a single %s entry - the caller
+ * should use a printf-style function to replace this with a human
+ * readable description of the resource in question.
+ *
+ * Note, if polkit_context_set_load_descriptions() on the
+ * #PolKitContext object used to get this object wasn't called, this
+ * method will return #NULL.
+ * 
+ * Returns: string or #NULL if descriptions are not loaded - caller shall not free this string
+ **/
+const char *
+polkit_policy_file_get_action_missing (PolKitPolicyFileEntry *policy_file_entry)
+{
+        g_return_val_if_fail (policy_file_entry != NULL, NULL);
+        return policy_file_entry->policy_missing;
+}
+
+/**
+ * polkit_policy_file_get_action_apply_to_all_mnemonic:
+ * @policy_file_entry: the object
+ * 
+ * Get a phrase, for the policy entry in question, that can be shown
+ * in the user interface for a checkbox whether the grant of a
+ * privilege should apply to all resources. The string may contain a
+ * single underscore to indicate a mnemonic shortcut.
+ *
+ * Note, if polkit_context_set_load_descriptions() on the
+ * #PolKitContext object used to get this object wasn't called, this
+ * method will return #NULL.
+ * 
+ * Returns: string or #NULL if descriptions are not loaded - caller shall not free this string
+ **/
+const char *
+polkit_policy_file_get_action_apply_to_all_mnemonic (PolKitPolicyFileEntry *policy_file_entry)
+{
+        g_return_val_if_fail (policy_file_entry != NULL, NULL);
+        return policy_file_entry->policy_apply_all_mnemonic;
+}
+
+
 /**
  * polkit_policy_file_entry_ref:
  * @policy_file_entry: the policy file object
@@ -121,6 +273,13 @@ polkit_policy_file_entry_unref (PolKitPo
         g_free (policy_file_entry->action);
         if (policy_file_entry->defaults != NULL)
                 polkit_policy_default_unref (policy_file_entry->defaults);
+
+        g_free (policy_file_entry->group_description);
+        g_free (policy_file_entry->group_description_short);
+        g_free (policy_file_entry->policy_description);
+        g_free (policy_file_entry->policy_missing);
+        g_free (policy_file_entry->policy_apply_all_mnemonic);
+
         g_free (policy_file_entry);
 }
 
@@ -156,6 +315,22 @@ polkit_policy_file_entry_get_id (PolKitP
 }
 
 /**
+ * polkit_policy_file_entry_get_group_id:
+ * @policy_file_entry: the file entry
+ * 
+ * Get the action group identifier.
+ * 
+ * Returns: A string - caller shall not free this string.
+ **/
+const char *
+polkit_policy_file_entry_get_group_id (PolKitPolicyFileEntry *policy_file_entry)
+{
+        g_return_val_if_fail (policy_file_entry != NULL, NULL);
+        return policy_file_entry->group;
+}
+
+
+/**
  * polkit_policy_file_entry_get_default:
  * @policy_file_entry: the file entry
  * 
diff --git a/polkit/polkit-policy-file-entry.h b/polkit/polkit-policy-file-entry.h
index 1fd11b5..5e0b310 100644
--- a/polkit/polkit-policy-file-entry.h
+++ b/polkit/polkit-policy-file-entry.h
@@ -40,8 +40,15 @@ PolKitPolicyFileEntry *polkit_policy_fil
 void                   polkit_policy_file_entry_unref (PolKitPolicyFileEntry *policy_file_entry);
 void                   polkit_policy_file_entry_debug (PolKitPolicyFileEntry *policy_file_entry);
 
-const char            *polkit_policy_file_entry_get_id      (PolKitPolicyFileEntry *policy_file_entry);
-PolKitPolicyDefault   *polkit_policy_file_entry_get_default (PolKitPolicyFileEntry *policy_file_entry);
+const char            *polkit_policy_file_entry_get_id       (PolKitPolicyFileEntry *policy_file_entry);
+const char            *polkit_policy_file_entry_get_group_id (PolKitPolicyFileEntry *policy_file_entry);
+PolKitPolicyDefault   *polkit_policy_file_entry_get_default  (PolKitPolicyFileEntry *policy_file_entry);
+
+const char            *polkit_policy_file_get_group_description (PolKitPolicyFileEntry *policy_file_entry);
+const char            *polkit_policy_file_get_group_description_short (PolKitPolicyFileEntry *policy_file_entry);
+const char            *polkit_policy_file_get_action_description (PolKitPolicyFileEntry *policy_file_entry);
+const char            *polkit_policy_file_get_action_missing (PolKitPolicyFileEntry *policy_file_entry);
+const char            *polkit_policy_file_get_action_apply_to_all_mnemonic (PolKitPolicyFileEntry *policy_file_entry);
 
 
 #endif /* POLKIT_POLICY_FILE_ENTRY_H */
diff --git a/polkit/polkit-policy-file.c b/polkit/polkit-policy-file.c
index 04b23dc..043fe90 100644
--- a/polkit/polkit-policy-file.c
+++ b/polkit/polkit-policy-file.c
@@ -36,11 +36,14 @@
 #include <unistd.h>
 #include <errno.h>
 
+#include <expat.h>
+
 #include <glib.h>
 #include "polkit-error.h"
 #include "polkit-result.h"
 #include "polkit-policy-file.h"
 #include "polkit-policy-file-entry.h"
+#include "polkit-debug.h"
 
 /**
  * SECTION:polkit-policy-file
@@ -61,34 +64,331 @@ struct PolKitPolicyFile
         GSList *entries;
 };
 
-extern PolKitPolicyFileEntry *_polkit_policy_file_entry_new   (GKeyFile *keyfile, 
-                                                                  const char *action, 
-                                                                  PolKitError **error);
+extern PolKitPolicyFileEntry *_polkit_policy_file_entry_new   (const char *action_group_id,
+                                                               const char *action_id, 
+                                                               PolKitResult defaults_allow_remote_inactive,
+                                                               PolKitResult defaults_allow_remote_active,
+                                                               PolKitResult defaults_allow_local_inactive,
+                                                               PolKitResult defaults_allow_local_active);
+
+enum {
+        STATE_NONE,
+        STATE_IN_POLICY_CONFIG,
+        STATE_IN_GROUP,
+        STATE_IN_GROUP_DESCRIPTION,
+        STATE_IN_GROUP_DESCRIPTION_SHORT,
+        STATE_IN_POLICY,
+        STATE_IN_POLICY_DESCRIPTION,
+        STATE_IN_POLICY_MISSING,
+        STATE_IN_POLICY_APPLY_TO_ALL_MNEMONIC,
+        STATE_IN_DEFAULTS,
+        STATE_IN_DEFAULTS_ALLOW_REMOTE_INACTIVE,
+        STATE_IN_DEFAULTS_ALLOW_REMOTE_ACTIVE,
+        STATE_IN_DEFAULTS_ALLOW_LOCAL_INACTIVE,
+        STATE_IN_DEFAULTS_ALLOW_LOCAL_ACTIVE
+};
+
+typedef struct {
+        XML_Parser parser;
+        int state;
+        char *group_id;
+        char *action_id;
+
+        PolKitResult defaults_allow_remote_inactive;
+        PolKitResult defaults_allow_remote_active;
+        PolKitResult defaults_allow_local_inactive;
+        PolKitResult defaults_allow_local_active;
+
+        PolKitPolicyFile *pf;
+
+        polkit_bool_t load_descriptions;
+
+        char *group_description;
+        char *group_description_short;
+        char *policy_description;
+        char *policy_missing;
+        char *policy_apply_all_mnemonic;
+} ParserData;
+
+static void
+_start (void *data, const char *el, const char **attr)
+{
+        int state;
+        int num_attr;
+        ParserData *pd = data;
+
+        for (num_attr = 0; attr[num_attr] != NULL; num_attr++)
+                ;
+
+        state = STATE_NONE;
+
+        switch (pd->state) {
+        case STATE_NONE:
+                if (strcmp (el, "policyconfig") == 0) {
+                        state = STATE_IN_POLICY_CONFIG;
+                }
+                break;
+        case STATE_IN_POLICY_CONFIG:
+                if (strcmp (el, "group") == 0) {
+                        if (num_attr != 2 || strcmp (attr[0], "id") != 0)
+                                goto error;
+                        g_free (pd->group_id);
+                        pd->group_id = g_strdup (attr[1]);
+                        state = STATE_IN_GROUP;
+
+                        g_free (pd->group_description);
+                        g_free (pd->group_description_short);
+                        pd->group_description = NULL;
+                        pd->group_description_short = NULL;
+                }
+                break;
+        case STATE_IN_GROUP:
+                if (strcmp (el, "policy") == 0) {
+                        if (num_attr != 2 || strcmp (attr[0], "id") != 0)
+                                goto error;
+                        g_free (pd->action_id);
+                        pd->action_id = g_strdup (attr[1]);
+                        state = STATE_IN_POLICY;
+
+                        pd->policy_description = NULL;
+                        pd->policy_missing = NULL;
+                        pd->policy_apply_all_mnemonic = NULL;
+
+                        /* initialize defaults */
+                        pd->defaults_allow_remote_inactive = POLKIT_RESULT_NO;
+                        pd->defaults_allow_remote_active = POLKIT_RESULT_NO;
+                        pd->defaults_allow_local_inactive = POLKIT_RESULT_NO;
+                        pd->defaults_allow_local_active = POLKIT_RESULT_NO;
+                }
+                else if (strcmp (el, "description") == 0)
+                        state = STATE_IN_GROUP_DESCRIPTION;
+                else if (strcmp (el, "description_short") == 0)
+                        state = STATE_IN_GROUP_DESCRIPTION_SHORT;
+                break;
+        case STATE_IN_GROUP_DESCRIPTION:
+                break;
+        case STATE_IN_GROUP_DESCRIPTION_SHORT:
+                break;
+        case STATE_IN_POLICY:
+                if (strcmp (el, "defaults") == 0)
+                        state = STATE_IN_DEFAULTS;
+                else if (strcmp (el, "description") == 0)
+                        state = STATE_IN_POLICY_DESCRIPTION;
+                else if (strcmp (el, "missing") == 0)
+                        state = STATE_IN_POLICY_MISSING;
+                else if (strcmp (el, "apply_to_all_mnemonic") == 0)
+                        state = STATE_IN_POLICY_APPLY_TO_ALL_MNEMONIC;
+                break;
+        case STATE_IN_POLICY_DESCRIPTION:
+                break;
+        case STATE_IN_POLICY_MISSING:
+                break;
+        case STATE_IN_POLICY_APPLY_TO_ALL_MNEMONIC:
+                break;
+        case STATE_IN_DEFAULTS:
+                if (strcmp (el, "allow_remote_inactive") == 0)
+                        state = STATE_IN_DEFAULTS_ALLOW_REMOTE_INACTIVE;
+                else if (strcmp (el, "allow_remote_active") == 0)
+                        state = STATE_IN_DEFAULTS_ALLOW_REMOTE_ACTIVE;
+                else if (strcmp (el, "allow_local_inactive") == 0)
+                        state = STATE_IN_DEFAULTS_ALLOW_LOCAL_INACTIVE;
+                else if (strcmp (el, "allow_local_active") == 0)
+                        state = STATE_IN_DEFAULTS_ALLOW_LOCAL_ACTIVE;
+                break;
+        case STATE_IN_DEFAULTS_ALLOW_REMOTE_INACTIVE:
+                break;
+        case STATE_IN_DEFAULTS_ALLOW_REMOTE_ACTIVE:
+                break;
+        case STATE_IN_DEFAULTS_ALLOW_LOCAL_INACTIVE:
+                break;
+        case STATE_IN_DEFAULTS_ALLOW_LOCAL_ACTIVE:
+                break;
+        default:
+                break;
+        }
+
+        if (state == STATE_NONE)
+                goto error;
+
+        pd->state = state;
+
+        return;
+error:
+        XML_StopParser (pd->parser, FALSE);
+}
+
+static void
+_cdata (void *data, const char *s, int len)
+{
+        char *str;
+        ParserData *pd = data;
+
+        str = g_strndup (s, len);
+        switch (pd->state) {
+
+        case STATE_IN_GROUP_DESCRIPTION:
+                if (pd->load_descriptions)
+                        pd->group_description = g_strdup (str);
+                break;
+                
+        case STATE_IN_GROUP_DESCRIPTION_SHORT:
+                if (pd->load_descriptions)
+                        pd->group_description_short = g_strdup (str);
+                break;
+
+        case STATE_IN_POLICY_DESCRIPTION:
+                if (pd->load_descriptions)
+                        pd->policy_description = g_strdup (str);
+                break;
+
+        case STATE_IN_POLICY_MISSING:
+                if (pd->load_descriptions)
+                        pd->policy_missing = g_strdup (str);
+                break;
+
+        case STATE_IN_POLICY_APPLY_TO_ALL_MNEMONIC:
+                if (pd->load_descriptions)
+                        pd->policy_apply_all_mnemonic = g_strdup (str);
+                break;
+
+                
+
+        case STATE_IN_DEFAULTS_ALLOW_REMOTE_INACTIVE:
+                if (!polkit_result_from_string_representation (str, &pd->defaults_allow_remote_inactive))
+                        goto error;
+                break;
+        case STATE_IN_DEFAULTS_ALLOW_REMOTE_ACTIVE:
+                if (!polkit_result_from_string_representation (str, &pd->defaults_allow_remote_active))
+                        goto error;
+                break;
+        case STATE_IN_DEFAULTS_ALLOW_LOCAL_INACTIVE:
+                if (!polkit_result_from_string_representation (str, &pd->defaults_allow_local_inactive))
+                        goto error;
+                break;
+        case STATE_IN_DEFAULTS_ALLOW_LOCAL_ACTIVE:
+                if (!polkit_result_from_string_representation (str, &pd->defaults_allow_local_active))
+                        goto error;
+                break;
+        default:
+                break;
+        }
+        g_free (str);
+        return;
+error:
+        g_free (str);
+        XML_StopParser (pd->parser, FALSE);
+}
+
+
+extern void _polkit_policy_file_entry_set_descriptions (PolKitPolicyFileEntry *pfe,
+                                                        const char *group_description,
+                                                        const char *group_description_short,
+                                                        const char *policy_description,
+                                                        const char *policy_missing,
+                                                        const char *policy_apply_all_mnemonic);
+
+static void
+_end (void *data, const char *el)
+{
+        int state;
+        ParserData *pd = data;
+
+        state = STATE_NONE;
+
+        switch (pd->state) {
+        case STATE_NONE:
+                break;
+        case STATE_IN_POLICY_CONFIG:
+                state = STATE_NONE;
+                break;
+        case STATE_IN_GROUP:
+                state = STATE_IN_POLICY_CONFIG;
+                break;
+        case STATE_IN_GROUP_DESCRIPTION:
+                state = STATE_IN_GROUP;
+                break;
+        case STATE_IN_GROUP_DESCRIPTION_SHORT:
+                state = STATE_IN_GROUP;
+                break;
+        case STATE_IN_POLICY:
+        {
+                PolKitPolicyFileEntry *pfe;
+
+                pfe = _polkit_policy_file_entry_new (pd->group_id, pd->action_id, 
+                                                     pd->defaults_allow_remote_inactive,
+                                                     pd->defaults_allow_remote_active,
+                                                     pd->defaults_allow_local_inactive,
+                                                     pd->defaults_allow_local_active);
+                if (pfe == NULL)
+                        goto error;
+
+                if (pd->load_descriptions)
+                        _polkit_policy_file_entry_set_descriptions (pfe,
+                                                                    pd->group_description,
+                                                                    pd->group_description_short,
+                                                                    pd->policy_description,
+                                                                    pd->policy_missing,
+                                                                    pd->policy_apply_all_mnemonic);
+
+                pd->pf->entries = g_slist_prepend (pd->pf->entries, pfe);
+
+                state = STATE_IN_GROUP;
+                break;
+        }
+        case STATE_IN_POLICY_DESCRIPTION:
+                state = STATE_IN_POLICY;
+                break;
+        case STATE_IN_POLICY_MISSING:
+                state = STATE_IN_POLICY;
+                break;
+        case STATE_IN_POLICY_APPLY_TO_ALL_MNEMONIC:
+                state = STATE_IN_POLICY;
+                break;
+        case STATE_IN_DEFAULTS:
+                state = STATE_IN_POLICY;
+                break;
+        case STATE_IN_DEFAULTS_ALLOW_REMOTE_INACTIVE:
+                state = STATE_IN_DEFAULTS;
+                break;
+        case STATE_IN_DEFAULTS_ALLOW_REMOTE_ACTIVE:
+                state = STATE_IN_DEFAULTS;
+                break;
+        case STATE_IN_DEFAULTS_ALLOW_LOCAL_INACTIVE:
+                state = STATE_IN_DEFAULTS;
+                break;
+        case STATE_IN_DEFAULTS_ALLOW_LOCAL_ACTIVE:
+                state = STATE_IN_DEFAULTS;
+                break;
+        default:
+                break;
+        }
+
+        pd->state = state;
+
+        return;
+error:
+        XML_StopParser (pd->parser, FALSE);
+}
+
 
 /**
  * polkit_policy_file_new:
- * @path: path to policy file
- * @error: return location for error
+ * @path: path to file
+ * @load_descriptions: whether descriptions should be loaded
+ * @error: Return location for error
  * 
- * Create a new #PolKitPolicyFile object. If the file does not
- * validate, a human readable explanation of why will be set in
- * @error.
+ * Load a policy file.
  * 
- * Returns: the new object or #NULL if error is set
+ * Returns: The new object or #NULL if error is set
  **/
 PolKitPolicyFile *
-polkit_policy_file_new (const char *path, PolKitError **error)
+polkit_policy_file_new (const char *path, polkit_bool_t load_descriptions, PolKitError **error)
 {
-        GKeyFile *key_file;
         PolKitPolicyFile *pf;
-        char **groups;
-        gsize groups_len;
-        int n;
-        GError *g_error;
+        ParserData pd;
+        int xml_res;
 
         pf = NULL;
-        key_file = NULL;
-        groups = NULL;
 
         if (!g_str_has_suffix (path, ".policy")) {
                 polkit_error_set_error (error, 
@@ -97,59 +397,75 @@ polkit_policy_file_new (const char *path
                 goto error;
         }
 
+	char *buf;
+	gsize buflen;
+        GError *g_error;
+
         g_error = NULL;
-        key_file = g_key_file_new ();
-        if (!g_key_file_load_from_file (key_file, path, G_KEY_FILE_NONE, &g_error)) {
+	if (!g_file_get_contents (path, &buf, &buflen, &g_error)) {
                 polkit_error_set_error (error, POLKIT_ERROR_POLICY_FILE_INVALID,
                                         "Cannot load PolicyKit policy file at '%s': %s",
                                         path,
                                         g_error->message);
                 g_error_free (g_error);
+		goto error;
+        }
+
+        pd.parser = XML_ParserCreate (NULL);
+        if (pd.parser == NULL) {
+                polkit_error_set_error (error, POLKIT_ERROR_OUT_OF_MEMORY,
+                                        "Cannot load PolicyKit policy file at '%s': %s",
+                                        path,
+                                        "No memory for parser");
                 goto error;
         }
+	XML_SetUserData (pd.parser, &pd);
+	XML_SetElementHandler (pd.parser, _start, _end);
+	XML_SetCharacterDataHandler (pd.parser, _cdata);
 
         pf = g_new0 (PolKitPolicyFile, 1);
         pf->refcount = 1;
 
-        groups = g_key_file_get_groups(key_file, &groups_len);
-        if (groups == NULL)
-                goto error;
-
-        for (n = 0; groups[n] != NULL; n++) {
-                const char *action;
-                PolKitPolicyFileEntry *pfe;
-
-                if (!g_str_has_prefix (groups[n], "Action ")) {
-                        polkit_error_set_error (error, 
-                                                POLKIT_ERROR_POLICY_FILE_INVALID,
-                                                "Unknown group of name '%s'", groups[n]);
-                        goto error;
-                }
-
-                action = groups[n] + 7; /* "Action " */
-                if (strlen (action) == 0) {
-                        polkit_error_set_error (error, 
-                                                POLKIT_ERROR_POLICY_FILE_INVALID,
-                                                "Zero-length action name");
-                        goto error;
-                }
+        pd.state = STATE_NONE;
+        pd.group_id = NULL;
+        pd.action_id = NULL;
+        pd.group_description = NULL;
+        pd.group_description_short = NULL;
+        pd.policy_description = NULL;
+        pd.policy_missing = NULL;
+        pd.policy_apply_all_mnemonic = NULL;
+        pd.pf = pf;
+        pd.load_descriptions = load_descriptions;
+
+        xml_res = XML_Parse (pd.parser, buf, buflen, 1);
+
+        g_free (pd.group_id);
+        g_free (pd.action_id);
+        g_free (pd.group_description);
+        g_free (pd.group_description_short);
+        g_free (pd.policy_description);
+        g_free (pd.policy_missing);
+        g_free (pd.policy_apply_all_mnemonic);
 
-                pfe = _polkit_policy_file_entry_new (key_file, action, error);
-                if (pfe == NULL)
-                        goto error;
-                pf->entries = g_slist_prepend (pf->entries, pfe);
-        }
+	if (xml_res == 0) {
+                polkit_error_set_error (error, POLKIT_ERROR_POLICY_FILE_INVALID,
+                                        "%s:%d: parse error: %s",
+                                        path, 
+                                        (int) XML_GetCurrentLineNumber (pd.parser),
+                                        XML_ErrorString (XML_GetErrorCode (pd.parser)));
+
+		XML_ParserFree (pd.parser);
+		g_free (buf);
+		goto error;
+	}
+	XML_ParserFree (pd.parser);
+	g_free (buf);
 
-        g_strfreev (groups);
-        g_key_file_free (key_file);
         return pf;
 error:
-        if (groups != NULL)
-                g_strfreev (groups);
-        if (key_file != NULL)
-                g_key_file_free (key_file);
         if (pf != NULL)
                 polkit_policy_file_unref (pf);
+
         return NULL;
 }
 
diff --git a/polkit/polkit-policy-file.h b/polkit/polkit-policy-file.h
index 3e1baf0..bcb28f9 100644
--- a/polkit/polkit-policy-file.h
+++ b/polkit/polkit-policy-file.h
@@ -48,7 +48,9 @@ typedef void (*PolKitPolicyFileEntryFore
                                                   PolKitPolicyFileEntry *policy_file_entry,
                                                   void                  *user_data);
 
-PolKitPolicyFile *polkit_policy_file_new           (const char       *path, PolKitError **error);
+PolKitPolicyFile *polkit_policy_file_new           (const char       *path, 
+                                                    polkit_bool_t load_descriptions, 
+                                                    PolKitError **error);
 PolKitPolicyFile *polkit_policy_file_ref           (PolKitPolicyFile *policy_file);
 void              polkit_policy_file_unref         (PolKitPolicyFile *policy_file);
 void              polkit_policy_file_entry_foreach (PolKitPolicyFile                 *policy_file,
diff --git a/tools/Makefile.am b/tools/Makefile.am
index eddca37..d40298d 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -11,7 +11,7 @@ INCLUDES = \
 	@GLIB_CFLAGS@ \
 	@DBUS_CFLAGS@
 
-bin_PROGRAMS = polkit-check-caller polkit-check-session polkit-policy-file-validate polkit-grant
+bin_PROGRAMS = polkit-check-caller polkit-check-session polkit-policy-file-validate polkit-grant polkit-list-actions
 
 polkit_check_caller_SOURCES = polkit-check-caller.c
 polkit_check_caller_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ $(top_builddir)/polkit/libpolkit.la $(top_builddir)/polkit-dbus/libpolkit-dbus.la
@@ -25,6 +25,9 @@ polkit_policy_file_validate_LDADD = $(to
 polkit_grant_SOURCES = polkit-grant.c
 polkit_grant_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ $(top_builddir)/polkit/libpolkit.la $(top_builddir)/polkit-grant/libpolkit-grant.la $(top_builddir)/polkit-dbus/libpolkit-dbus.la
 
+polkit_list_actions_SOURCES = polkit-list-actions.c
+polkit_list_actions_LDADD = $(GLIB) $(top_builddir)/polkit/libpolkit.la
+
 clean-local :
 	rm -f *~
 
diff --git a/tools/polkit-list-actions.c b/tools/polkit-list-actions.c
new file mode 100644
index 0000000..756c1d8
--- /dev/null
+++ b/tools/polkit-list-actions.c
@@ -0,0 +1,143 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/***************************************************************************
+ *
+ * polkit-list-actions.c : list all registered PolicyKit actions
+ *
+ * Copyright (C) 2007 David Zeuthen, <david at fubar.dk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307	 USA
+ *
+ **************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <stdbool.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <grp.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <polkit/polkit.h>
+
+static void
+usage (int argc, char *argv[])
+{
+	fprintf (stderr,
+                 "\n"
+                 "usage : polkit-list-actions [--version] [--help]\n"
+                 "\n");
+	fprintf (stderr,
+                 "\n"
+                 "        --version        Show version and exit\n"
+                 "        --help           Show this information and exit\n"
+                 "\n"
+                 "List the actions registered with PolicyKit.\n");
+}
+
+static void
+_print_entry (PolKitPolicyCache *policy_cache,
+              PolKitPolicyFileEntry *pfe,
+              void *user_data)
+{
+        const char *action_id;
+        const char *group_id;
+        PolKitPolicyDefault *def;
+        PolKitResult default_remote_inactive;
+        PolKitResult default_remote_active;
+        PolKitResult default_local_inactive;
+        PolKitResult default_local_active;
+
+        action_id = polkit_policy_file_entry_get_id (pfe);
+        group_id = polkit_policy_file_entry_get_group_id (pfe);
+        def = polkit_policy_file_entry_get_default (pfe);
+        default_remote_inactive = polkit_policy_default_get_allow_remote_inactive (def);
+        default_remote_active = polkit_policy_default_get_allow_remote_active (def);
+        default_local_inactive = polkit_policy_default_get_allow_local_inactive (def);
+        default_local_active = polkit_policy_default_get_allow_local_active (def);
+
+        printf ("Policy\n"
+                "------\n"
+                "group                   = %s ('%s') ('%s')\n"
+                "action                  = %s ('%s') ('%s') ('%s')\n"
+                "default_remote_inactive = %s\n"
+                "default_remote_active   = %s\n"
+                "default_local_inactive  = %s\n"
+                "default_local_active    = %s\n"
+                "\n", 
+                group_id, 
+                polkit_policy_file_get_group_description (pfe),
+                polkit_policy_file_get_group_description_short (pfe),
+                action_id,
+                polkit_policy_file_get_action_description (pfe),
+                polkit_policy_file_get_action_missing (pfe),
+                polkit_policy_file_get_action_apply_to_all_mnemonic (pfe),
+                polkit_result_to_string_representation (default_remote_inactive),
+                polkit_result_to_string_representation (default_remote_active),
+                polkit_result_to_string_representation (default_local_inactive),
+                polkit_result_to_string_representation (default_local_active));
+}
+
+int
+main (int argc, char *argv[])
+{
+        int n;
+
+        for (n = 1; n < argc; n++) {
+                if (strcmp (argv[n], "--help") == 0) {
+                        usage (argc, argv);
+                        return 0;
+                }
+                if (strcmp (argv[n], "--version") == 0) {
+                        printf ("polkit-list-actions " PACKAGE_VERSION "\n");
+                        return 0;
+                }
+	}
+
+        int ret;
+        ret = 1;
+
+        PolKitContext *ctx;
+        PolKitPolicyCache *cache;
+        PolKitError *error;
+        ctx = polkit_context_new ();
+        if (ctx == NULL)
+                goto out;
+        error = NULL;
+        polkit_context_set_load_descriptions (ctx);
+        if (!polkit_context_init (ctx, &error)) {
+                printf ("Init failed: %s\n", polkit_error_get_error_message (error));
+                polkit_context_unref (ctx);
+                goto out;
+        }
+
+        cache = polkit_context_get_policy_cache (ctx);
+        if (cache == NULL) {
+                polkit_context_unref (ctx);
+                goto out;
+        }
+
+        polkit_policy_cache_foreach (cache, _print_entry, NULL);
+
+        polkit_context_unref (ctx);
+out:
+        return ret;
+}
diff --git a/tools/polkit-policy-file-validate.c b/tools/polkit-policy-file-validate.c
index 4bd1d76..1ad5035 100644
--- a/tools/polkit-policy-file-validate.c
+++ b/tools/polkit-policy-file-validate.c
@@ -61,7 +61,7 @@ validate_file (const char *file)
         PolKitError *error;
 
         error = NULL;
-        priv_file = polkit_policy_file_new (file, &error);
+        priv_file = polkit_policy_file_new (file, TRUE, &error);
         if (priv_file == NULL) {
                 printf ("%s did not validate: %s\n", file, polkit_error_get_error_message (error));
                 polkit_error_free (error);


More information about the hal-commit mailing list