|
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 <philip@tecnocode.co.uk>
|
|
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-contacts-service
|
|
Packit |
4b6dd7 |
* @short_description: GData Contacts service object
|
|
Packit |
4b6dd7 |
* @stability: Stable
|
|
Packit |
4b6dd7 |
* @include: gdata/services/contacts/gdata-contacts-service.h
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* #GDataContactsService is a subclass of #GDataService for communicating with the GData API of Google Contacts. It supports querying
|
|
Packit |
4b6dd7 |
* for, inserting, editing and deleting contacts from a Google address book.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* For more details of Google Contacts' GData API, see the <ulink type="http" url="http://code.google.com/apis/contacts/docs/2.0/reference.html">
|
|
Packit |
4b6dd7 |
* online documentation</ulink>.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* <example>
|
|
Packit |
4b6dd7 |
* <title>Querying for Groups</title>
|
|
Packit |
4b6dd7 |
* <programlisting>
|
|
Packit |
4b6dd7 |
* GDataContactsService *service;
|
|
Packit |
4b6dd7 |
* GDataFeed *feed;
|
|
Packit |
4b6dd7 |
* GList *i;
|
|
Packit |
4b6dd7 |
* GError *error = NULL;
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* /* Create a service */
|
|
Packit |
4b6dd7 |
* service = create_contacts_service ();
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* /* Query for groups */
|
|
Packit |
4b6dd7 |
* feed = gdata_contacts_service_query_groups (service, NULL, NULL, NULL, NULL, &error);
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* g_object_unref (service);
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* if (error != NULL) {
|
|
Packit |
4b6dd7 |
* g_error ("Error querying for groups: %s", error->message);
|
|
Packit |
4b6dd7 |
* g_error_free (error);
|
|
Packit |
4b6dd7 |
* return;
|
|
Packit |
4b6dd7 |
* }
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* /* Iterate through the returned groups and do something with them */
|
|
Packit |
4b6dd7 |
* for (i = gdata_feed_get_entries (feed); i != NULL; i = i->next) {
|
|
Packit |
4b6dd7 |
* const gchar *system_group_id, *group_name;
|
|
Packit |
4b6dd7 |
* gboolean is_system_group;
|
|
Packit |
4b6dd7 |
* GDataContactsGroup *group = GDATA_CONTACTS_GROUP (i->data);
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* /* Determine whether the group's a system group. If so, you should use the system group ID to provide your application's own
|
|
Packit |
4b6dd7 |
* * translations of the group name, as it's not translated. */
|
|
Packit |
4b6dd7 |
* system_group_id = gdata_contacts_group_get_system_group_id (group);
|
|
Packit |
4b6dd7 |
* is_system_group = (system_group_id != NULL) ? TRUE : FALSE;
|
|
Packit |
4b6dd7 |
* group_name = (is_system_group == TRUE) ? get_group_name_for_system_group_id (system_group_id)
|
|
Packit |
4b6dd7 |
* : gdata_entry_get_title (GDATA_ENTRY (group));
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* /* Do something with the group here, such as insert it into a UI. Note that system groups are not allowed to be deleted,
|
|
Packit |
4b6dd7 |
* * so you may want to make certain parts of your UI insensitive accordingly if the group is a system group. */
|
|
Packit |
4b6dd7 |
* }
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* g_object_unref (feed);
|
|
Packit |
4b6dd7 |
* </programlisting>
|
|
Packit |
4b6dd7 |
* </example>
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* The Contacts service can be manipulated using batch operations, too. See the
|
|
Packit |
4b6dd7 |
* <ulink type="http" url="http://code.google.com/apis/contacts/docs/3.0/developers_guide_protocol.html#Batch">online documentation on batch
|
|
Packit |
4b6dd7 |
* operations</ulink> for more information.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* <example>
|
|
Packit |
4b6dd7 |
* <title>Performing a Batch Operation on Contacts</title>
|
|
Packit |
4b6dd7 |
* <programlisting>
|
|
Packit |
4b6dd7 |
* GDataContactsService *service;
|
|
Packit |
4b6dd7 |
* GDataBatchOperation *operation;
|
|
Packit |
4b6dd7 |
* GDataFeed *feed;
|
|
Packit |
4b6dd7 |
* GDataLink *batch_link;
|
|
Packit |
4b6dd7 |
* GList *i;
|
|
Packit |
4b6dd7 |
* GError *error = NULL;
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* /* Create a service */
|
|
Packit |
4b6dd7 |
* service = create_contacts_service ();
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* /* Create the batch operation; this requires that we have done a query first so that we can get the batch link */
|
|
Packit |
4b6dd7 |
* feed = do_some_query (service);
|
|
Packit |
4b6dd7 |
* batch_link = gdata_feed_look_up_link (feed, GDATA_LINK_BATCH);
|
|
Packit |
4b6dd7 |
* operation = gdata_batchable_create_operation (GDATA_BATCHABLE (service), gdata_link_get_uri (batch_link));
|
|
Packit |
4b6dd7 |
* g_object_unref (feed);
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* gdata_batch_operation_add_query (operation, contact_entry_id_to_query, GDATA_TYPE_CONTACTS_CONTACT,
|
|
Packit |
4b6dd7 |
* (GDataBatchOperationCallback) batch_query_cb, user_data);
|
|
Packit |
4b6dd7 |
* gdata_batch_operation_add_insertion (operation, new_entry, (GDataBatchOperationCallback) batch_insertion_cb, user_data);
|
|
Packit |
4b6dd7 |
* gdata_batch_operation_add_update (operation, old_entry, (GDataBatchOperationCallback) batch_update_cb, user_data);
|
|
Packit |
4b6dd7 |
* gdata_batch_operation_add_deletion (operation, entry_to_delete, (GDataBatchOperationCallback) batch_deletion_cb, user_data);
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* /* Run the batch operation and handle the results in the various callbacks */
|
|
Packit |
4b6dd7 |
* gdata_test_batch_operation_run (operation, NULL, &error);
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* g_object_unref (operation);
|
|
Packit |
4b6dd7 |
* g_object_unref (service);
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* if (error != NULL) {
|
|
Packit |
4b6dd7 |
* g_error ("Error running batch operation: %s", error->message);
|
|
Packit |
4b6dd7 |
* g_error_free (error);
|
|
Packit |
4b6dd7 |
* return;
|
|
Packit |
4b6dd7 |
* }
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* static void
|
|
Packit |
4b6dd7 |
* batch_query_cb (guint operation_id, GDataBatchOperationType operation_type, GDataEntry *entry, GError *error, gpointer user_data)
|
|
Packit |
4b6dd7 |
* {
|
|
Packit |
4b6dd7 |
* /* operation_type == GDATA_BATCH_OPERATION_QUERY */
|
|
Packit |
4b6dd7 |
* /* Reference and do something with the returned entry. */
|
|
Packit |
4b6dd7 |
* }
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* static void
|
|
Packit |
4b6dd7 |
* batch_insertion_cb (guint operation_id, GDataBatchOperationType operation_type, GDataEntry *entry, GError *error, gpointer user_data)
|
|
Packit |
4b6dd7 |
* {
|
|
Packit |
4b6dd7 |
* /* operation_type == GDATA_BATCH_OPERATION_INSERTION */
|
|
Packit |
4b6dd7 |
* /* Reference and do something with the returned entry. */
|
|
Packit |
4b6dd7 |
* }
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* static void
|
|
Packit |
4b6dd7 |
* batch_update_cb (guint operation_id, GDataBatchOperationType operation_type, GDataEntry *entry, GError *error, gpointer user_data)
|
|
Packit |
4b6dd7 |
* {
|
|
Packit |
4b6dd7 |
* /* operation_type == GDATA_BATCH_OPERATION_UPDATE */
|
|
Packit |
4b6dd7 |
* /* Reference and do something with the returned entry. */
|
|
Packit |
4b6dd7 |
* }
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* static void
|
|
Packit |
4b6dd7 |
* batch_deletion_cb (guint operation_id, GDataBatchOperationType operation_type, GDataEntry *entry, GError *error, gpointer user_data)
|
|
Packit |
4b6dd7 |
* {
|
|
Packit |
4b6dd7 |
* /* operation_type == GDATA_BATCH_OPERATION_DELETION, entry == NULL */
|
|
Packit |
4b6dd7 |
* }
|
|
Packit |
4b6dd7 |
* </programlisting>
|
|
Packit |
4b6dd7 |
* </example>
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Since: 0.2.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 <libsoup/soup.h>
|
|
Packit |
4b6dd7 |
#include <string.h>
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
#include "gdata-contacts-service.h"
|
|
Packit |
4b6dd7 |
#include "gdata-batchable.h"
|
|
Packit |
4b6dd7 |
#include "gdata-service.h"
|
|
Packit |
4b6dd7 |
#include "gdata-private.h"
|
|
Packit |
4b6dd7 |
#include "gdata-query.h"
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
static GList *get_authorization_domains (void);
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
_GDATA_DEFINE_AUTHORIZATION_DOMAIN (contacts, "cp", "https://www.google.com/m8/feeds/")
|
|
Packit |
4b6dd7 |
G_DEFINE_TYPE_WITH_CODE (GDataContactsService, gdata_contacts_service, GDATA_TYPE_SERVICE,
|
|
Packit |
4b6dd7 |
G_IMPLEMENT_INTERFACE (GDATA_TYPE_BATCHABLE, NULL))
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
static void
|
|
Packit |
4b6dd7 |
gdata_contacts_service_class_init (GDataContactsServiceClass *klass)
|
|
Packit |
4b6dd7 |
{
|
|
Packit |
4b6dd7 |
GDataServiceClass *service_class = GDATA_SERVICE_CLASS (klass);
|
|
Packit |
4b6dd7 |
service_class->api_version = "3";
|
|
Packit |
4b6dd7 |
service_class->get_authorization_domains = get_authorization_domains;
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
static void
|
|
Packit |
4b6dd7 |
gdata_contacts_service_init (GDataContactsService *self)
|
|
Packit |
4b6dd7 |
{
|
|
Packit |
4b6dd7 |
/* Nothing to see here */
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
static GList *
|
|
Packit |
4b6dd7 |
get_authorization_domains (void)
|
|
Packit |
4b6dd7 |
{
|
|
Packit |
4b6dd7 |
return g_list_prepend (NULL, get_contacts_authorization_domain ());
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
/**
|
|
Packit |
4b6dd7 |
* gdata_contacts_service_new:
|
|
Packit |
4b6dd7 |
* @authorizer: (allow-none): a #GDataAuthorizer to authorize the service's requests, or %NULL
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Creates a new #GDataContactsService using the given #GDataAuthorizer. If @authorizer is %NULL, all requests are made as an unauthenticated user.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Return value: a new #GDataContactsService, or %NULL; unref with g_object_unref()
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Since: 0.9.0
|
|
Packit |
4b6dd7 |
*/
|
|
Packit |
4b6dd7 |
GDataContactsService *
|
|
Packit |
4b6dd7 |
gdata_contacts_service_new (GDataAuthorizer *authorizer)
|
|
Packit |
4b6dd7 |
{
|
|
Packit |
4b6dd7 |
g_return_val_if_fail (authorizer == NULL || GDATA_IS_AUTHORIZER (authorizer), NULL);
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
return g_object_new (GDATA_TYPE_CONTACTS_SERVICE,
|
|
Packit |
4b6dd7 |
"authorizer", authorizer,
|
|
Packit |
4b6dd7 |
NULL);
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
/**
|
|
Packit |
4b6dd7 |
* gdata_contacts_service_get_primary_authorization_domain:
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* The primary #GDataAuthorizationDomain for interacting with Google Contacts. This will not normally need to be used, as it's used internally
|
|
Packit |
4b6dd7 |
* by the #GDataContactsService methods. However, if using the plain #GDataService methods to implement custom queries or requests which libgdata
|
|
Packit |
4b6dd7 |
* does not support natively, then this domain may be needed to authorize the requests.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* The domain never changes, and is interned so that pointer comparison can be used to differentiate it from other authorization domains.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Return value: (transfer none): the service's authorization domain
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Since: 0.9.0
|
|
Packit |
4b6dd7 |
*/
|
|
Packit |
4b6dd7 |
GDataAuthorizationDomain *
|
|
Packit |
4b6dd7 |
gdata_contacts_service_get_primary_authorization_domain (void)
|
|
Packit |
4b6dd7 |
{
|
|
Packit |
4b6dd7 |
return get_contacts_authorization_domain ();
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
/**
|
|
Packit |
4b6dd7 |
* gdata_contacts_service_query_contacts:
|
|
Packit |
4b6dd7 |
* @self: a #GDataContactsService
|
|
Packit |
4b6dd7 |
* @query: (allow-none): a #GDataQuery with the query parameters, or %NULL
|
|
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 an entry 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 |
* Queries the service to return a list of contacts matching the given @query.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* For more details, see gdata_service_query().
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Return value: (transfer full): a #GDataFeed of query results; unref with g_object_unref()
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Since: 0.2.0
|
|
Packit |
4b6dd7 |
*/
|
|
Packit |
4b6dd7 |
GDataFeed *
|
|
Packit |
4b6dd7 |
gdata_contacts_service_query_contacts (GDataContactsService *self, GDataQuery *query, GCancellable *cancellable,
|
|
Packit |
4b6dd7 |
GDataQueryProgressCallback progress_callback, gpointer progress_user_data, GError **error)
|
|
Packit |
4b6dd7 |
{
|
|
Packit |
4b6dd7 |
GDataFeed *feed;
|
|
Packit |
4b6dd7 |
gchar *request_uri;
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
g_return_val_if_fail (GDATA_IS_CONTACTS_SERVICE (self), NULL);
|
|
Packit |
4b6dd7 |
g_return_val_if_fail (query == NULL || GDATA_IS_QUERY (query), 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 |
/* Ensure we're authenticated first */
|
|
Packit |
4b6dd7 |
if (gdata_authorizer_is_authorized_for_domain (gdata_service_get_authorizer (GDATA_SERVICE (self)),
|
|
Packit |
4b6dd7 |
get_contacts_authorization_domain ()) == FALSE) {
|
|
Packit |
4b6dd7 |
g_set_error_literal (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_AUTHENTICATION_REQUIRED,
|
|
Packit |
4b6dd7 |
_("You must be authenticated to query contacts."));
|
|
Packit |
4b6dd7 |
return NULL;
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
request_uri = g_strconcat (_gdata_service_get_scheme (), "://www.google.com/m8/feeds/contacts/default/full", NULL);
|
|
Packit |
4b6dd7 |
feed = gdata_service_query (GDATA_SERVICE (self), get_contacts_authorization_domain (), request_uri, GDATA_QUERY (query),
|
|
Packit |
4b6dd7 |
GDATA_TYPE_CONTACTS_CONTACT, cancellable, progress_callback, progress_user_data, error);
|
|
Packit |
4b6dd7 |
g_free (request_uri);
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
return feed;
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
/**
|
|
Packit |
4b6dd7 |
* gdata_contacts_service_query_contacts_async:
|
|
Packit |
4b6dd7 |
* @self: a #GDataContactsService
|
|
Packit |
4b6dd7 |
* @query: (allow-none): a #GDataQuery with the query parameters, or %NULL
|
|
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 an entry 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 |
* Queries the service to return a list of contacts matching the given @query. @self and
|
|
Packit |
4b6dd7 |
* @query are all reffed when this function is called, so can safely be unreffed after this function returns.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* For more details, see gdata_contacts_service_query_contacts(), which is the synchronous version of this function,
|
|
Packit |
4b6dd7 |
* and gdata_service_query_async(), which is the base asynchronous query function.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Since: 0.9.1
|
|
Packit |
4b6dd7 |
*/
|
|
Packit |
4b6dd7 |
void
|
|
Packit |
4b6dd7 |
gdata_contacts_service_query_contacts_async (GDataContactsService *self, GDataQuery *query, 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 |
gchar *request_uri;
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
g_return_if_fail (GDATA_IS_CONTACTS_SERVICE (self));
|
|
Packit |
4b6dd7 |
g_return_if_fail (query == NULL || GDATA_IS_QUERY (query));
|
|
Packit |
4b6dd7 |
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
|
Packit |
4b6dd7 |
g_return_if_fail (callback != NULL);
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
/* Ensure we're authenticated first */
|
|
Packit |
4b6dd7 |
if (gdata_authorizer_is_authorized_for_domain (gdata_service_get_authorizer (GDATA_SERVICE (self)),
|
|
Packit |
4b6dd7 |
get_contacts_authorization_domain ()) == FALSE) {
|
|
Packit |
4b6dd7 |
g_autoptr(GTask) task = NULL;
|
|
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_return_new_error (task, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_AUTHENTICATION_REQUIRED, "%s",
|
|
Packit |
4b6dd7 |
_("You must be authenticated to query contacts."));
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
return;
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
request_uri = g_strconcat (_gdata_service_get_scheme (), "://www.google.com/m8/feeds/contacts/default/full", NULL);
|
|
Packit |
4b6dd7 |
gdata_service_query_async (GDATA_SERVICE (self), get_contacts_authorization_domain (), request_uri, GDATA_QUERY (query),
|
|
Packit |
4b6dd7 |
GDATA_TYPE_CONTACTS_CONTACT, cancellable, progress_callback, progress_user_data,
|
|
Packit |
4b6dd7 |
destroy_progress_user_data, callback, user_data);
|
|
Packit |
4b6dd7 |
g_free (request_uri);
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
/**
|
|
Packit |
4b6dd7 |
* gdata_contacts_service_insert_contact:
|
|
Packit |
4b6dd7 |
* @self: a #GDataContactsService
|
|
Packit |
4b6dd7 |
* @contact: the #GDataContactsContact to insert
|
|
Packit |
4b6dd7 |
* @cancellable: (allow-none): optional #GCancellable object, or %NULL
|
|
Packit |
4b6dd7 |
* @error: a #GError, or %NULL
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Inserts @contact by uploading it to the online contacts service.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* For more details, see gdata_service_insert_entry().
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Return value: (transfer full): an updated #GDataContactsContact, or %NULL; unref with g_object_unref()
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Since: 0.2.0
|
|
Packit |
4b6dd7 |
*/
|
|
Packit |
4b6dd7 |
GDataContactsContact *
|
|
Packit |
4b6dd7 |
gdata_contacts_service_insert_contact (GDataContactsService *self, GDataContactsContact *contact, GCancellable *cancellable, GError **error)
|
|
Packit |
4b6dd7 |
{
|
|
Packit |
4b6dd7 |
gchar *uri;
|
|
Packit |
4b6dd7 |
GDataEntry *entry;
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
g_return_val_if_fail (GDATA_IS_CONTACTS_SERVICE (self), NULL);
|
|
Packit |
4b6dd7 |
g_return_val_if_fail (GDATA_IS_CONTACTS_CONTACT (contact), 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 |
uri = g_strconcat (_gdata_service_get_scheme (), "://www.google.com/m8/feeds/contacts/default/full", NULL);
|
|
Packit |
4b6dd7 |
entry = gdata_service_insert_entry (GDATA_SERVICE (self), get_contacts_authorization_domain (), uri, GDATA_ENTRY (contact), cancellable,
|
|
Packit |
4b6dd7 |
error);
|
|
Packit |
4b6dd7 |
g_free (uri);
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
return GDATA_CONTACTS_CONTACT (entry);
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
/**
|
|
Packit |
4b6dd7 |
* gdata_contacts_service_insert_contact_async:
|
|
Packit |
4b6dd7 |
* @self: a #GDataContactsService
|
|
Packit |
4b6dd7 |
* @contact: the #GDataContactsContact to insert
|
|
Packit |
4b6dd7 |
* @cancellable: (allow-none): optional #GCancellable object, or %NULL
|
|
Packit |
4b6dd7 |
* @callback: a #GAsyncReadyCallback to call when insertion is finished
|
|
Packit |
4b6dd7 |
* @user_data: (closure): data to pass to the @callback function
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Inserts @contact by uploading it to the online contacts service. @self and @contact are both reffed when this function is called, so can safely be
|
|
Packit |
4b6dd7 |
* unreffed after this function returns.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* @callback should call gdata_service_insert_entry_finish() to obtain a #GDataContactsContact representing the inserted contact and to check for
|
|
Packit |
4b6dd7 |
* possible errors.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* For more details, see gdata_contacts_service_insert_contact(), which is the synchronous version of this function,
|
|
Packit |
4b6dd7 |
* and gdata_service_insert_entry_async(), which is the base asynchronous insertion function.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Since: 0.7.0
|
|
Packit |
4b6dd7 |
*/
|
|
Packit |
4b6dd7 |
void
|
|
Packit |
4b6dd7 |
gdata_contacts_service_insert_contact_async (GDataContactsService *self, GDataContactsContact *contact, GCancellable *cancellable,
|
|
Packit |
4b6dd7 |
GAsyncReadyCallback callback, gpointer user_data)
|
|
Packit |
4b6dd7 |
{
|
|
Packit |
4b6dd7 |
gchar *uri;
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
g_return_if_fail (GDATA_IS_CONTACTS_SERVICE (self));
|
|
Packit |
4b6dd7 |
g_return_if_fail (GDATA_IS_CONTACTS_CONTACT (contact));
|
|
Packit |
4b6dd7 |
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
uri = g_strconcat (_gdata_service_get_scheme (), "://www.google.com/m8/feeds/contacts/default/full", NULL);
|
|
Packit |
4b6dd7 |
gdata_service_insert_entry_async (GDATA_SERVICE (self), get_contacts_authorization_domain (), uri, GDATA_ENTRY (contact), cancellable,
|
|
Packit |
4b6dd7 |
callback, user_data);
|
|
Packit |
4b6dd7 |
g_free (uri);
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
/**
|
|
Packit |
4b6dd7 |
* gdata_contacts_service_query_groups:
|
|
Packit |
4b6dd7 |
* @self: a #GDataContactsService
|
|
Packit |
4b6dd7 |
* @query: (allow-none): a #GDataQuery with the query parameters, or %NULL
|
|
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 an entry 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 |
* Queries the service to return a list of groups matching the given @query.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* For more details, see gdata_service_query().
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Return value: (transfer full): a #GDataFeed of query results; unref with g_object_unref()
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Since: 0.7.0
|
|
Packit |
4b6dd7 |
*/
|
|
Packit |
4b6dd7 |
GDataFeed *
|
|
Packit |
4b6dd7 |
gdata_contacts_service_query_groups (GDataContactsService *self, GDataQuery *query, GCancellable *cancellable,
|
|
Packit |
4b6dd7 |
GDataQueryProgressCallback progress_callback, gpointer progress_user_data, GError **error)
|
|
Packit |
4b6dd7 |
{
|
|
Packit |
4b6dd7 |
GDataFeed *feed;
|
|
Packit |
4b6dd7 |
gchar *request_uri;
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
g_return_val_if_fail (GDATA_IS_CONTACTS_SERVICE (self), NULL);
|
|
Packit |
4b6dd7 |
g_return_val_if_fail (query == NULL || GDATA_IS_QUERY (query), 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 |
/* Ensure we're authenticated first */
|
|
Packit |
4b6dd7 |
if (gdata_authorizer_is_authorized_for_domain (gdata_service_get_authorizer (GDATA_SERVICE (self)),
|
|
Packit |
4b6dd7 |
get_contacts_authorization_domain ()) == FALSE) {
|
|
Packit |
4b6dd7 |
g_set_error_literal (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_AUTHENTICATION_REQUIRED,
|
|
Packit |
4b6dd7 |
_("You must be authenticated to query contact groups."));
|
|
Packit |
4b6dd7 |
return NULL;
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
request_uri = g_strconcat (_gdata_service_get_scheme (), "://www.google.com/m8/feeds/groups/default/full", NULL);
|
|
Packit |
4b6dd7 |
feed = gdata_service_query (GDATA_SERVICE (self), get_contacts_authorization_domain (), request_uri, GDATA_QUERY (query),
|
|
Packit |
4b6dd7 |
GDATA_TYPE_CONTACTS_GROUP, cancellable, progress_callback, progress_user_data, error);
|
|
Packit |
4b6dd7 |
g_free (request_uri);
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
return feed;
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
/**
|
|
Packit |
4b6dd7 |
* gdata_contacts_service_query_groups_async:
|
|
Packit |
4b6dd7 |
* @self: a #GDataContactsService
|
|
Packit |
4b6dd7 |
* @query: (allow-none): a #GDataQuery with the query parameters, or %NULL
|
|
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 an entry 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 |
* Queries the service to return a list of groups matching the given @query. @self and @query are all reffed when this function is called, so can
|
|
Packit |
4b6dd7 |
* safely be unreffed after this function returns.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* For more details, see gdata_contacts_service_query_groups(), which is the synchronous version of this function, and gdata_service_query_async(),
|
|
Packit |
4b6dd7 |
* which is the base asynchronous query function.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Since: 0.9.1
|
|
Packit |
4b6dd7 |
*/
|
|
Packit |
4b6dd7 |
void
|
|
Packit |
4b6dd7 |
gdata_contacts_service_query_groups_async (GDataContactsService *self, GDataQuery *query, 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 |
gchar *request_uri;
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
g_return_if_fail (GDATA_IS_CONTACTS_SERVICE (self));
|
|
Packit |
4b6dd7 |
g_return_if_fail (query == NULL || GDATA_IS_QUERY (query));
|
|
Packit |
4b6dd7 |
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
|
Packit |
4b6dd7 |
g_return_if_fail (callback != NULL);
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
/* Ensure we're authenticated first */
|
|
Packit |
4b6dd7 |
if (gdata_authorizer_is_authorized_for_domain (gdata_service_get_authorizer (GDATA_SERVICE (self)),
|
|
Packit |
4b6dd7 |
get_contacts_authorization_domain ()) == FALSE) {
|
|
Packit |
4b6dd7 |
g_autoptr(GTask) task = NULL;
|
|
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_return_new_error (task, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_AUTHENTICATION_REQUIRED, "%s",
|
|
Packit |
4b6dd7 |
_("You must be authenticated to query contact groups."));
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
return;
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
request_uri = g_strconcat (_gdata_service_get_scheme (), "://www.google.com/m8/feeds/groups/default/full", NULL);
|
|
Packit |
4b6dd7 |
gdata_service_query_async (GDATA_SERVICE (self), get_contacts_authorization_domain (), request_uri, GDATA_QUERY (query),
|
|
Packit |
4b6dd7 |
GDATA_TYPE_CONTACTS_GROUP, cancellable, progress_callback, progress_user_data,
|
|
Packit |
4b6dd7 |
destroy_progress_user_data, callback, user_data);
|
|
Packit |
4b6dd7 |
g_free (request_uri);
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
/**
|
|
Packit |
4b6dd7 |
* gdata_contacts_service_insert_group:
|
|
Packit |
4b6dd7 |
* @self: a #GDataContactsService
|
|
Packit |
4b6dd7 |
* @group: a #GDataContactsGroup to create on the server
|
|
Packit |
4b6dd7 |
* @cancellable: (allow-none): optional #GCancellable object, or %NULL
|
|
Packit |
4b6dd7 |
* @error: a #GError, or %NULL
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Inserts a new contact group described by @group. The user must be authenticated to use this function.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Return value: (transfer full): the inserted #GDataContactsGroup; unref with g_object_unref()
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Since: 0.7.0
|
|
Packit |
4b6dd7 |
*/
|
|
Packit |
4b6dd7 |
GDataContactsGroup *
|
|
Packit |
4b6dd7 |
gdata_contacts_service_insert_group (GDataContactsService *self, GDataContactsGroup *group, GCancellable *cancellable, GError **error)
|
|
Packit |
4b6dd7 |
{
|
|
Packit |
4b6dd7 |
gchar *request_uri;
|
|
Packit |
4b6dd7 |
GDataEntry *new_group;
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
g_return_val_if_fail (GDATA_IS_CONTACTS_SERVICE (self), NULL);
|
|
Packit |
4b6dd7 |
g_return_val_if_fail (GDATA_IS_CONTACTS_GROUP (group), 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 |
if (gdata_entry_is_inserted (GDATA_ENTRY (group)) == TRUE) {
|
|
Packit |
4b6dd7 |
g_set_error_literal (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_ENTRY_ALREADY_INSERTED,
|
|
Packit |
4b6dd7 |
_("The group has already been inserted."));
|
|
Packit |
4b6dd7 |
return NULL;
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
if (gdata_authorizer_is_authorized_for_domain (gdata_service_get_authorizer (GDATA_SERVICE (self)),
|
|
Packit |
4b6dd7 |
get_contacts_authorization_domain ()) == FALSE) {
|
|
Packit |
4b6dd7 |
g_set_error_literal (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_AUTHENTICATION_REQUIRED,
|
|
Packit |
4b6dd7 |
_("You must be authenticated to insert a group."));
|
|
Packit |
4b6dd7 |
return NULL;
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
request_uri = g_strconcat (_gdata_service_get_scheme (), "://www.google.com/m8/feeds/groups/default/full", NULL);
|
|
Packit |
4b6dd7 |
new_group = gdata_service_insert_entry (GDATA_SERVICE (self), get_contacts_authorization_domain (), request_uri, GDATA_ENTRY (group),
|
|
Packit |
4b6dd7 |
cancellable, error);
|
|
Packit |
4b6dd7 |
g_free (request_uri);
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
return GDATA_CONTACTS_GROUP (new_group);
|
|
Packit |
4b6dd7 |
}
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
/**
|
|
Packit |
4b6dd7 |
* gdata_contacts_service_insert_group_async:
|
|
Packit |
4b6dd7 |
* @self: a #GDataContactsService
|
|
Packit |
4b6dd7 |
* @group: the #GDataContactsGroup to insert
|
|
Packit |
4b6dd7 |
* @cancellable: (allow-none): optional #GCancellable object, or %NULL
|
|
Packit |
4b6dd7 |
* @callback: a #GAsyncReadyCallback to call when insertion is finished
|
|
Packit |
4b6dd7 |
* @user_data: (closure): data to pass to the @callback function
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Inserts a new contact group described by @group. The user must be authenticated to use this function. @self and @group are both reffed when this
|
|
Packit |
4b6dd7 |
* function is called, so can safely be unreffed after this function returns.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* @callback should call gdata_service_insert_entry_finish() to obtain a #GDataContactsGroup representing the inserted group and to check for possible
|
|
Packit |
4b6dd7 |
* errors.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* For more details, see gdata_contacts_service_insert_group(), which is the synchronous version of this function, and
|
|
Packit |
4b6dd7 |
* gdata_service_insert_entry_async(), which is the base asynchronous insertion function.
|
|
Packit |
4b6dd7 |
*
|
|
Packit |
4b6dd7 |
* Since: 0.7.0
|
|
Packit |
4b6dd7 |
*/
|
|
Packit |
4b6dd7 |
void
|
|
Packit |
4b6dd7 |
gdata_contacts_service_insert_group_async (GDataContactsService *self, GDataContactsGroup *group, GCancellable *cancellable,
|
|
Packit |
4b6dd7 |
GAsyncReadyCallback callback, gpointer user_data)
|
|
Packit |
4b6dd7 |
{
|
|
Packit |
4b6dd7 |
gchar *request_uri;
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
g_return_if_fail (GDATA_IS_CONTACTS_SERVICE (self));
|
|
Packit |
4b6dd7 |
g_return_if_fail (GDATA_IS_CONTACTS_GROUP (group));
|
|
Packit |
4b6dd7 |
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
|
Packit |
4b6dd7 |
|
|
Packit |
4b6dd7 |
request_uri = g_strconcat (_gdata_service_get_scheme (), "://www.google.com/m8/feeds/groups/default/full", NULL);
|
|
Packit |
4b6dd7 |
gdata_service_insert_entry_async (GDATA_SERVICE (self), get_contacts_authorization_domain (), request_uri, GDATA_ENTRY (group), cancellable,
|
|
Packit |
4b6dd7 |
callback, user_data);
|
|
Packit |
4b6dd7 |
g_free (request_uri);
|
|
Packit |
4b6dd7 |
}
|