|
Packit |
4b6dd7 |
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
|
|
Packit |
4b6dd7 |
/*
|
|
Packit |
4b6dd7 |
* GData Client
|
|
Packit |
4b6dd7 |
* Copyright (C) Philip Withnall 2009–2010, 2015 <philip@tecnocode.co.uk>
|
|
Packit |
4b6dd7 |
* Copyright (C) Red Hat, Inc. 2015
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* GData Client is free software; you can redistribute it and/or
|
|
Packit |
4b6dd7 |
* modify it under the terms of the GNU Lesser General Public
|
|
Packit |
4b6dd7 |
* License as published by the Free Software Foundation; either
|
|
Packit |
4b6dd7 |
* version 2.1 of the License, or (at your option) any later version.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* GData Client is distributed in the hope that it will be useful,
|
|
Packit |
4b6dd7 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
4b6dd7 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
4b6dd7 |
* Lesser General Public License for more details.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit |
4b6dd7 |
* License along with GData Client. If not, see <http://www.gnu.org/licenses/>.
|
|
Packit |
4b6dd7 |
*/
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
/**
|
|
Packit |
4b6dd7 |
* SECTION:gdata-access-handler
|
|
Packit |
4b6dd7 |
* @short_description: GData access handler interface
|
|
Packit |
4b6dd7 |
* @stability: Stable
|
|
Packit |
4b6dd7 |
* @include: gdata/gdata-access-handler.h
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* #GDataAccessHandler is an interface which can be implemented by #GDataEntrys which can have their permissions controlled by an
|
|
Packit |
4b6dd7 |
* access control list (ACL). It has a set of methods which allow the #GDataAccessRules for the access handler/entry to be retrieved,
|
|
Packit |
4b6dd7 |
* added, modified and deleted, with immediate effect.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* For an example of inserting an access rule into an ACL, see the documentation for #GDataAccessRule.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* When implementing the interface, classes must implement an <function>is_owner_rule</function> function. It's optional to implement a
|
|
Packit |
4b6dd7 |
* <function>get_authorization_domain</function> function, but if it's not implemented, any operations on the access handler's
|
|
Packit |
4b6dd7 |
* #GDataAccessRules will be performed unauthorized (i.e. as if by a non-logged-in user). This will not usually work.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Since: 0.3.0
|
|
Packit |
4b6dd7 |
*/
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
#include <config.h>
|
|
Packit |
4b6dd7 |
#include <glib.h>
|
|
Packit |
4b6dd7 |
#include <glib/gi18n-lib.h>
|
|
Packit |
4b6dd7 |
#include <string.h>
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
#include "gdata-access-handler.h"
|
|
Packit |
4b6dd7 |
#include "gdata-private.h"
|
|
Packit |
4b6dd7 |
#include "gdata-access-rule.h"
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
static GDataFeed *
|
|
Packit |
4b6dd7 |
gdata_access_handler_real_get_rules (GDataAccessHandler *self,
|
|
Packit |
4b6dd7 |
GDataService *service,
|
|
Packit |
4b6dd7 |
GCancellable *cancellable,
|
|
Packit |
4b6dd7 |
GDataQueryProgressCallback progress_callback,
|
|
Packit |
4b6dd7 |
gpointer progress_user_data,
|
|
Packit |
4b6dd7 |
GError **error);
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
typedef GDataAccessHandlerIface GDataAccessHandlerInterface;
|
|
Packit |
4b6dd7 |
G_DEFINE_INTERFACE (GDataAccessHandler, gdata_access_handler,
|
|
Packit |
4b6dd7 |
GDATA_TYPE_ENTRY);
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
static void
|
|
Packit |
4b6dd7 |
gdata_access_handler_default_init (GDataAccessHandlerInterface *iface)
|
|
Packit |
4b6dd7 |
{
|
|
Packit |
4b6dd7 |
iface->get_rules = gdata_access_handler_real_get_rules;
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
typedef struct {
|
|
Packit |
4b6dd7 |
GDataService *service;
|
|
Packit |
4b6dd7 |
GDataQueryProgressCallback progress_callback;
|
|
Packit |
4b6dd7 |
gpointer progress_user_data;
|
|
Packit |
4b6dd7 |
GDestroyNotify destroy_progress_user_data;
|
|
Packit |
4b6dd7 |
} GetRulesAsyncData;
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
static void
|
|
Packit |
4b6dd7 |
get_rules_async_data_free (GetRulesAsyncData *self)
|
|
Packit |
4b6dd7 |
{
|
|
Packit |
4b6dd7 |
if (self->service != NULL)
|
|
Packit |
4b6dd7 |
g_object_unref (self->service);
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
g_slice_free (GetRulesAsyncData, self);
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
static GDataFeed *
|
|
Packit |
4b6dd7 |
gdata_access_handler_real_get_rules (GDataAccessHandler *self,
|
|
Packit |
4b6dd7 |
GDataService *service,
|
|
Packit |
4b6dd7 |
GCancellable *cancellable,
|
|
Packit |
4b6dd7 |
GDataQueryProgressCallback progress_callback,
|
|
Packit |
4b6dd7 |
gpointer progress_user_data,
|
|
Packit |
4b6dd7 |
GError **error)
|
|
Packit |
4b6dd7 |
{
|
|
Packit |
4b6dd7 |
GDataAccessHandlerIface *iface;
|
|
Packit |
4b6dd7 |
GDataAuthorizationDomain *domain = NULL;
|
|
Packit |
4b6dd7 |
GDataFeed *feed;
|
|
Packit |
4b6dd7 |
GDataLink *_link;
|
|
Packit |
4b6dd7 |
SoupMessage *message;
|
|
Packit |
4b6dd7 |
SoupMessageHeaders *headers;
|
|
Packit |
4b6dd7 |
const gchar *content_type;
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
_link = gdata_entry_look_up_link (GDATA_ENTRY (self), GDATA_LINK_ACCESS_CONTROL_LIST);
|
|
Packit |
4b6dd7 |
g_assert (_link != NULL);
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
iface = GDATA_ACCESS_HANDLER_GET_IFACE (self);
|
|
Packit |
4b6dd7 |
if (iface->get_authorization_domain != NULL) {
|
|
Packit |
4b6dd7 |
domain = iface->get_authorization_domain (self);
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
message = _gdata_service_query (service, domain, gdata_link_get_uri (_link), NULL, cancellable, error);
|
|
Packit |
4b6dd7 |
if (message == NULL) {
|
|
Packit |
4b6dd7 |
return NULL;
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
g_assert (message->response_body->data != NULL);
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
headers = message->response_headers;
|
|
Packit |
4b6dd7 |
content_type = soup_message_headers_get_content_type (headers, NULL);
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
if (g_strcmp0 (content_type, "application/json") == 0) {
|
|
Packit |
4b6dd7 |
/* Definitely JSON. */
|
|
Packit |
4b6dd7 |
g_debug("JSON content type detected.");
|
|
Packit |
4b6dd7 |
feed = _gdata_feed_new_from_json (GDATA_TYPE_FEED, message->response_body->data, message->response_body->length, GDATA_TYPE_ACCESS_RULE,
|
|
Packit |
4b6dd7 |
progress_callback, progress_user_data, error);
|
|
Packit |
4b6dd7 |
} else {
|
|
Packit |
4b6dd7 |
/* Potentially XML. Don't bother checking the Content-Type, since the parser
|
|
Packit |
4b6dd7 |
* will fail gracefully if the response body is not valid XML. */
|
|
Packit |
4b6dd7 |
g_debug("XML content type detected.");
|
|
Packit |
4b6dd7 |
feed = _gdata_feed_new_from_xml (GDATA_TYPE_FEED, message->response_body->data, message->response_body->length, GDATA_TYPE_ACCESS_RULE,
|
|
Packit |
4b6dd7 |
progress_callback, progress_user_data, error);
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
g_object_unref (message);
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
return feed;
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
static void
|
|
Packit |
4b6dd7 |
get_rules_thread (GTask *task, gpointer source_object, gpointer task_data, GCancellable *cancellable)
|
|
Packit |
4b6dd7 |
{
|
|
Packit |
4b6dd7 |
GDataAccessHandler *access_handler = GDATA_ACCESS_HANDLER (source_object);
|
|
Packit |
4b6dd7 |
GDataAccessHandlerIface *iface;
|
|
Packit |
4b6dd7 |
g_autoptr(GError) error = NULL;
|
|
Packit |
4b6dd7 |
g_autoptr(GDataFeed) feed = NULL;
|
|
Packit |
4b6dd7 |
GetRulesAsyncData *data = task_data;
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
/* Execute the query and return */
|
|
Packit |
4b6dd7 |
iface = GDATA_ACCESS_HANDLER_GET_IFACE (access_handler);
|
|
Packit |
4b6dd7 |
g_assert (iface->get_rules != NULL);
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
feed = iface->get_rules (access_handler, data->service,
|
|
Packit |
4b6dd7 |
cancellable, data->progress_callback,
|
|
Packit |
4b6dd7 |
data->progress_user_data, &error);
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
if (feed == NULL && error != NULL)
|
|
Packit |
4b6dd7 |
g_task_return_error (task, g_steal_pointer (&error));
|
|
Packit |
4b6dd7 |
else
|
|
Packit |
4b6dd7 |
g_task_return_pointer (task, g_steal_pointer (&feed), g_object_unref);
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
if (data->destroy_progress_user_data != NULL) {
|
|
Packit |
4b6dd7 |
data->destroy_progress_user_data (data->progress_user_data);
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
/**
|
|
Packit |
4b6dd7 |
* gdata_access_handler_get_rules_async:
|
|
Packit |
4b6dd7 |
* @self: a #GDataAccessHandler
|
|
Packit |
4b6dd7 |
* @service: a #GDataService
|
|
Packit |
4b6dd7 |
* @cancellable: (allow-none): optional #GCancellable object, or %NULL
|
|
Packit |
4b6dd7 |
* @progress_callback: (allow-none) (closure progress_user_data): a #GDataQueryProgressCallback to call when a rule is loaded, or %NULL
|
|
Packit |
4b6dd7 |
* @progress_user_data: (closure): data to pass to the @progress_callback function
|
|
Packit |
4b6dd7 |
* @destroy_progress_user_data: (allow-none): the function to call when @progress_callback will not be called any more, or %NULL. This function will be
|
|
Packit |
4b6dd7 |
* called with @progress_user_data as a parameter and can be used to free any memory allocated for it.
|
|
Packit |
4b6dd7 |
* @callback: a #GAsyncReadyCallback to call when the query is finished
|
|
Packit |
4b6dd7 |
* @user_data: (closure): data to pass to the @callback function
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Retrieves a #GDataFeed containing all the access rules which apply to the given #GDataAccessHandler. Only the owner of a #GDataAccessHandler may
|
|
Packit |
4b6dd7 |
* view its rule feed. @self and @service are both reffed when this function is called, so can safely be unreffed after this function returns.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* For more details, see gdata_access_handler_get_rules(), which is the synchronous version of this function, and gdata_service_query_async(), which
|
|
Packit |
4b6dd7 |
* is the base asynchronous query function.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* When the operation is finished, @callback will be called. You can then call gdata_service_query_finish()
|
|
Packit |
4b6dd7 |
* to get the results of the operation.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Since: 0.9.1
|
|
Packit |
4b6dd7 |
*/
|
|
Packit |
4b6dd7 |
void
|
|
Packit |
4b6dd7 |
gdata_access_handler_get_rules_async (GDataAccessHandler *self, GDataService *service, GCancellable *cancellable,
|
|
Packit |
4b6dd7 |
GDataQueryProgressCallback progress_callback, gpointer progress_user_data,
|
|
Packit |
4b6dd7 |
GDestroyNotify destroy_progress_user_data,
|
|
Packit |
4b6dd7 |
GAsyncReadyCallback callback, gpointer user_data)
|
|
Packit |
4b6dd7 |
{
|
|
Packit |
4b6dd7 |
g_autoptr(GTask) task = NULL;
|
|
Packit |
4b6dd7 |
GetRulesAsyncData *data;
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
g_return_if_fail (GDATA_IS_ACCESS_HANDLER (self));
|
|
Packit |
4b6dd7 |
g_return_if_fail (GDATA_IS_SERVICE (service));
|
|
Packit |
4b6dd7 |
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
|
Packit |
4b6dd7 |
g_return_if_fail (callback != NULL);
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
data = g_slice_new (GetRulesAsyncData);
|
|
Packit |
4b6dd7 |
data->service = g_object_ref (service);
|
|
Packit |
4b6dd7 |
data->progress_callback = progress_callback;
|
|
Packit |
4b6dd7 |
data->progress_user_data = progress_user_data;
|
|
Packit |
4b6dd7 |
data->destroy_progress_user_data = destroy_progress_user_data;
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
task = g_task_new (self, cancellable, callback, user_data);
|
|
Packit |
4b6dd7 |
g_task_set_source_tag (task, gdata_service_query_async);
|
|
Packit |
4b6dd7 |
g_task_set_task_data (task, g_steal_pointer (&data), (GDestroyNotify) get_rules_async_data_free);
|
|
Packit |
4b6dd7 |
g_task_run_in_thread (task, get_rules_thread);
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
/**
|
|
Packit |
4b6dd7 |
* gdata_access_handler_get_rules:
|
|
Packit |
4b6dd7 |
* @self: a #GDataAccessHandler
|
|
Packit |
4b6dd7 |
* @service: a #GDataService
|
|
Packit |
4b6dd7 |
* @cancellable: (allow-none): optional #GCancellable object, or %NULL
|
|
Packit |
4b6dd7 |
* @progress_callback: (allow-none) (scope call) (closure progress_user_data): a #GDataQueryProgressCallback to call when a rule is loaded, or %NULL
|
|
Packit |
4b6dd7 |
* @progress_user_data: (closure): data to pass to the @progress_callback function
|
|
Packit |
4b6dd7 |
* @error: a #GError, or %NULL
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Retrieves a #GDataFeed containing all the access rules which apply to the given #GDataAccessHandler. Only the owner of a #GDataAccessHandler may
|
|
Packit |
4b6dd7 |
* view its rule feed.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* If @cancellable is not %NULL, then the operation can be cancelled by triggering the @cancellable object from another thread.
|
|
Packit |
4b6dd7 |
* If the operation was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* A %GDATA_SERVICE_ERROR_PROTOCOL_ERROR will be returned if the server indicates there is a problem with the query.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* For each rule in the response feed, @progress_callback will be called in the main thread. If there was an error parsing the XML response,
|
|
Packit |
4b6dd7 |
* a #GDataParserError will be returned.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Return value: (transfer full): a #GDataFeed of access control rules, or %NULL; unref with g_object_unref()
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Since: 0.3.0
|
|
Packit |
4b6dd7 |
*/
|
|
Packit |
4b6dd7 |
GDataFeed *
|
|
Packit |
4b6dd7 |
gdata_access_handler_get_rules (GDataAccessHandler *self, GDataService *service, GCancellable *cancellable,
|
|
Packit |
4b6dd7 |
GDataQueryProgressCallback progress_callback, gpointer progress_user_data, GError **error)
|
|
Packit |
4b6dd7 |
{
|
|
Packit |
4b6dd7 |
GDataAccessHandlerIface *iface;
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
g_return_val_if_fail (GDATA_IS_ACCESS_HANDLER (self), NULL);
|
|
Packit |
4b6dd7 |
g_return_val_if_fail (GDATA_IS_SERVICE (service), NULL);
|
|
Packit |
4b6dd7 |
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
|
|
Packit |
4b6dd7 |
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
iface = GDATA_ACCESS_HANDLER_GET_IFACE (self);
|
|
Packit |
4b6dd7 |
g_assert (iface->get_rules != NULL);
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
return iface->get_rules (self, service, cancellable, progress_callback,
|
|
Packit |
4b6dd7 |
progress_user_data, error);
|
|
Packit |
4b6dd7 |
}
|