[libgdata] core: Add support for ACL entries with keys
- From: Philip Withnall <pwithnall src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libgdata] core: Add support for ACL entries with keys
- Date: Sun, 24 Aug 2014 15:09:21 +0000 (UTC)
commit f817fdaff889764125c5f073be4fd433c5c33b14
Author: Philip Withnall <philip withnall collabora co uk>
Date: Sun Aug 24 16:05:42 2014 +0100
core: Add support for ACL entries with keys
This adds support for <gAcl:withKey/> elements, allowing for
authorisation keys in ACLs, e.g. for Google Documents.
This adds the following API:
• GDataAccessRule:key
• gdata_access_rule_get_key()
and appropriate tests.
https://bugzilla.gnome.org/show_bug.cgi?id=690628
docs/reference/gdata-sections.txt | 1 +
gdata/gdata-access-rule.c | 97 ++++++++++++++++++++++++++++++++++++-
gdata/gdata-access-rule.h | 1 +
gdata/gdata.symbols | 1 +
gdata/tests/general.c | 59 ++++++++++++++++++++++-
5 files changed, 156 insertions(+), 3 deletions(-)
---
diff --git a/docs/reference/gdata-sections.txt b/docs/reference/gdata-sections.txt
index 5426402..fdcac2f 100644
--- a/docs/reference/gdata-sections.txt
+++ b/docs/reference/gdata-sections.txt
@@ -691,6 +691,7 @@ gdata_access_rule_set_role
gdata_access_rule_get_scope
gdata_access_rule_set_scope
gdata_access_rule_get_edited
+gdata_access_rule_get_key
<SUBSECTION Standard>
gdata_access_rule_get_type
GDATA_ACCESS_RULE
diff --git a/gdata/gdata-access-rule.c b/gdata/gdata-access-rule.c
index 51409ac..220c2a4 100644
--- a/gdata/gdata-access-rule.c
+++ b/gdata/gdata-access-rule.c
@@ -2,7 +2,7 @@
/*
* GData Client
* Copyright (C) Thibault Saunier 2009 <saunierthibault gmail com>
- * Copyright (C) Philip Withnall 2009–2010 <philip tecnocode co uk>
+ * Copyright (C) Philip Withnall 2009–2010, 2014 <philip tecnocode co uk>
*
* GData Client is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -99,6 +99,7 @@ struct _GDataAccessRulePrivate {
gchar *scope_type;
gchar *scope_value;
gint64 edited;
+ gchar *key;
};
enum {
@@ -106,7 +107,8 @@ enum {
PROP_SCOPE_TYPE,
PROP_SCOPE_VALUE,
PROP_EDITED,
- PROP_ETAG
+ PROP_ETAG,
+ PROP_KEY,
};
G_DEFINE_TYPE (GDataAccessRule, gdata_access_rule, GDATA_TYPE_ENTRY)
@@ -190,6 +192,22 @@ gdata_access_rule_class_init (GDataAccessRuleClass *klass)
-1, G_MAXINT64, -1,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+ /**
+ * GDataAccessRule:key:
+ *
+ * An optional authorisation key required to access this item with the given scope. If set, this
restricts
+ * access to those principals who have a copy of the key. The key is generated server-side and cannot
be
+ * modified by the client. If no authorisation key is set (and hence none is needed for access to the
item),
+ * this will be %NULL.
+ *
+ * Since: UNRELEASED
+ */
+ g_object_class_install_property (gobject_class, PROP_KEY,
+ g_param_spec_string ("key",
+ "Key", "An optional authorisation key required
to access this item.",
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
/* Override the ETag property since ETags don't seem to be supported for ACL entries. TODO:
Investigate this further (might only be
* unsupported for Google Calendar). */
g_object_class_override_property (gobject_class, PROP_ETAG, "etag");
@@ -260,6 +278,7 @@ gdata_access_rule_finalize (GObject *object)
g_free (priv->role);
g_free (priv->scope_type);
g_free (priv->scope_value);
+ g_free (priv->key);
/* Chain up to the parent class */
G_OBJECT_CLASS (gdata_access_rule_parent_class)->finalize (object);
@@ -287,6 +306,9 @@ gdata_access_rule_get_property (GObject *object, guint property_id, GValue *valu
/* Never return an ETag */
g_value_set_string (value, NULL);
break;
+ case PROP_KEY:
+ g_value_set_string (value, priv->key);
+ break;
default:
/* We don't have any other property... */
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -316,6 +338,11 @@ gdata_access_rule_set_property (GObject *object, guint property_id, const GValue
case PROP_ETAG:
/* Never set an ETag (note that this doesn't stop it being set in GDataEntry due to
XML parsing) */
break;
+ case PROP_KEY:
+ g_free (self->priv->key);
+ self->priv->key = g_value_dup_string (value);
+ g_object_notify (object, "key");
+ break;
default:
/* We don't have any other property... */
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -358,6 +385,46 @@ parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_da
self->priv->scope_type = (gchar*) scope_type;
self->priv->scope_value = (gchar*) scope_value;
+ } else if (xmlStrcmp (node->name, (xmlChar*) "withKey") == 0) {
+ /* gAcl:withKey */
+ gboolean found_role = FALSE;
+ xmlNode *child;
+ xmlChar *key;
+
+ /* Extract the key. */
+ key = xmlGetProp (node, (xmlChar *) "key");
+ if (key == NULL) {
+ return gdata_parser_error_required_property_missing (node, "key", error);
+ }
+
+ self->priv->key = (gchar *) key;
+
+ /* Look for a gAcl:role child element. */
+ for (child = node->children; child != NULL; child = child->next) {
+ if (xmlStrcmp (child->name, (xmlChar*) "role") == 0) {
+ xmlChar *role = xmlGetProp (child, (xmlChar *) "value");
+ if (role == NULL) {
+ return gdata_parser_error_required_property_missing (child,
"value", error);
+ }
+
+ self->priv->role = (gchar *) role;
+ found_role = TRUE;
+ } else {
+ /* TODO: this logic copied from gdata-parsable.c. Re-evaluate this
at some point in the future.
+ * If GeoRSS and GML support were to be used more widely, it might
due to implement GML objects. */
+ xmlBuffer *buffer;
+
+ /* Unhandled XML */
+ buffer = xmlBufferCreate ();
+ xmlNodeDump (buffer, doc, child, 0, 0);
+ g_debug ("Unhandled XML in <gAcl:withKey>: %s", (gchar *)
xmlBufferContent (buffer));
+ xmlBufferFree (buffer);
+ }
+ }
+
+ if (!found_role) {
+ return gdata_parser_error_required_element_missing ("role", "gAcl:withKey",
error);
+ }
} else {
return GDATA_PARSABLE_CLASS (gdata_access_rule_parent_class)->parse_xml (parsable,
doc, node, user_data, error);
}
@@ -376,11 +443,20 @@ get_xml (GDataParsable *parsable, GString *xml_string)
/* Chain up to the parent class */
GDATA_PARSABLE_CLASS (gdata_access_rule_parent_class)->get_xml (parsable, xml_string);
+ if (priv->key != NULL) {
+ /* gAcl:withKey; has to wrap gAcl:role */
+ gdata_parser_string_append_escaped (xml_string, "<gAcl:withKey key='", priv->key, "'>");
+ }
+
if (priv->role != NULL) {
/* gAcl:role */
gdata_parser_string_append_escaped (xml_string, "<gAcl:role value='", priv->role, "'/>");
}
+ if (priv->key != NULL) {
+ g_string_append (xml_string, "</gAcl:withKey>");
+ }
+
if (priv->scope_value != NULL) {
/* gAcl:scope */
if (priv->scope_type != NULL) {
@@ -531,3 +607,20 @@ gdata_access_rule_get_edited (GDataAccessRule *self)
g_return_val_if_fail (GDATA_IS_ACCESS_RULE (self), -1);
return self->priv->edited;
}
+
+/**
+ * gdata_access_rule_get_key:
+ * @self: a #GDataAccessRule
+ *
+ * Gets the #GDataAccessRule:key property.
+ *
+ * Return value: the access rule's authorisation key, or %NULL
+ *
+ * Since: UNRELEASED
+ */
+const gchar *
+gdata_access_rule_get_key (GDataAccessRule *self)
+{
+ g_return_val_if_fail (GDATA_IS_ACCESS_RULE (self), NULL);
+ return self->priv->key;
+}
diff --git a/gdata/gdata-access-rule.h b/gdata/gdata-access-rule.h
index 483a871..29409a9 100644
--- a/gdata/gdata-access-rule.h
+++ b/gdata/gdata-access-rule.h
@@ -106,6 +106,7 @@ void gdata_access_rule_set_role (GDataAccessRule *self, const gchar *role);
void gdata_access_rule_get_scope (GDataAccessRule *self, const gchar **type, const gchar **value);
void gdata_access_rule_set_scope (GDataAccessRule *self, const gchar *type, const gchar *value);
gint64 gdata_access_rule_get_edited (GDataAccessRule *self);
+const gchar *gdata_access_rule_get_key (GDataAccessRule *self) G_GNUC_PURE;
G_END_DECLS
diff --git a/gdata/gdata.symbols b/gdata/gdata.symbols
index 3f3c1f0..5b83a42 100644
--- a/gdata/gdata.symbols
+++ b/gdata/gdata.symbols
@@ -307,6 +307,7 @@ gdata_access_rule_set_role
gdata_access_rule_get_scope
gdata_access_rule_set_scope
gdata_access_rule_get_edited
+gdata_access_rule_get_key
gdata_parsable_get_type
gdata_parsable_new_from_xml
gdata_parsable_get_xml
diff --git a/gdata/tests/general.c b/gdata/tests/general.c
index f920727..237a908 100644
--- a/gdata/tests/general.c
+++ b/gdata/tests/general.c
@@ -1471,7 +1471,7 @@ static void
test_access_rule_get_xml (void)
{
GDataAccessRule *rule, *rule2;
- gchar *xml, *role, *scope_type3, *scope_value3;
+ gchar *xml, *role, *scope_type3, *scope_value3, *key;
gint64 edited, edited2;
const gchar *scope_type, *scope_value, *scope_type2, *scope_value2;
GError *error = NULL;
@@ -1491,6 +1491,7 @@ test_access_rule_get_xml (void)
g_assert_cmpstr (scope_value, ==, "A scope value");
edited = gdata_access_rule_get_edited (rule);
g_assert_cmpuint (edited, >, 0); /* current time */
+ g_assert_cmpstr (gdata_access_rule_get_key (rule), ==, NULL);
/* Set the properties more conventionally */
gdata_access_rule_set_role (rule, GDATA_ACCESS_ROLE_NONE);
@@ -1524,6 +1525,7 @@ test_access_rule_get_xml (void)
g_assert_cmpstr (scope_value, ==, scope_value2);
edited = gdata_access_rule_get_edited (rule2);
g_assert_cmpuint (edited, ==, -1); /* unspecified in XML */
+ g_assert_cmpstr (gdata_access_rule_get_key (rule), ==, gdata_access_rule_get_key (rule2));
/* Check properties a different way */
g_object_get (G_OBJECT (rule2),
@@ -1531,12 +1533,14 @@ test_access_rule_get_xml (void)
"scope-type", &scope_type3,
"scope-value", &scope_value3,
"edited", &edited2,
+ "key", &key,
NULL);
g_assert_cmpstr (role, ==, gdata_access_rule_get_role (rule));
g_assert_cmpstr (scope_type, ==, scope_type3);
g_assert_cmpstr (scope_value, ==, scope_value3);
g_assert_cmpuint (edited2, ==, -1);
+ g_assert_cmpstr (key, ==, NULL);
g_free (role);
g_free (scope_type3);
@@ -1591,6 +1595,53 @@ test_access_rule_get_xml (void)
}
static void
+test_access_rule_get_xml_with_key (void)
+{
+ GDataAccessRule *rule;
+ gint64 edited;
+ const gchar *scope_type, *scope_value;
+ GError *error = NULL;
+
+ rule = GDATA_ACCESS_RULE (gdata_parsable_new_from_xml (GDATA_TYPE_ACCESS_RULE,
+ "<?xml version='1.0' encoding='UTF-8'?>"
+ "<entry xmlns='http://www.w3.org/2005/Atom' "
+ "xmlns:gd='http://schemas.google.com/g/2005' "
+ "xmlns:gAcl='http://schemas.google.com/acl/2007'>"
+ "<title type='text'>none</title>"
+ "<id>an-id</id>"
+ "<category term='http://schemas.google.com/acl/2007#accessRule'
scheme='http://schemas.google.com/g/2005#kind'/>"
+ "<gAcl:withKey key='asdasd'><gAcl:role value='none'/></gAcl:withKey>"
+ "<gAcl:scope type='user' value='foo example com'/>"
+ "</entry>", -1, &error));
+ g_assert_no_error (error);
+ g_assert (GDATA_IS_ACCESS_RULE (rule));
+
+ /* Check the properties. */
+ g_assert_cmpstr (gdata_access_rule_get_role (rule), ==, "none");
+ gdata_access_rule_get_scope (rule, &scope_type, &scope_value);
+ g_assert_cmpstr (scope_type, ==, "user");
+ g_assert_cmpstr (scope_value, ==, "foo example com");
+ edited = gdata_access_rule_get_edited (rule);
+ g_assert_cmpuint (edited, >, 0); /* current time */
+ g_assert_cmpstr (gdata_access_rule_get_key (rule), ==, "asdasd");
+
+ /* Check the outputted XML is the same. */
+ gdata_test_assert_xml (rule,
+ "<?xml version='1.0' encoding='UTF-8'?>"
+ "<entry xmlns='http://www.w3.org/2005/Atom' "
+ "xmlns:gd='http://schemas.google.com/g/2005' "
+ "xmlns:gAcl='http://schemas.google.com/acl/2007'>"
+ "<title type='text'>none</title>"
+ "<id>an-id</id>"
+ "<category term='http://schemas.google.com/acl/2007#accessRule'
scheme='http://schemas.google.com/g/2005#kind'/>"
+ "<gAcl:withKey key='asdasd'><gAcl:role value='none'/></gAcl:withKey>"
+ "<gAcl:scope type='user' value='foo example com'/>"
+ "</entry>");
+
+ g_object_unref (rule);
+}
+
+static void
test_access_rule_error_handling (void)
{
GDataAccessRule *rule;
@@ -1616,6 +1667,11 @@ test_access_rule_error_handling (void)
TEST_XML_ERROR_HANDLING ("<app:edited/>"); /* missing date */
TEST_XML_ERROR_HANDLING ("<app:edited>not a date</app:edited>"); /* bad date */
+ /* withKey */
+ TEST_XML_ERROR_HANDLING ("<gAcl:withKey><gAcl:role value='none'/></gAcl:withKey>"); /* missing key */
+ TEST_XML_ERROR_HANDLING ("<gAcl:withKey key='asd'/>"); /* missing role */
+ TEST_XML_ERROR_HANDLING ("<gAcl:withKey key='asd'><gAcl:role/></gAcl:withKey>"); /* missing role */
+
#undef TEST_XML_ERROR_HANDLING
}
@@ -4527,6 +4583,7 @@ main (int argc, char *argv[])
g_test_add_func ("/query/etag", test_query_etag);
g_test_add_func ("/access-rule/get_xml", test_access_rule_get_xml);
+ g_test_add_func ("/access-rule/get_xml/with_key", test_access_rule_get_xml_with_key);
g_test_add_func ("/access-rule/error_handling", test_access_rule_error_handling);
g_test_add_func ("/access-rule/escaping", test_access_rule_escaping);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]