1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 /*
3 * GData Client
4 * Copyright (C) Thibault Saunier 2009 <saunierthibault@gmail.com>
5 * Copyright (C) Philip Withnall 2009–2010, 2014 <philip@tecnocode.co.uk>
6 * Copyright (C) Red Hat, Inc. 2015
7 *
8 * GData Client is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * GData Client is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with GData Client. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 /**
23 * SECTION:gdata-access-rule
24 * @short_description: GData access rule object
25 * @stability: Stable
26 * @include: gdata/gdata-access-rule.h
27 *
28 * #GDataAccessRule is a subclass of #GDataEntry to represent a generic access rule from an access control list (ACL).
29 * It is returned by the ACL methods implemented in the #GDataAccessHandler interface.
30 *
31 * Access rules should be inserted to the %GDATA_LINK_ACCESS_CONTROL_LIST URI of the feed or entry they should be applied to. This will return a
32 * %GDATA_SERVICE_ERROR_CONFLICT error if a rule already exists on that feed or entry for that scope type and value.
33 *
34 * <example>
35 * <title>Adding a Rule to the Access Control List for an Entry</title>
36 * <programlisting>
37 * GDataAuthorizationDomain *domain;
38 * GDataService *service;
39 * GDataEntry *entry;
40 * GDataFeed *acl_feed;
41 * GDataAccessRule *rule, *new_rule;
42 * GError *error = NULL;
43 *
44 * domain = gdata_documents_service_get_primary_authorization_domain ();
45 *
46 * /<!-- -->* Retrieve a GDataEntry which will have a new rule inserted into its ACL. *<!-- -->/
47 * service = build_my_service ();
48 * entry = get_the_entry (service);
49 *
50 * /<!-- -->* Create and insert a new access rule for example@gmail.com which grants them _no_ permissions on the entry.
51 * * In a real application, the GDataEntry subclass would define its own access roles which are more useful. For example,
52 * * GDataDocumentsEntry defines access roles for users who can read (but not write) a Google Document, and users who
53 * * can also write to the document. *<!-- -->/
54 * rule = gdata_access_rule_new (NULL);
55 * gdata_access_rule_set_role (rule, GDATA_ACCESS_ROLE_NONE); /<!-- -->* or, for example, GDATA_DOCUMENTS_ACCESS_ROLE_READER *<!-- -->/
56 * gdata_access_rule_set_scope (rule, GDATA_ACCESS_SCOPE_USER, "example@gmail.com"); /<!-- -->* e-mail address of the user the ACL applies to *<!-- -->/
57 *
58 * acl_link = gdata_entry_look_up_link (entry, GDATA_LINK_ACCESS_CONTROL_LIST);
59 * new_rule = GDATA_ACCESS_RULE (gdata_service_insert_entry (GDATA_SERVICE (service), domain, gdata_link_get_uri (acl_link),
60 * GDATA_ENTRY (rule), NULL, &error));
61 *
62 * g_object_unref (rule);
63 * g_object_unref (entry);
64 * g_object_unref (service);
65 *
66 * if (error != NULL) {
67 * g_error ("Error inserting access rule: %s", error->message);
68 * g_error_free (error);
69 * return;
70 * }
71 *
72 * /<!-- -->* Potentially do something with the new_rule here, such as store its ID for later use. *<!-- -->/
73 *
74 * g_object_unref (new_rule);
75 * </programlisting>
76 * </example>
77 *
78 * Since: 0.3.0
79 */
80
81 #include <config.h>
82 #include <glib.h>
83 #include <libxml/parser.h>
84 #include <string.h>
85
86 #include "gdata-access-rule.h"
87 #include "gdata-parser.h"
88 #include "gdata-types.h"
89 #include "gdata-private.h"
90
91 static GObject *gdata_access_rule_constructor (GType type, guint n_construct_params, GObjectConstructParam *construct_params);
92 static void gdata_access_rule_finalize (GObject *object);
93 static void get_namespaces (GDataParsable *parsable, GHashTable *namespaces);
94 static void get_xml (GDataParsable *parsable, GString *xml_string);
95 static void gdata_access_rule_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec);
96 static void gdata_access_rule_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec);
97 static gboolean parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_data, GError **error);
98 static gboolean post_parse_xml (GDataParsable *parsable, gpointer user_data, GError **error);
99
100 struct _GDataAccessRulePrivate {
101 gchar *role;
102 gchar *scope_type;
103 gchar *scope_value;
104 gint64 edited;
105 gchar *key;
106 };
107
108 enum {
109 PROP_ROLE = 1,
110 PROP_SCOPE_TYPE,
111 PROP_SCOPE_VALUE,
112 PROP_EDITED,
113 PROP_ETAG,
114 PROP_KEY,
115 };
116
G_DEFINE_TYPE(GDataAccessRule,gdata_access_rule,GDATA_TYPE_ENTRY)117 G_DEFINE_TYPE (GDataAccessRule, gdata_access_rule, GDATA_TYPE_ENTRY)
118
119 static void
120 gdata_access_rule_class_init (GDataAccessRuleClass *klass)
121 {
122 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
123 GDataParsableClass *parsable_class = GDATA_PARSABLE_CLASS (klass);
124 GDataEntryClass *entry_class = GDATA_ENTRY_CLASS (klass);
125
126 g_type_class_add_private (klass, sizeof (GDataAccessRulePrivate));
127
128 gobject_class->constructor = gdata_access_rule_constructor;
129 gobject_class->finalize = gdata_access_rule_finalize;
130 gobject_class->get_property = gdata_access_rule_get_property;
131 gobject_class->set_property = gdata_access_rule_set_property;
132
133 parsable_class->parse_xml = parse_xml;
134 parsable_class->post_parse_xml = post_parse_xml;
135 parsable_class->get_xml = get_xml;
136 parsable_class->get_namespaces = get_namespaces;
137
138 entry_class->kind_term = "http://schemas.google.com/acl/2007#accessRule";
139
140 /**
141 * GDataAccessRule:role:
142 *
143 * The role of the person concerned by this ACL. By default, this can only be %GDATA_ACCESS_ROLE_NONE. Services may extend it with
144 * their own namespaced roles.
145 *
146 * Since: 0.3.0
147 */
148 g_object_class_install_property (gobject_class, PROP_ROLE,
149 g_param_spec_string ("role",
150 "Role", "The role of the person concerned by this ACL.",
151 GDATA_ACCESS_ROLE_NONE,
152 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
153
154 /**
155 * GDataAccessRule:scope-type:
156 *
157 * Specifies to whom this access rule applies. For example, %GDATA_ACCESS_SCOPE_USER or %GDATA_ACCESS_SCOPE_DEFAULT.
158 *
159 * Since: 0.3.0
160 */
161 g_object_class_install_property (gobject_class, PROP_SCOPE_TYPE,
162 g_param_spec_string ("scope-type",
163 "Scope type", "Specifies to whom this access rule applies.",
164 GDATA_ACCESS_SCOPE_DEFAULT,
165 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
166
167 /**
168 * GDataAccessRule:scope-value:
169 *
170 * A value representing the user who is represented by the access rule, such as an
171 * e-mail address for users, or a domain name for domains.
172 *
173 * This must be %NULL if and only if #GDataAccessRule:scope-type is %GDATA_ACCESS_SCOPE_DEFAULT.
174 *
175 * Since: 0.3.0
176 */
177 g_object_class_install_property (gobject_class, PROP_SCOPE_VALUE,
178 g_param_spec_string ("scope-value",
179 "Scope value", "The scope value for this access rule.",
180 NULL,
181 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
182
183 /**
184 * GDataAccessRule:edited:
185 *
186 * The last time the access rule was edited. If the rule has not been edited yet, the content indicates the time it was created.
187 *
188 * For more information, see the <ulink type="http" url="http://www.atomenabled.org/developers/protocol/#appEdited">
189 * Atom Publishing Protocol specification</ulink>.
190 *
191 * Since: 0.7.0
192 */
193 g_object_class_install_property (gobject_class, PROP_EDITED,
194 g_param_spec_int64 ("edited",
195 "Edited", "The last time the access rule was edited.",
196 -1, G_MAXINT64, -1,
197 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
198
199 /**
200 * GDataAccessRule:key:
201 *
202 * An optional authorisation key required to access this item with the given scope. If set, this restricts
203 * access to those principals who have a copy of the key. The key is generated server-side and cannot be
204 * modified by the client. If no authorisation key is set (and hence none is needed for access to the item),
205 * this will be %NULL.
206 *
207 * Since: 0.16.0
208 */
209 g_object_class_install_property (gobject_class, PROP_KEY,
210 g_param_spec_string ("key",
211 "Key", "An optional authorisation key required to access this item.",
212 NULL,
213 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
214
215 /* Override the ETag property since ETags don't seem to be supported for ACL entries. TODO: Investigate this further (might only be
216 * unsupported for Google Calendar). */
217 g_object_class_override_property (gobject_class, PROP_ETAG, "etag");
218 }
219
220 static void notify_role_cb (GDataAccessRule *self, GParamSpec *pspec, gpointer user_data);
221
222 static void
notify_title_cb(GDataAccessRule * self,GParamSpec * pspec,gpointer user_data)223 notify_title_cb (GDataAccessRule *self, GParamSpec *pspec, gpointer user_data)
224 {
225 /* Update GDataAccessRule:role */
226 g_signal_handlers_block_by_func (self, notify_role_cb, self);
227 gdata_access_rule_set_role (self, gdata_entry_get_title (GDATA_ENTRY (self)));
228 g_signal_handlers_unblock_by_func (self, notify_role_cb, self);
229 }
230
231 static void
notify_role_cb(GDataAccessRule * self,GParamSpec * pspec,gpointer user_data)232 notify_role_cb (GDataAccessRule *self, GParamSpec *pspec, gpointer user_data)
233 {
234 /* Update GDataEntry:title */
235 g_signal_handlers_block_by_func (self, notify_title_cb, self);
236 gdata_entry_set_title (GDATA_ENTRY (self), gdata_access_rule_get_role (self));
237 g_signal_handlers_unblock_by_func (self, notify_title_cb, self);
238 }
239
240 static void
gdata_access_rule_init(GDataAccessRule * self)241 gdata_access_rule_init (GDataAccessRule *self)
242 {
243 self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GDATA_TYPE_ACCESS_RULE, GDataAccessRulePrivate);
244 self->priv->edited = -1;
245
246 /* Listen to change notifications for the entry's title, since it's linked to GDataAccessRule:role */
247 g_signal_connect (self, "notify::title", (GCallback) notify_title_cb, self);
248 g_signal_connect (self, "notify::role", (GCallback) notify_role_cb, self);
249 }
250
251 static GObject *
gdata_access_rule_constructor(GType type,guint n_construct_params,GObjectConstructParam * construct_params)252 gdata_access_rule_constructor (GType type, guint n_construct_params, GObjectConstructParam *construct_params)
253 {
254 GObject *object;
255
256 /* Chain up to the parent class */
257 object = G_OBJECT_CLASS (gdata_access_rule_parent_class)->constructor (type, n_construct_params, construct_params);
258
259 /* We can't create these in init, or they would collide with the group and control created when parsing the XML */
260 if (_gdata_parsable_is_constructed_from_xml (GDATA_PARSABLE (object)) == FALSE) {
261 GDataAccessRulePrivate *priv = GDATA_ACCESS_RULE (object)->priv;
262 GTimeVal time_val;
263
264 /* Set the edited property to the current time (creation time). We don't do this in *_init() since that would cause
265 * setting it from parse_xml() to fail (duplicate element). */
266 g_get_current_time (&time_val);
267 priv->edited = time_val.tv_sec;
268
269 /* Set up the role and scope type */
270 priv->role = g_strdup (GDATA_ACCESS_ROLE_NONE);
271 priv->scope_type = g_strdup (GDATA_ACCESS_SCOPE_DEFAULT);
272 }
273
274 return object;
275 }
276
277 static void
gdata_access_rule_finalize(GObject * object)278 gdata_access_rule_finalize (GObject *object)
279 {
280 GDataAccessRulePrivate *priv = GDATA_ACCESS_RULE (object)->priv;
281
282 g_free (priv->role);
283 g_free (priv->scope_type);
284 g_free (priv->scope_value);
285 g_free (priv->key);
286
287 /* Chain up to the parent class */
288 G_OBJECT_CLASS (gdata_access_rule_parent_class)->finalize (object);
289 }
290
291 static void
gdata_access_rule_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)292 gdata_access_rule_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
293 {
294 GDataAccessRulePrivate *priv = GDATA_ACCESS_RULE (object)->priv;
295
296 switch (property_id) {
297 case PROP_ROLE:
298 g_value_set_string (value, priv->role);
299 break;
300 case PROP_SCOPE_TYPE:
301 g_value_set_string (value, priv->scope_type);
302 break;
303 case PROP_SCOPE_VALUE:
304 g_value_set_string (value, priv->scope_value);
305 break;
306 case PROP_EDITED:
307 g_value_set_int64 (value, priv->edited);
308 break;
309 case PROP_ETAG:
310 /* Never return an ETag */
311 g_value_set_string (value, NULL);
312 break;
313 case PROP_KEY:
314 g_value_set_string (value, priv->key);
315 break;
316 default:
317 /* We don't have any other property... */
318 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
319 break;
320 }
321 }
322
323 static void
gdata_access_rule_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)324 gdata_access_rule_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
325 {
326 GDataAccessRule *self = GDATA_ACCESS_RULE (object);
327
328 switch (property_id) {
329 case PROP_ROLE:
330 gdata_access_rule_set_role (self, g_value_get_string (value));
331 break;
332 case PROP_SCOPE_TYPE:
333 g_free (self->priv->scope_type);
334 self->priv->scope_type = g_value_dup_string (value);
335 g_object_notify (object, "scope-type");
336 break;
337 case PROP_SCOPE_VALUE:
338 g_free (self->priv->scope_value);
339 self->priv->scope_value = g_value_dup_string (value);
340 g_object_notify (object, "scope-value");
341 break;
342 case PROP_ETAG:
343 /* Never set an ETag (note that this doesn't stop it being set in GDataEntry due to XML parsing) */
344 break;
345 case PROP_KEY:
346 /* Read only; fall through */
347 default:
348 /* We don't have any other property... */
349 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
350 break;
351 }
352 }
353
354 static gboolean
parse_xml(GDataParsable * parsable,xmlDoc * doc,xmlNode * node,gpointer user_data,GError ** error)355 parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_data, GError **error)
356 {
357 gboolean success;
358 GDataAccessRule *self = GDATA_ACCESS_RULE (parsable);
359
360 if (gdata_parser_is_namespace (node, "http://www.w3.org/2007/app") == TRUE &&
361 gdata_parser_int64_time_from_element (node, "edited", P_REQUIRED | P_NO_DUPES, &(self->priv->edited), &success, error) == TRUE) {
362 return success;
363 } else if (gdata_parser_is_namespace (node, "http://schemas.google.com/acl/2007") == TRUE) {
364 if (xmlStrcmp (node->name, (xmlChar*) "role") == 0) {
365 /* gAcl:role */
366 xmlChar *role = xmlGetProp (node, (xmlChar*) "value");
367 if (role == NULL || *role == '\0') {
368 xmlFree (role);
369 return gdata_parser_error_required_property_missing (node, "value", error);
370 }
371 self->priv->role = (gchar*) role;
372 } else if (xmlStrcmp (node->name, (xmlChar*) "scope") == 0) {
373 /* gAcl:scope */
374 xmlChar *scope_type, *scope_value;
375
376 scope_type = xmlGetProp (node, (xmlChar*) "type");
377 if (scope_type == NULL || *scope_type == '\0') {
378 xmlFree (scope_type);
379 return gdata_parser_error_required_property_missing (node, "type", error);
380 }
381
382 scope_value = xmlGetProp (node, (xmlChar*) "value");
383
384 /* The @value property is required for all scope types except "default".
385 * See: https://developers.google.com/google-apps/calendar/v2/reference#gacl_reference */
386 if (xmlStrcmp (scope_type, (xmlChar*) GDATA_ACCESS_SCOPE_DEFAULT) != 0 && scope_value == NULL) {
387 xmlFree (scope_type);
388 return gdata_parser_error_required_property_missing (node, "value", error);
389 }
390
391 self->priv->scope_type = (gchar*) scope_type;
392 self->priv->scope_value = (gchar*) scope_value;
393 } else if (xmlStrcmp (node->name, (xmlChar*) "withKey") == 0) {
394 /* gAcl:withKey */
395 gboolean found_role = FALSE;
396 xmlNode *child;
397 xmlChar *key;
398
399 /* Extract the key. */
400 key = xmlGetProp (node, (xmlChar *) "key");
401 if (key == NULL) {
402 return gdata_parser_error_required_property_missing (node, "key", error);
403 }
404
405 self->priv->key = (gchar *) key;
406
407 /* Look for a gAcl:role child element. */
408 for (child = node->children; child != NULL; child = child->next) {
409 if (xmlStrcmp (child->name, (xmlChar*) "role") == 0) {
410 xmlChar *role = xmlGetProp (child, (xmlChar *) "value");
411 if (role == NULL) {
412 return gdata_parser_error_required_property_missing (child, "value", error);
413 }
414
415 self->priv->role = (gchar *) role;
416 found_role = TRUE;
417 } else {
418 /* TODO: this logic copied from gdata-parsable.c. Re-evaluate this at some point in the future.
419 * If GeoRSS and GML support were to be used more widely, it might due to implement GML objects. */
420 xmlBuffer *buffer;
421
422 /* Unhandled XML */
423 buffer = xmlBufferCreate ();
424 xmlNodeDump (buffer, doc, child, 0, 0);
425 g_debug ("Unhandled XML in <gAcl:withKey>: %s", (gchar *) xmlBufferContent (buffer));
426 xmlBufferFree (buffer);
427 }
428 }
429
430 if (!found_role) {
431 return gdata_parser_error_required_element_missing ("role", "gAcl:withKey", error);
432 }
433 } else {
434 return GDATA_PARSABLE_CLASS (gdata_access_rule_parent_class)->parse_xml (parsable, doc, node, user_data, error);
435 }
436 } else {
437 return GDATA_PARSABLE_CLASS (gdata_access_rule_parent_class)->parse_xml (parsable, doc, node, user_data, error);
438 }
439
440 return TRUE;
441 }
442
443 static gboolean
post_parse_xml(GDataParsable * parsable,gpointer user_data,GError ** error)444 post_parse_xml (GDataParsable *parsable, gpointer user_data, GError **error)
445 {
446 GDataAccessRulePrivate *priv = GDATA_ACCESS_RULE (parsable)->priv;
447
448 /* Check for missing required elements */
449 if (gdata_entry_get_title (GDATA_ENTRY (parsable)) == NULL || *gdata_entry_get_title (GDATA_ENTRY (parsable)) == '\0')
450 return gdata_parser_error_required_element_missing ("role", "entry", error);
451 if (priv->scope_type == NULL)
452 return gdata_parser_error_required_element_missing ("scope", "entry", error);
453
454 return TRUE;
455 }
456
457 static void
get_xml(GDataParsable * parsable,GString * xml_string)458 get_xml (GDataParsable *parsable, GString *xml_string)
459 {
460 GDataAccessRulePrivate *priv = GDATA_ACCESS_RULE (parsable)->priv;
461
462 /* Chain up to the parent class */
463 GDATA_PARSABLE_CLASS (gdata_access_rule_parent_class)->get_xml (parsable, xml_string);
464
465 if (priv->key != NULL) {
466 /* gAcl:withKey; has to wrap gAcl:role */
467 gdata_parser_string_append_escaped (xml_string, "<gAcl:withKey key='", priv->key, "'>");
468 }
469
470 if (priv->role != NULL) {
471 /* gAcl:role */
472 gdata_parser_string_append_escaped (xml_string, "<gAcl:role value='", priv->role, "'/>");
473 }
474
475 if (priv->key != NULL) {
476 g_string_append (xml_string, "</gAcl:withKey>");
477 }
478
479 if (priv->scope_value != NULL) {
480 /* gAcl:scope */
481 if (priv->scope_type != NULL) {
482 gdata_parser_string_append_escaped (xml_string, "<gAcl:scope type='", priv->scope_type, "'");
483 gdata_parser_string_append_escaped (xml_string, " value='", priv->scope_value, "'/>");
484 } else {
485 gdata_parser_string_append_escaped (xml_string, "<gAcl:scope value='", priv->scope_value, "'/>");
486 }
487 } else {
488 /* gAcl:scope of type GDATA_ACCESS_SCOPE_DEFAULT. */
489 g_assert (priv->scope_type != NULL && strcmp (priv->scope_type, GDATA_ACCESS_SCOPE_DEFAULT) == 0);
490 g_string_append (xml_string, "<gAcl:scope type='default'/>");
491 }
492 }
493
494 static void
get_namespaces(GDataParsable * parsable,GHashTable * namespaces)495 get_namespaces (GDataParsable *parsable, GHashTable *namespaces)
496 {
497 /* Chain up to the parent class */
498 GDATA_PARSABLE_CLASS (gdata_access_rule_parent_class)->get_namespaces (parsable, namespaces);
499
500 g_hash_table_insert (namespaces, (gchar*) "gAcl", (gchar*) "http://schemas.google.com/acl/2007");
501 }
502
503 /**
504 * gdata_access_rule_new:
505 * @id: the access rule's ID, or %NULL
506 *
507 * Creates a new #GDataAccessRule with the given ID and default properties.
508 *
509 * Return value: a new #GDataAccessRule; unref with g_object_unref()
510 *
511 * Since: 0.3.0
512 */
513 GDataAccessRule *
gdata_access_rule_new(const gchar * id)514 gdata_access_rule_new (const gchar *id)
515 {
516 return GDATA_ACCESS_RULE (g_object_new (GDATA_TYPE_ACCESS_RULE, "id", id, NULL));
517 }
518
519 /**
520 * gdata_access_rule_set_role:
521 * @self: a #GDataAccessRule
522 * @role: a new role, or %NULL
523 *
524 * Sets the #GDataAccessRule:role property to @role. @role must be a non-empty string, such as %GDATA_ACCESS_ROLE_NONE.
525 *
526 * Set @role to %NULL to unset the property in the access rule.
527 *
528 * Since: 0.3.0
529 */
530 void
gdata_access_rule_set_role(GDataAccessRule * self,const gchar * role)531 gdata_access_rule_set_role (GDataAccessRule *self, const gchar *role)
532 {
533 g_return_if_fail (GDATA_IS_ACCESS_RULE (self));
534 g_return_if_fail (role == NULL || *role != '\0');
535
536 g_free (self->priv->role);
537 self->priv->role = g_strdup (role);
538 g_object_notify (G_OBJECT (self), "role");
539 }
540
541 /**
542 * gdata_access_rule_get_role:
543 * @self: a #GDataAccessRule
544 *
545 * Gets the #GDataAccessRule:role property.
546 *
547 * Return value: the access rule's role, or %NULL
548 *
549 * Since: 0.3.0
550 */
551 const gchar *
gdata_access_rule_get_role(GDataAccessRule * self)552 gdata_access_rule_get_role (GDataAccessRule *self)
553 {
554 g_return_val_if_fail (GDATA_IS_ACCESS_RULE (self), NULL);
555 return self->priv->role;
556 }
557
558
559 /**
560 * gdata_access_rule_set_scope:
561 * @self: a #GDataAccessRule
562 * @type: a new scope type
563 * @value: (allow-none): a new scope value, or %NULL
564 *
565 * Sets the #GDataAccessRule:scope-type property to @type and the #GDataAccessRule:scope-value property to @value.
566 *
567 * Set @scope_value to %NULL to unset the #GDataAccessRule:scope-value property in the access rule. @type cannot
568 * be %NULL. @scope_value must be %NULL if @type is <literal>default</literal>, and non-%NULL otherwise.
569 *
570 * See the
571 * <ulink type="http" url="https://developers.google.com/google-apps/calendar/v3/reference/acl">online
572 * documentation</ulink> for more information.
573 *
574 * Since: 0.3.0
575 */
576 void
gdata_access_rule_set_scope(GDataAccessRule * self,const gchar * type,const gchar * value)577 gdata_access_rule_set_scope (GDataAccessRule *self, const gchar *type, const gchar *value)
578 {
579 g_return_if_fail (GDATA_IS_ACCESS_RULE (self));
580 g_return_if_fail (type != NULL && *type != '\0');
581 g_return_if_fail ((strcmp (type, GDATA_ACCESS_SCOPE_DEFAULT) == 0 && value == NULL) || value != NULL);
582
583 g_free (self->priv->scope_type);
584 self->priv->scope_type = g_strdup (type);
585
586 g_free (self->priv->scope_value);
587 self->priv->scope_value = g_strdup (value);
588
589 g_object_freeze_notify (G_OBJECT (self));
590 g_object_notify (G_OBJECT (self), "scope-type");
591 g_object_notify (G_OBJECT (self), "scope-value");
592 g_object_thaw_notify (G_OBJECT (self));
593 }
594
595 /**
596 * gdata_access_rule_get_scope:
597 * @self: a #GDataAccessRule
598 * @type: (out callee-allocates) (transfer none) (allow-none): return location for the scope type, or %NULL
599 * @value: (out callee-allocates) (transfer none) (allow-none): return location for the scope value, or %NULL
600 *
601 * Gets the #GDataAccessRule:scope-type and #GDataAccessRule:scope-value properties.
602 *
603 * Since: 0.3.0
604 */
605 void
gdata_access_rule_get_scope(GDataAccessRule * self,const gchar ** type,const gchar ** value)606 gdata_access_rule_get_scope (GDataAccessRule *self, const gchar **type, const gchar **value)
607 {
608 g_return_if_fail (GDATA_IS_ACCESS_RULE (self));
609 if (type != NULL)
610 *type = self->priv->scope_type;
611 if (value != NULL)
612 *value = self->priv->scope_value;
613 }
614
615 /**
616 * gdata_access_rule_get_edited:
617 * @self: a #GDataAccessRule
618 *
619 * Gets the #GDataAccessRule:edited property. If the property is unset, <code class="literal">-1</code> will be returned.
620 *
621 * Return value: the UNIX timestamp for the time the access rule was last edited, or <code class="literal">-1</code>
622 *
623 * Since: 0.7.0
624 */
625 gint64
gdata_access_rule_get_edited(GDataAccessRule * self)626 gdata_access_rule_get_edited (GDataAccessRule *self)
627 {
628 g_return_val_if_fail (GDATA_IS_ACCESS_RULE (self), -1);
629 return self->priv->edited;
630 }
631
632 void
_gdata_access_rule_set_key(GDataAccessRule * self,const gchar * key)633 _gdata_access_rule_set_key (GDataAccessRule *self, const gchar *key)
634 {
635 g_return_if_fail (GDATA_IS_ACCESS_RULE (self));
636
637 if (g_strcmp0 (key, self->priv->key) == 0)
638 return;
639
640 g_free (self->priv->key);
641 self->priv->key = g_strdup (key);
642
643 g_object_notify (G_OBJECT (self), "key");
644 }
645
646 /**
647 * gdata_access_rule_get_key:
648 * @self: a #GDataAccessRule
649 *
650 * Gets the #GDataAccessRule:key property.
651 *
652 * Return value: the access rule's authorisation key, or %NULL
653 *
654 * Since: 0.16.0
655 */
656 const gchar *
gdata_access_rule_get_key(GDataAccessRule * self)657 gdata_access_rule_get_key (GDataAccessRule *self)
658 {
659 g_return_val_if_fail (GDATA_IS_ACCESS_RULE (self), NULL);
660 return self->priv->key;
661 }
662