Blame gdata/services/documents/gdata-documents-entry.c

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) Thibault Saunier 2009 <saunierthibault@gmail.com>
Packit 4b6dd7
 * Copyright (C) Red Hat, Inc. 2015, 2016
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-documents-entry
Packit 4b6dd7
 * @short_description: GData document object abstract class
Packit 4b6dd7
 * @stability: Stable
Packit 4b6dd7
 * @include: gdata/services/documents/gdata-documents-entry.h
Packit 4b6dd7
 *
Packit 4b6dd7
 * #GDataDocumentsEntry is a subclass of #GDataEntry to represent a Google Drive entry, which is then further subclassed
Packit 4b6dd7
 * to give specific document types.
Packit 4b6dd7
 *
Packit 4b6dd7
 * #GDataDocumentsEntry implements #GDataAccessHandler, meaning the access rules to it can be modified using that interface. As well as the
Packit 4b6dd7
 * access roles defined for the base #GDataAccessRule (e.g. %GDATA_ACCESS_ROLE_NONE), #GDataDocumentsEntry has its own, such as
Packit 4b6dd7
 * %GDATA_DOCUMENTS_ACCESS_ROLE_OWNER and %GDATA_DOCUMENTS_ACCESS_ROLE_READER.
Packit 4b6dd7
 *
Packit 4b6dd7
 * Documents can (confusingly) be referenced by three different types of IDs: their entry ID, their resource ID and their document ID (untyped resource
Packit 4b6dd7
 * ID). Each is a substring of the previous ones (i.e. the entry ID contains the resource ID, which in turn contains the document ID). The resource ID
Packit 4b6dd7
 * and document ID should almost always be considered as internal, and thus entry IDs (#GDataEntry:id) should normally be used to uniquely identify
Packit 4b6dd7
 * documents. For more information, see #GDataDocumentsEntry:resource-id.
Packit 4b6dd7
 *
Packit 4b6dd7
 * For more details of Google Drive's GData API, see the
Packit 4b6dd7
 * <ulink type="http" url="https://developers.google.com/drive/v2/web/about-sdk">online documentation</ulink>.
Packit 4b6dd7
 *
Packit 4b6dd7
 * <example>
Packit 4b6dd7
 * 	<title>Moving an Entry Between Folders</title>
Packit 4b6dd7
 * 	<programlisting>
Packit 4b6dd7
 *	GDataDocumentsService *service;
Packit 4b6dd7
 *	GDataDocumentsEntry *entry, *intermediate_entry, *updated_entry;
Packit 4b6dd7
 *	GDataDocumentsFolder *old_folder, *new_folder;
Packit 4b6dd7
 *	GError *error = NULL;
Packit 4b6dd7
 *
Packit 4b6dd7
 *	/* Create a service */
Packit 4b6dd7
 *	service = create_documents_service ();
Packit 4b6dd7
 *
Packit 4b6dd7
 *	/* Get the entry, the folder it's being moved out of, and the folder it's being moved into. The entry can either be a document or
Packit 4b6dd7
 *	 * another folder, allowing hierarchies of folders to be constructed. */
Packit 4b6dd7
 *	entry = query_user_for_entry (service);
Packit 4b6dd7
 *	old_folder = query_user_for_old_folder (service);
Packit 4b6dd7
 *	new_folder = query_user_for_new_folder (service);
Packit 4b6dd7
 *
Packit 4b6dd7
 *	/* Add the entry to the new folder */
Packit 4b6dd7
 *	intermediate_entry = gdata_documents_service_add_entry_to_folder (service, entry, new_folder, NULL, &error);
Packit 4b6dd7
 *
Packit 4b6dd7
 *	g_object_unref (entry);
Packit 4b6dd7
 *	g_object_unref (new_folder);
Packit 4b6dd7
 *
Packit 4b6dd7
 *	if (error != NULL) {
Packit 4b6dd7
 *		g_error ("Error adding entry to new folder: %s", error->message);
Packit 4b6dd7
 *		g_error_free (error);
Packit 4b6dd7
 *		g_object_unref (old_folder);
Packit 4b6dd7
 *		g_object_unref (service);
Packit 4b6dd7
 *		return;
Packit 4b6dd7
 *	}
Packit 4b6dd7
 *
Packit 4b6dd7
 *	/* Remove the entry from the old folder */
Packit 4b6dd7
 *	updated_entry = gdata_documents_service_remove_entry_from_folder (service, intermediate_entry, old_folder, NULL, &error);
Packit 4b6dd7
 *
Packit 4b6dd7
 *	g_object_unref (intermediate_entry);
Packit 4b6dd7
 *	g_object_unref (old_folder);
Packit 4b6dd7
 *	g_object_unref (service);
Packit 4b6dd7
 *
Packit 4b6dd7
 *	if (error != NULL) {
Packit 4b6dd7
 *		/* Note that you might want to attempt to remove the intermediate_entry from the new_folder in this error case, so that
Packit 4b6dd7
 *		 * the operation is aborted cleanly. */
Packit 4b6dd7
 *		g_error ("Error removing entry from previous folder: %s", error->message);
Packit 4b6dd7
 *		g_error_free (error);
Packit 4b6dd7
 *		return;
Packit 4b6dd7
 *	}
Packit 4b6dd7
 *
Packit 4b6dd7
 *	/* Do something with the updated entry */
Packit 4b6dd7
 *
Packit 4b6dd7
 *	g_object_unref (updated_entry);
Packit 4b6dd7
 * 	</programlisting>
Packit 4b6dd7
 * </example>
Packit 4b6dd7
 *
Packit 4b6dd7
 * Since: 0.4.0
Packit 4b6dd7
 */
Packit 4b6dd7
Packit 4b6dd7
#include <config.h>
Packit 4b6dd7
#include <glib.h>
Packit 4b6dd7
#include <glib/gi18n-lib.h>
Packit 4b6dd7
Packit 4b6dd7
#include "gdata-documents-entry.h"
Packit 4b6dd7
#include "gdata-parser.h"
Packit 4b6dd7
#include "gdata-types.h"
Packit 4b6dd7
#include "gdata-private.h"
Packit 4b6dd7
#include "gdata-access-handler.h"
Packit 4b6dd7
#include "gdata-documents-access-rule.h"
Packit 4b6dd7
#include "gdata-documents-service.h"
Packit 4b6dd7
Packit 4b6dd7
#include "gdata-documents-spreadsheet.h"
Packit 4b6dd7
#include "gdata-documents-presentation.h"
Packit 4b6dd7
#include "gdata-documents-text.h"
Packit 4b6dd7
#include "gdata-documents-folder.h"
Packit 4b6dd7
#include "gdata-documents-utils.h"
Packit 4b6dd7
Packit 4b6dd7
static void gdata_documents_entry_access_handler_init (GDataAccessHandlerIface *iface);
Packit 4b6dd7
static void gdata_documents_entry_finalize (GObject *object);
Packit 4b6dd7
static void gdata_entry_dispose (GObject *object);
Packit 4b6dd7
static const gchar *get_content_type (void);
Packit 4b6dd7
static void get_namespaces (GDataParsable *parsable, GHashTable *namespaces);
Packit 4b6dd7
static void gdata_documents_entry_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec);
Packit 4b6dd7
static void gdata_documents_entry_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec);
Packit 4b6dd7
static gboolean parse_json (GDataParsable *parsable, JsonReader *reader, gpointer user_data, GError **error);
Packit 4b6dd7
static gboolean post_parse_json (GDataParsable *parsable, gpointer user_data, GError **error);
Packit 4b6dd7
static void get_json (GDataParsable *parsable, JsonBuilder *builder);
Packit 4b6dd7
static gchar *get_entry_uri (const gchar *id);
Packit 4b6dd7
Packit 4b6dd7
struct _GDataDocumentsEntryPrivate {
Packit 4b6dd7
	gint64 last_viewed;
Packit 4b6dd7
	gchar *resource_id;
Packit 4b6dd7
	gboolean writers_can_invite;
Packit 4b6dd7
	gboolean is_deleted;
Packit 4b6dd7
	GDataAuthor *last_modified_by;
Packit 4b6dd7
	goffset quota_used; /* bytes */
Packit 4b6dd7
	goffset file_size; /* bytes */
Packit 4b6dd7
};
Packit 4b6dd7
Packit 4b6dd7
enum {
Packit 4b6dd7
	PROP_EDITED = 1,
Packit 4b6dd7
	PROP_LAST_VIEWED,
Packit 4b6dd7
	PROP_DOCUMENT_ID,
Packit 4b6dd7
	PROP_LAST_MODIFIED_BY,
Packit 4b6dd7
	PROP_IS_DELETED,
Packit 4b6dd7
	PROP_WRITERS_CAN_INVITE,
Packit 4b6dd7
	PROP_RESOURCE_ID,
Packit 4b6dd7
	PROP_QUOTA_USED,
Packit 4b6dd7
	PROP_FILE_SIZE,
Packit 4b6dd7
};
Packit 4b6dd7
Packit 4b6dd7
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GDataDocumentsEntry, gdata_documents_entry, GDATA_TYPE_ENTRY,
Packit 4b6dd7
                                  G_IMPLEMENT_INTERFACE (GDATA_TYPE_ACCESS_HANDLER, gdata_documents_entry_access_handler_init))
Packit 4b6dd7
Packit 4b6dd7
static void
Packit 4b6dd7
gdata_documents_entry_class_init (GDataDocumentsEntryClass *klass)
Packit 4b6dd7
{
Packit 4b6dd7
	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
Packit 4b6dd7
	GDataParsableClass *parsable_class = GDATA_PARSABLE_CLASS (klass);
Packit 4b6dd7
	GDataEntryClass *entry_class = GDATA_ENTRY_CLASS (klass);
Packit 4b6dd7
Packit 4b6dd7
	g_type_class_add_private (klass, sizeof (GDataDocumentsEntryPrivate));
Packit 4b6dd7
Packit 4b6dd7
	gobject_class->get_property = gdata_documents_entry_get_property;
Packit 4b6dd7
	gobject_class->set_property = gdata_documents_entry_set_property;
Packit 4b6dd7
	gobject_class->finalize = gdata_documents_entry_finalize;
Packit 4b6dd7
	gobject_class->dispose = gdata_entry_dispose;
Packit 4b6dd7
Packit 4b6dd7
	parsable_class->parse_json = parse_json;
Packit 4b6dd7
	parsable_class->post_parse_json = post_parse_json;
Packit 4b6dd7
	parsable_class->get_content_type = get_content_type;
Packit 4b6dd7
	parsable_class->get_json = get_json;
Packit 4b6dd7
	parsable_class->get_namespaces = get_namespaces;
Packit 4b6dd7
Packit 4b6dd7
	entry_class->get_entry_uri = get_entry_uri;
Packit 4b6dd7
Packit 4b6dd7
	/**
Packit 4b6dd7
	 * GDataDocumentsEntry:edited:
Packit 4b6dd7
	 *
Packit 4b6dd7
	 * The last time the document was edited. If the document has not been edited yet, the content indicates the time it was created.
Packit 4b6dd7
	 *
Packit 4b6dd7
	 * Since: 0.4.0
Packit 4b6dd7
	 * Deprecated: 0.17.0: This is identical to #GDataEntry:updated.
Packit 4b6dd7
	 */
Packit 4b6dd7
	g_object_class_install_property (gobject_class, PROP_EDITED,
Packit 4b6dd7
	                                 g_param_spec_int64 ("edited",
Packit 4b6dd7
	                                                     "Edited", "The last time the document was edited.",
Packit 4b6dd7
	                                                     -1, G_MAXINT64, -1,
Packit 4b6dd7
	                                                     G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_DEPRECATED));
Packit 4b6dd7
Packit 4b6dd7
	/**
Packit 4b6dd7
	 * GDataDocumentsEntry:last-viewed:
Packit 4b6dd7
	 *
Packit 4b6dd7
	 * The last time the document was viewed.
Packit 4b6dd7
	 *
Packit 4b6dd7
	 * Since: 0.4.0
Packit 4b6dd7
	 */
Packit 4b6dd7
	g_object_class_install_property (gobject_class, PROP_LAST_VIEWED,
Packit 4b6dd7
	                                 g_param_spec_int64 ("last-viewed",
Packit 4b6dd7
	                                                     "Last viewed", "The last time the document was viewed.",
Packit 4b6dd7
	                                                     -1, G_MAXINT64, -1,
Packit 4b6dd7
	                                                     G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
Packit 4b6dd7
Packit 4b6dd7
	/**
Packit 4b6dd7
	 * GDataDocumentsEntry:writers-can-invite:
Packit 4b6dd7
	 *
Packit 4b6dd7
	 * Indicates whether the document entry writers can invite others to edit the document.
Packit 4b6dd7
	 *
Packit 4b6dd7
	 * Since: 0.4.0
Packit 4b6dd7
	 */
Packit 4b6dd7
	g_object_class_install_property (gobject_class, PROP_WRITERS_CAN_INVITE,
Packit 4b6dd7
	                                 g_param_spec_boolean ("writers-can-invite",
Packit 4b6dd7
	                                                       "Writers can invite?", "Indicates whether writers can invite others to edit.",
Packit 4b6dd7
	                                                       FALSE,
Packit 4b6dd7
	                                                       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
Packit 4b6dd7
Packit 4b6dd7
	/**
Packit 4b6dd7
	 * GDataDocumentsEntry:is-deleted:
Packit 4b6dd7
	 *
Packit 4b6dd7
	 * Indicates whether the document entry has been deleted (moved to the trash). Deleted documents will only
Packit 4b6dd7
	 * appear in query results if the #GDataDocumentsQuery:show-deleted property is %TRUE.
Packit 4b6dd7
	 *
Packit 4b6dd7
	 * Since: 0.5.0
Packit 4b6dd7
	 */
Packit 4b6dd7
	g_object_class_install_property (gobject_class, PROP_IS_DELETED,
Packit 4b6dd7
	                                 g_param_spec_boolean ("is-deleted",
Packit 4b6dd7
	                                                       "Deleted?", "Indicates whether the document entry has been deleted.",
Packit 4b6dd7
	                                                       FALSE,
Packit 4b6dd7
	                                                       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
Packit 4b6dd7
Packit 4b6dd7
	/**
Packit 4b6dd7
	 * GDataDocumentsEntry:resource-id:
Packit 4b6dd7
	 *
Packit 4b6dd7
	 * The resource ID of the document. This should not normally need to be used in client code, and is mostly for internal use. To uniquely
Packit 4b6dd7
	 * identify a given document or folder, use its #GDataEntry:id.
Packit 4b6dd7
	 *
Packit 4b6dd7
	 * Resource IDs have the form:
Packit 4b6dd7
	 * <literal><replaceable>document|drawing|pdf|spreadsheet|presentation|folder</replaceable>:<replaceable>untyped resource ID</replaceable></literal>; whereas
Packit 4b6dd7
	 * entry IDs have the form:
Packit 4b6dd7
	 * <literal>https://docs.google.com/feeds/id/<replaceable>resource ID</replaceable></literal> in version 3 of the API.
Packit 4b6dd7
	 *
Packit 4b6dd7
	 * For more information, see the
Packit 4b6dd7
	 * <ulink type="http" url="https://developers.google.com/google-apps/documents-list/#resource_ids_explained">Google Documents
Packit 4b6dd7
	 * API reference</ulink>.
Packit 4b6dd7
	 *
Packit 4b6dd7
	 * Since: 0.11.0
Packit 4b6dd7
	 */
Packit 4b6dd7
	g_object_class_install_property (gobject_class, PROP_RESOURCE_ID,
Packit 4b6dd7
	                                 g_param_spec_string ("resource-id",
Packit 4b6dd7
	                                                      "Resource ID", "The resource ID of the document.",
Packit 4b6dd7
	                                                      NULL,
Packit 4b6dd7
	                                                      G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
Packit 4b6dd7
Packit 4b6dd7
	/**
Packit 4b6dd7
	 * GDataDocumentsEntry:document-id:
Packit 4b6dd7
	 *
Packit 4b6dd7
	 * The document ID of the document, which is different from its entry ID (GDataEntry:id). The
Packit 4b6dd7
	 * <ulink type="http" url="https://developers.google.com/google-apps/documents-list/#terminology_used_in_this_guide">online GData
Packit 4b6dd7
	 * Documentation</ulink> refers to these as “untyped resource IDs”.
Packit 4b6dd7
	 *
Packit 4b6dd7
	 * Since: 0.4.0
Packit 4b6dd7
	 * Deprecated: 0.11.0: This a substring of the #GDataDocumentsEntry:resource-id, which is more general and should be used instead.
Packit 4b6dd7
	 */
Packit 4b6dd7
	g_object_class_install_property (gobject_class, PROP_DOCUMENT_ID,
Packit 4b6dd7
	                                 g_param_spec_string ("document-id",
Packit 4b6dd7
	                                                      "Document ID", "The document ID of the document.",
Packit 4b6dd7
	                                                      NULL,
Packit 4b6dd7
	                                                      G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_DEPRECATED));
Packit 4b6dd7
Packit 4b6dd7
	/**
Packit 4b6dd7
	 * GDataDocumentsEntry:last-modified-by:
Packit 4b6dd7
	 *
Packit 4b6dd7
	 * Indicates the author of the last modification.
Packit 4b6dd7
	 *
Packit 4b6dd7
	 * Since: 0.4.0
Packit 4b6dd7
	 */
Packit 4b6dd7
	g_object_class_install_property (gobject_class, PROP_LAST_MODIFIED_BY,
Packit 4b6dd7
	                                 g_param_spec_object ("last-modified-by",
Packit 4b6dd7
	                                                      "Last modified by", "Indicates the author of the last modification.",
Packit 4b6dd7
	                                                      GDATA_TYPE_AUTHOR,
Packit 4b6dd7
	                                                      G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
Packit 4b6dd7
Packit 4b6dd7
	/**
Packit 4b6dd7
	 * GDataDocumentsEntry:quota-used:
Packit 4b6dd7
	 *
Packit 4b6dd7
	 * The amount of user quota the document is occupying. Currently, only arbitrary files consume file space quota (whereas standard document
Packit 4b6dd7
	 * formats, such as #GDataDocumentsText, #GDataDocumentsSpreadsheet and #GDataDocumentsFolder don't). Measured in bytes.
Packit 4b6dd7
	 *
Packit 4b6dd7
	 * This property will be 0 for documents which aren't consuming any quota.
Packit 4b6dd7
	 *
Packit 4b6dd7
	 * Since: 0.13.0
Packit 4b6dd7
	 */
Packit 4b6dd7
	g_object_class_install_property (gobject_class, PROP_QUOTA_USED,
Packit 4b6dd7
	                                 g_param_spec_int64 ("quota-used",
Packit 4b6dd7
	                                                     "Quota used", "The amount of user quota the document is occupying.",
Packit 4b6dd7
	                                                     0, G_MAXINT64, 0,
Packit 4b6dd7
	                                                     G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
Packit 4b6dd7
Packit 4b6dd7
	/**
Packit 4b6dd7
	 * GDataDocumentsEntry:file-size:
Packit 4b6dd7
	 *
Packit 4b6dd7
         * The size of the document. This is only set for non-document files.
Packit 4b6dd7
         * Standard formats, such as #GDataDocumentsText,
Packit 4b6dd7
         * #GDataDocumentsSpreadsheet and #GDataDocumentsFolder are not binary
Packit 4b6dd7
         * data and so have no size. Measured in bytes.
Packit 4b6dd7
	 *
Packit 4b6dd7
	 * Since: 0.17.7
Packit 4b6dd7
	 */
Packit 4b6dd7
	g_object_class_install_property (gobject_class, PROP_FILE_SIZE,
Packit 4b6dd7
	                                 g_param_spec_int64 ("file-size",
Packit 4b6dd7
	                                                     "File size", "The size of the document.",
Packit 4b6dd7
	                                                     0, G_MAXINT64, 0,
Packit 4b6dd7
	                                                     G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
Packit 4b6dd7
}
Packit 4b6dd7
Packit 4b6dd7
static gboolean
Packit 4b6dd7
is_owner_rule (GDataAccessRule *rule)
Packit 4b6dd7
{
Packit 4b6dd7
	return (strcmp (gdata_access_rule_get_role (rule), GDATA_DOCUMENTS_ACCESS_ROLE_OWNER) == 0) ? TRUE : FALSE;
Packit 4b6dd7
}
Packit 4b6dd7
Packit 4b6dd7
static GDataAuthorizationDomain *
Packit 4b6dd7
get_authorization_domain (GDataAccessHandler *self)
Packit 4b6dd7
{
Packit 4b6dd7
	return gdata_documents_service_get_primary_authorization_domain ();
Packit 4b6dd7
}
Packit 4b6dd7
Packit 4b6dd7
static GDataFeed *
Packit 4b6dd7
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
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
	feed = _gdata_feed_new_from_json (GDATA_TYPE_FEED, message->response_body->data, message->response_body->length, GDATA_TYPE_DOCUMENTS_ACCESS_RULE,
Packit 4b6dd7
					  progress_callback, progress_user_data, error);
Packit 4b6dd7
Packit 4b6dd7
	g_object_unref (message);
Packit 4b6dd7
Packit 4b6dd7
	return feed;
Packit 4b6dd7
}
Packit 4b6dd7
Packit 4b6dd7
static void
Packit 4b6dd7
gdata_documents_entry_access_handler_init (GDataAccessHandlerIface *iface)
Packit 4b6dd7
{
Packit 4b6dd7
	iface->is_owner_rule = is_owner_rule;
Packit 4b6dd7
	iface->get_authorization_domain = get_authorization_domain;
Packit 4b6dd7
	iface->get_rules = get_rules;
Packit 4b6dd7
}
Packit 4b6dd7
Packit 4b6dd7
static void
Packit 4b6dd7
gdata_documents_entry_init (GDataDocumentsEntry *self)
Packit 4b6dd7
{
Packit 4b6dd7
	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GDATA_TYPE_DOCUMENTS_ENTRY, GDataDocumentsEntryPrivate);
Packit 4b6dd7
	self->priv->last_viewed = -1;
Packit 4b6dd7
}
Packit 4b6dd7
Packit 4b6dd7
static void
Packit 4b6dd7
gdata_entry_dispose (GObject *object)
Packit 4b6dd7
{
Packit 4b6dd7
	GDataDocumentsEntryPrivate *priv = GDATA_DOCUMENTS_ENTRY (object)->priv;
Packit 4b6dd7
Packit 4b6dd7
	if (priv->last_modified_by != NULL)
Packit 4b6dd7
		g_object_unref (priv->last_modified_by);
Packit 4b6dd7
	priv->last_modified_by = NULL;
Packit 4b6dd7
Packit 4b6dd7
	/* Chain up to the parent class */
Packit 4b6dd7
	G_OBJECT_CLASS (gdata_documents_entry_parent_class)->dispose (object);
Packit 4b6dd7
}
Packit 4b6dd7
Packit 4b6dd7
static void
Packit 4b6dd7
gdata_documents_entry_finalize (GObject *object)
Packit 4b6dd7
{
Packit 4b6dd7
	GDataDocumentsEntryPrivate *priv = GDATA_DOCUMENTS_ENTRY (object)->priv;
Packit 4b6dd7
Packit 4b6dd7
	g_free (priv->resource_id);
Packit 4b6dd7
Packit 4b6dd7
	/* Chain up to the parent class */
Packit 4b6dd7
	G_OBJECT_CLASS (gdata_documents_entry_parent_class)->finalize (object);
Packit 4b6dd7
}
Packit 4b6dd7
Packit 4b6dd7
static void
Packit 4b6dd7
gdata_documents_entry_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
Packit 4b6dd7
{
Packit 4b6dd7
	GDataDocumentsEntryPrivate *priv = GDATA_DOCUMENTS_ENTRY (object)->priv;
Packit 4b6dd7
Packit 4b6dd7
	switch (property_id) {
Packit 4b6dd7
		case PROP_RESOURCE_ID:
Packit 4b6dd7
			g_value_set_string (value, priv->resource_id);
Packit 4b6dd7
			break;
Packit 4b6dd7
		case PROP_DOCUMENT_ID:
Packit 4b6dd7
			g_value_set_string (value, gdata_entry_get_id (GDATA_ENTRY (object)));
Packit 4b6dd7
			break;
Packit 4b6dd7
		case PROP_WRITERS_CAN_INVITE:
Packit 4b6dd7
			g_value_set_boolean (value, priv->writers_can_invite);
Packit 4b6dd7
			break;
Packit 4b6dd7
		case PROP_IS_DELETED:
Packit 4b6dd7
			g_value_set_boolean (value, priv->is_deleted);
Packit 4b6dd7
			break;
Packit 4b6dd7
		case PROP_EDITED:
Packit 4b6dd7
			g_value_set_int64 (value, gdata_entry_get_updated (GDATA_ENTRY (object)));
Packit 4b6dd7
			break;
Packit 4b6dd7
		case PROP_LAST_VIEWED:
Packit 4b6dd7
			g_value_set_int64 (value, priv->last_viewed);
Packit 4b6dd7
			break;
Packit 4b6dd7
		case PROP_LAST_MODIFIED_BY:
Packit 4b6dd7
			g_value_set_object (value, priv->last_modified_by);
Packit 4b6dd7
			break;
Packit 4b6dd7
		case PROP_QUOTA_USED:
Packit 4b6dd7
			g_value_set_int64 (value, priv->quota_used);
Packit 4b6dd7
			break;
Packit 4b6dd7
		case PROP_FILE_SIZE:
Packit 4b6dd7
			g_value_set_int64 (value, priv->file_size);
Packit 4b6dd7
			break;
Packit 4b6dd7
		default:
Packit 4b6dd7
			/* We don't have any other property... */
Packit 4b6dd7
			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
Packit 4b6dd7
			break;
Packit 4b6dd7
	}
Packit 4b6dd7
}
Packit 4b6dd7
Packit 4b6dd7
static void
Packit 4b6dd7
gdata_documents_entry_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
Packit 4b6dd7
{
Packit 4b6dd7
	GDataDocumentsEntry *self = GDATA_DOCUMENTS_ENTRY (object);
Packit 4b6dd7
Packit 4b6dd7
	switch (property_id) {
Packit 4b6dd7
		case PROP_WRITERS_CAN_INVITE:
Packit 4b6dd7
			gdata_documents_entry_set_writers_can_invite (self, g_value_get_boolean (value));
Packit 4b6dd7
			break;
Packit 4b6dd7
		case PROP_QUOTA_USED:
Packit 4b6dd7
		case PROP_FILE_SIZE:
Packit 4b6dd7
			/* Read only. */
Packit 4b6dd7
		default:
Packit 4b6dd7
			/* We don't have any other property... */
Packit 4b6dd7
			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
Packit 4b6dd7
			break;
Packit 4b6dd7
	}
Packit 4b6dd7
}
Packit 4b6dd7
Packit 4b6dd7
static void
Packit 4b6dd7
get_kind_email_and_name (JsonReader *reader, gchar **out_kind, gchar **out_email, gchar **out_name, GError **error)
Packit 4b6dd7
{
Packit 4b6dd7
	GError *child_error = NULL;
Packit 4b6dd7
	gboolean success;
Packit 4b6dd7
	gchar *email = NULL;
Packit 4b6dd7
	gchar *kind = NULL;
Packit 4b6dd7
	gchar *name = NULL;
Packit 4b6dd7
	guint i, members;
Packit 4b6dd7
Packit 4b6dd7
	for (i = 0, members = (guint) json_reader_count_members (reader); i < members; i++) {
Packit 4b6dd7
		json_reader_read_element (reader, i);
Packit 4b6dd7
Packit 4b6dd7
		if (gdata_parser_string_from_json_member (reader, "kind", P_REQUIRED | P_NON_EMPTY, &kind, &success, &child_error) == TRUE) {
Packit 4b6dd7
			if (!success && child_error != NULL) {
Packit 4b6dd7
				g_propagate_prefixed_error (error, child_error,
Packit 4b6dd7
				                            /* Translators: the parameter is an error message */
Packit 4b6dd7
				                            _("Error parsing JSON: %s"),
Packit 4b6dd7
				                            "Failed to find ‘kind’.");
Packit 4b6dd7
				json_reader_end_element (reader);
Packit 4b6dd7
				goto out;
Packit 4b6dd7
			}
Packit 4b6dd7
		}
Packit 4b6dd7
Packit 4b6dd7
		if (gdata_parser_string_from_json_member (reader, "displayName", P_REQUIRED | P_NON_EMPTY, &name, &success, &child_error) == TRUE) {
Packit 4b6dd7
			if (!success && child_error != NULL) {
Packit 4b6dd7
				g_propagate_prefixed_error (error, child_error,
Packit 4b6dd7
				                            /* Translators: the parameter is an error message */
Packit 4b6dd7
				                            _("Error parsing JSON: %s"),
Packit 4b6dd7
				                            "Failed to find ‘displayName’.");
Packit 4b6dd7
				json_reader_end_element (reader);
Packit 4b6dd7
				goto out;
Packit 4b6dd7
			}
Packit 4b6dd7
		}
Packit 4b6dd7
Packit 4b6dd7
		if (gdata_parser_string_from_json_member (reader, "emailAddress", P_DEFAULT, &email, &success, &child_error) == TRUE) {
Packit 4b6dd7
			if (!success && child_error != NULL) {
Packit 4b6dd7
				g_propagate_prefixed_error (error, child_error,
Packit 4b6dd7
				                            /* Translators: the parameter is an error message */
Packit 4b6dd7
				                            _("Error parsing JSON: %s"),
Packit 4b6dd7
				                            "Failed to find ‘emailAddress’.");
Packit 4b6dd7
				json_reader_end_element (reader);
Packit 4b6dd7
				goto out;
Packit 4b6dd7
			}
Packit 4b6dd7
		}
Packit 4b6dd7
Packit 4b6dd7
		json_reader_end_element (reader);
Packit 4b6dd7
	}
Packit 4b6dd7
Packit 4b6dd7
	if (out_kind != NULL) {
Packit 4b6dd7
		*out_kind = kind;
Packit 4b6dd7
		kind = NULL;
Packit 4b6dd7
	}
Packit 4b6dd7
Packit 4b6dd7
	if (out_email != NULL) {
Packit 4b6dd7
		*out_email = email;
Packit 4b6dd7
		email = NULL;
Packit 4b6dd7
	}
Packit 4b6dd7
Packit 4b6dd7
	if (out_name != NULL) {
Packit 4b6dd7
		*out_name = name;
Packit 4b6dd7
		name = NULL;
Packit 4b6dd7
	}
Packit 4b6dd7
Packit 4b6dd7
 out:
Packit 4b6dd7
	g_free (kind);
Packit 4b6dd7
	g_free (email);
Packit 4b6dd7
	g_free (name);
Packit 4b6dd7
}
Packit 4b6dd7
Packit 4b6dd7
static void
Packit 4b6dd7
get_kind_and_parent_link (JsonReader *reader, gchar **out_kind, gchar **out_parent_link, GError **error)
Packit 4b6dd7
{
Packit 4b6dd7
	GError *child_error = NULL;
Packit 4b6dd7
	gboolean success;
Packit 4b6dd7
	gchar *kind = NULL;
Packit 4b6dd7
	gchar *parent_link = NULL;
Packit 4b6dd7
	guint i, members;
Packit 4b6dd7
Packit 4b6dd7
	for (i = 0, members = (guint) json_reader_count_members (reader); i < members; i++) {
Packit 4b6dd7
		json_reader_read_element (reader, i);
Packit 4b6dd7
Packit 4b6dd7
		if (gdata_parser_string_from_json_member (reader, "kind", P_REQUIRED | P_NON_EMPTY, &kind, &success, &child_error) == TRUE) {
Packit 4b6dd7
			if (!success && child_error != NULL) {
Packit 4b6dd7
				g_propagate_prefixed_error (error, child_error,
Packit 4b6dd7
				                            /* Translators: the parameter is an error message */
Packit 4b6dd7
				                            _("Error parsing JSON: %s"),
Packit 4b6dd7
				                            "Failed to find ‘kind’.");
Packit 4b6dd7
				json_reader_end_element (reader);
Packit 4b6dd7
				goto out;
Packit 4b6dd7
			}
Packit 4b6dd7
		}
Packit 4b6dd7
Packit 4b6dd7
		if (gdata_parser_string_from_json_member (reader, "parentLink", P_REQUIRED | P_NON_EMPTY, &parent_link, &success, &child_error) == TRUE) {
Packit 4b6dd7
			if (!success && child_error != NULL) {
Packit 4b6dd7
				g_propagate_prefixed_error (error, child_error,
Packit 4b6dd7
				                            /* Translators: the parameter is an error message */
Packit 4b6dd7
				                            _("Error parsing JSON: %s"),
Packit 4b6dd7
				                            "Failed to find ‘parentLink’.");
Packit 4b6dd7
				json_reader_end_element (reader);
Packit 4b6dd7
				goto out;
Packit 4b6dd7
			}
Packit 4b6dd7
		}
Packit 4b6dd7
Packit 4b6dd7
		json_reader_end_element (reader);
Packit 4b6dd7
	}
Packit 4b6dd7
Packit 4b6dd7
	if (out_kind != NULL) {
Packit 4b6dd7
		*out_kind = kind;
Packit 4b6dd7
		kind = NULL;
Packit 4b6dd7
	}
Packit 4b6dd7
Packit 4b6dd7
	if (out_parent_link != NULL) {
Packit 4b6dd7
		*out_parent_link = parent_link;
Packit 4b6dd7
		parent_link = NULL;
Packit 4b6dd7
	}
Packit 4b6dd7
Packit 4b6dd7
 out:
Packit 4b6dd7
	g_free (kind);
Packit 4b6dd7
	g_free (parent_link);
Packit 4b6dd7
}
Packit 4b6dd7
Packit 4b6dd7
static gboolean
Packit 4b6dd7
parse_json (GDataParsable *parsable, JsonReader *reader, gpointer user_data, GError **error)
Packit 4b6dd7
{
Packit 4b6dd7
	GDataDocumentsEntryPrivate *priv = GDATA_DOCUMENTS_ENTRY (parsable)->priv;
Packit 4b6dd7
	GDataCategory *category;
Packit 4b6dd7
	GError *child_error = NULL;
Packit 4b6dd7
	gboolean shared;
Packit 4b6dd7
	gboolean success = TRUE;
Packit 4b6dd7
	gchar *alternate_uri = NULL;
Packit 4b6dd7
	gchar *kind = NULL;
Packit 4b6dd7
	gchar *mime_type = NULL;
Packit 4b6dd7
	gchar *quota_used = NULL;
Packit 4b6dd7
	gchar *file_size = NULL;
Packit 4b6dd7
	gint64 published;
Packit 4b6dd7
	gint64 updated;
Packit 4b6dd7
Packit 4b6dd7
	/* JSON format: https://developers.google.com/drive/v2/reference/files */
Packit 4b6dd7
Packit 4b6dd7
	if (gdata_parser_string_from_json_member (reader, "alternateLink", P_DEFAULT, &alternate_uri, &success, error) == TRUE) {
Packit 4b6dd7
		if (success && alternate_uri != NULL && alternate_uri[0] != '\0') {
Packit 4b6dd7
			GDataLink *_link;
Packit 4b6dd7
Packit 4b6dd7
			_link = gdata_link_new (alternate_uri, GDATA_LINK_ALTERNATE);
Packit 4b6dd7
			gdata_entry_add_link (GDATA_ENTRY (parsable), _link);
Packit 4b6dd7
			g_object_unref (_link);
Packit 4b6dd7
		}
Packit 4b6dd7
Packit 4b6dd7
		g_free (alternate_uri);
Packit 4b6dd7
		return success;
Packit 4b6dd7
	} else if (gdata_parser_string_from_json_member (reader, "mimeType", P_DEFAULT, &mime_type, &success, error) == TRUE) {
Packit 4b6dd7
		if (success)
Packit 4b6dd7
			gdata_documents_utils_add_content_type (GDATA_DOCUMENTS_ENTRY (parsable), mime_type);
Packit 4b6dd7
		g_free (mime_type);
Packit 4b6dd7
		return success;
Packit 4b6dd7
	} else if (gdata_parser_int64_time_from_json_member (reader, "lastViewedByMeDate", P_DEFAULT, &(priv->last_viewed), &success, error) == TRUE ||
Packit 4b6dd7
		   gdata_parser_string_from_json_member (reader, "kind", P_REQUIRED | P_NON_EMPTY, &kind, &success, error) == TRUE) {
Packit 4b6dd7
		g_free (kind);
Packit 4b6dd7
		return success;
Packit 4b6dd7
	} else if (gdata_parser_int64_time_from_json_member (reader, "createdDate", P_DEFAULT, &published, &success, error) == TRUE) {
Packit 4b6dd7
		if (success)
Packit 4b6dd7
			_gdata_entry_set_published (GDATA_ENTRY (parsable), published);
Packit 4b6dd7
		return success;
Packit 4b6dd7
	} else if (gdata_parser_int64_time_from_json_member (reader, "modifiedDate", P_DEFAULT, &updated, &success, error) == TRUE) {
Packit 4b6dd7
		if (success)
Packit 4b6dd7
			_gdata_entry_set_updated (GDATA_ENTRY (parsable), updated);
Packit 4b6dd7
		return success;
Packit 4b6dd7
	} else if (gdata_parser_string_from_json_member (reader, "quotaBytesUsed", P_DEFAULT, &quota_used, &success, error) == TRUE) {
Packit 4b6dd7
		gchar *end_ptr;
Packit 4b6dd7
		guint64 val;
Packit 4b6dd7
Packit 4b6dd7
		/* Even though ‘quotaBytesUsed’ is documented as long,
Packit 4b6dd7
		 * it is actually a string in the JSON.
Packit 4b6dd7
		 */
Packit 4b6dd7
		val = g_ascii_strtoull (quota_used, &end_ptr, 10);
Packit 4b6dd7
		if (*end_ptr == '\0')
Packit 4b6dd7
			priv->quota_used = (goffset) val;
Packit 4b6dd7
		g_free (quota_used);
Packit 4b6dd7
		return success;
Packit 4b6dd7
	} else if (gdata_parser_string_from_json_member (reader, "fileSize", P_DEFAULT, &file_size, &success, error) == TRUE) {
Packit 4b6dd7
		gchar *end_ptr;
Packit 4b6dd7
		guint64 val;
Packit 4b6dd7
Packit 4b6dd7
		/* like 'quotaBytesUsed', 'fileSize' is also a string
Packit 4b6dd7
		 * in the JSON.
Packit 4b6dd7
		 */
Packit 4b6dd7
		val = g_ascii_strtoull (file_size, &end_ptr, 10);
Packit 4b6dd7
		if (*end_ptr == '\0')
Packit 4b6dd7
			priv->file_size = (goffset) val;
Packit 4b6dd7
		g_free (file_size);
Packit 4b6dd7
		return success;
Packit 4b6dd7
	} else if (gdata_parser_boolean_from_json_member (reader, "shared", P_DEFAULT, &shared, &success, error) == TRUE) {
Packit 4b6dd7
		if (success && shared) {
Packit 4b6dd7
			category = gdata_category_new ("http://schemas.google.com/g/2005/labels#shared", GDATA_CATEGORY_SCHEMA_LABELS, "shared");
Packit 4b6dd7
			gdata_entry_add_category (GDATA_ENTRY (parsable), category);
Packit 4b6dd7
			g_object_unref (category);
Packit 4b6dd7
		}
Packit 4b6dd7
		return success;
Packit 4b6dd7
	} else if (g_strcmp0 (json_reader_get_member_name (reader), "labels") == 0) {
Packit 4b6dd7
		guint i, members;
Packit 4b6dd7
Packit 4b6dd7
		if (json_reader_is_object (reader) == FALSE) {
Packit 4b6dd7
			g_set_error (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_PROTOCOL_ERROR,
Packit 4b6dd7
			             /* Translators: the parameter is an error message */
Packit 4b6dd7
			             _("Error parsing JSON: %s"),
Packit 4b6dd7
			             "JSON node ‘labels’ is not an object.");
Packit 4b6dd7
			return FALSE;
Packit 4b6dd7
		}
Packit 4b6dd7
Packit 4b6dd7
		for (i = 0, members = (guint) json_reader_count_members (reader); i < members; i++) {
Packit 4b6dd7
			gboolean starred;
Packit 4b6dd7
			gboolean viewed;
Packit 4b6dd7
Packit 4b6dd7
			json_reader_read_element (reader, i);
Packit 4b6dd7
Packit 4b6dd7
			gdata_parser_boolean_from_json_member (reader, "starred", P_DEFAULT, &starred, &success, NULL);
Packit 4b6dd7
			if (success && starred) {
Packit 4b6dd7
				category = gdata_category_new (GDATA_CATEGORY_SCHEMA_LABELS_STARRED, GDATA_CATEGORY_SCHEMA_LABELS, "starred");
Packit 4b6dd7
				gdata_entry_add_category (GDATA_ENTRY (parsable), category);
Packit 4b6dd7
				g_object_unref (category);
Packit 4b6dd7
			}
Packit 4b6dd7
Packit 4b6dd7
			gdata_parser_boolean_from_json_member (reader, "viewed", P_DEFAULT, &viewed, &success, NULL);
Packit 4b6dd7
			if (success && viewed) {
Packit 4b6dd7
				category = gdata_category_new ("http://schemas.google.com/g/2005/labels#viewed", GDATA_CATEGORY_SCHEMA_LABELS, "viewed");
Packit 4b6dd7
				gdata_entry_add_category (GDATA_ENTRY (parsable), category);
Packit 4b6dd7
				g_object_unref (category);
Packit 4b6dd7
			}
Packit 4b6dd7
Packit 4b6dd7
			json_reader_end_element (reader);
Packit 4b6dd7
		}
Packit 4b6dd7
Packit 4b6dd7
		return TRUE;
Packit 4b6dd7
	} else if (g_strcmp0 (json_reader_get_member_name (reader), "owners") == 0) {
Packit 4b6dd7
		guint i, elements;
Packit 4b6dd7
Packit 4b6dd7
		if (json_reader_is_array (reader) == FALSE) {
Packit 4b6dd7
			g_set_error (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_PROTOCOL_ERROR,
Packit 4b6dd7
			             /* Translators: the parameter is an error message */
Packit 4b6dd7
			             _("Error parsing JSON: %s"),
Packit 4b6dd7
			             "JSON node ‘owners’ is not an array.");
Packit 4b6dd7
			return FALSE;
Packit 4b6dd7
		}
Packit 4b6dd7
Packit 4b6dd7
		/* Loop through the elements array. */
Packit 4b6dd7
		for (i = 0, elements = json_reader_count_elements (reader); success && i < elements; i++) {
Packit 4b6dd7
			gchar *email = NULL;
Packit 4b6dd7
			gchar *name = NULL;
Packit 4b6dd7
Packit 4b6dd7
			json_reader_read_element (reader, i);
Packit 4b6dd7
Packit 4b6dd7
			if (json_reader_is_object (reader) == FALSE) {
Packit 4b6dd7
				g_set_error (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_PROTOCOL_ERROR,
Packit 4b6dd7
				             /* Translators: the parameter is an error message */
Packit 4b6dd7
				             _("Error parsing JSON: %s"),
Packit 4b6dd7
				             "JSON node inside ‘owners’ is not an object.");
Packit 4b6dd7
				success = FALSE;
Packit 4b6dd7
				goto continue_owners;
Packit 4b6dd7
			}
Packit 4b6dd7
Packit 4b6dd7
			get_kind_email_and_name (reader, &kind, &email, &name, &child_error);
Packit 4b6dd7
			if (child_error != NULL) {
Packit 4b6dd7
				g_propagate_error (error, child_error);
Packit 4b6dd7
				success = FALSE;
Packit 4b6dd7
				goto continue_owners;
Packit 4b6dd7
			}
Packit 4b6dd7
			if (name == NULL || name[0] == '\0') {
Packit 4b6dd7
				g_set_error (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_PROTOCOL_ERROR,
Packit 4b6dd7
				             /* Translators: the parameter is an error message */
Packit 4b6dd7
				             _("Error parsing JSON: %s"),
Packit 4b6dd7
				             "Failed to find ‘displayName’.");
Packit 4b6dd7
				success = FALSE;
Packit 4b6dd7
				goto continue_owners;
Packit 4b6dd7
			}
Packit 4b6dd7
Packit 4b6dd7
			if (g_strcmp0 (kind, "drive#user") == 0) {
Packit 4b6dd7
				GDataAuthor *author;
Packit 4b6dd7
Packit 4b6dd7
				author = gdata_author_new (name, NULL, email);
Packit 4b6dd7
				gdata_entry_add_author (GDATA_ENTRY (parsable), author);
Packit 4b6dd7
				g_object_unref (author);
Packit 4b6dd7
			} else {
Packit 4b6dd7
				g_warning ("%s authors are not handled yet", kind);
Packit 4b6dd7
			}
Packit 4b6dd7
Packit 4b6dd7
		continue_owners:
Packit 4b6dd7
			g_free (email);
Packit 4b6dd7
			g_free (kind);
Packit 4b6dd7
			g_free (name);
Packit 4b6dd7
			json_reader_end_element (reader);
Packit 4b6dd7
		}
Packit 4b6dd7
Packit 4b6dd7
		return success;
Packit 4b6dd7
	} else if (g_strcmp0 (json_reader_get_member_name (reader), "parents") == 0) {
Packit 4b6dd7
		guint i, elements;
Packit 4b6dd7
Packit 4b6dd7
		if (json_reader_is_array (reader) == FALSE) {
Packit 4b6dd7
			g_set_error (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_PROTOCOL_ERROR,
Packit 4b6dd7
			             /* Translators: the parameter is an error message */
Packit 4b6dd7
			             _("Error parsing JSON: %s"),
Packit 4b6dd7
			             "JSON node ‘parents’ is not an array.");
Packit 4b6dd7
			return FALSE;
Packit 4b6dd7
		}
Packit 4b6dd7
Packit 4b6dd7
		/* Loop through the elements array. */
Packit 4b6dd7
		for (i = 0, elements = (guint) json_reader_count_elements (reader); success && i < elements; i++) {
Packit 4b6dd7
			GDataLink *_link = NULL;
Packit 4b6dd7
			const gchar *relation_type = NULL;
Packit 4b6dd7
			gchar *uri = NULL;
Packit 4b6dd7
Packit 4b6dd7
			json_reader_read_element (reader, i);
Packit 4b6dd7
Packit 4b6dd7
			if (json_reader_is_object (reader) == FALSE) {
Packit 4b6dd7
				g_set_error (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_PROTOCOL_ERROR,
Packit 4b6dd7
				             /* Translators: the parameter is an error message */
Packit 4b6dd7
				             _("Error parsing JSON: %s"),
Packit 4b6dd7
				             "JSON node inside ‘parents’ is not an object.");
Packit 4b6dd7
				success = FALSE;
Packit 4b6dd7
				goto continue_parents;
Packit 4b6dd7
			}
Packit 4b6dd7
Packit 4b6dd7
			get_kind_and_parent_link (reader, &kind, &uri, &child_error);
Packit 4b6dd7
			if (child_error != NULL) {
Packit 4b6dd7
				g_propagate_error (error, child_error);
Packit 4b6dd7
				success = FALSE;
Packit 4b6dd7
				goto continue_parents;
Packit 4b6dd7
			}
Packit 4b6dd7
Packit 4b6dd7
			if (g_strcmp0 (kind, "drive#parentReference") == 0) {
Packit 4b6dd7
				relation_type = GDATA_LINK_PARENT;
Packit 4b6dd7
			} else {
Packit 4b6dd7
				g_warning ("%s parents are not handled yet", kind);
Packit 4b6dd7
			}
Packit 4b6dd7
Packit 4b6dd7
			if (relation_type == NULL)
Packit 4b6dd7
				goto continue_parents;
Packit 4b6dd7
Packit 4b6dd7
			_link = gdata_link_new (uri, relation_type);
Packit 4b6dd7
			gdata_entry_add_link (GDATA_ENTRY (parsable), _link);
Packit 4b6dd7
Packit 4b6dd7
		continue_parents:
Packit 4b6dd7
			g_clear_object (&_link);
Packit 4b6dd7
			g_free (kind);
Packit 4b6dd7
			g_free (uri);
Packit 4b6dd7
			json_reader_end_element (reader);
Packit 4b6dd7
		}
Packit 4b6dd7
Packit 4b6dd7
		return success;
Packit 4b6dd7
	}
Packit 4b6dd7
Packit 4b6dd7
	return GDATA_PARSABLE_CLASS (gdata_documents_entry_parent_class)->parse_json (parsable, reader, user_data, error);
Packit 4b6dd7
}
Packit 4b6dd7
Packit 4b6dd7
static gboolean
Packit 4b6dd7
post_parse_json (GDataParsable *parsable, gpointer user_data, GError **error)
Packit 4b6dd7
{
Packit 4b6dd7
	GDataDocumentsEntryPrivate *priv = GDATA_DOCUMENTS_ENTRY (parsable)->priv;
Packit 4b6dd7
	GDataLink *_link;
Packit 4b6dd7
	const gchar *id;
Packit 4b6dd7
	gchar *uri;
Packit 4b6dd7
Packit 4b6dd7
	id = gdata_entry_get_id (GDATA_ENTRY (parsable));
Packit 4b6dd7
Packit 4b6dd7
	/* gdata_access_handler_get_rules requires the presence of a GDATA_LINK_ACCESS_CONTROL_LIST link with the
Packit 4b6dd7
	 * right URI. */
Packit 4b6dd7
	uri = g_strconcat ("https://www.googleapis.com/drive/v2/files/", id, "/permissions", NULL);
Packit 4b6dd7
	_link = gdata_link_new (uri, GDATA_LINK_ACCESS_CONTROL_LIST);
Packit 4b6dd7
	gdata_entry_add_link (GDATA_ENTRY (parsable), _link);
Packit 4b6dd7
	g_free (uri);
Packit 4b6dd7
	g_object_unref (_link);
Packit 4b6dd7
Packit 4b6dd7
	/* Since the document-id is identical to GDataEntry:id, which is parsed by the parent class, we can't
Packit 4b6dd7
	 * create the resource-id while parsing. */
Packit 4b6dd7
	priv->resource_id = g_strconcat ("document:", id, NULL);
Packit 4b6dd7
Packit 4b6dd7
	return TRUE;
Packit 4b6dd7
}
Packit 4b6dd7
Packit 4b6dd7
static const gchar *
Packit 4b6dd7
get_content_type (void)
Packit 4b6dd7
{
Packit 4b6dd7
	return "application/json";
Packit 4b6dd7
}
Packit 4b6dd7
Packit 4b6dd7
static void
Packit 4b6dd7
get_json (GDataParsable *parsable, JsonBuilder *builder)
Packit 4b6dd7
{
Packit 4b6dd7
	GList *i;
Packit 4b6dd7
	GList *parent_folders_list;
Packit 4b6dd7
	const gchar *mime_type;
Packit 4b6dd7
Packit 4b6dd7
	GDATA_PARSABLE_CLASS (gdata_documents_entry_parent_class)->get_json (parsable, builder);
Packit 4b6dd7
Packit 4b6dd7
	/* Inserting files: https://developers.google.com/drive/v2/reference/files/insert */
Packit 4b6dd7
Packit 4b6dd7
	mime_type = gdata_documents_utils_get_content_type (GDATA_DOCUMENTS_ENTRY (parsable));
Packit 4b6dd7
	if (mime_type != NULL) {
Packit 4b6dd7
		json_builder_set_member_name (builder, "mimeType");
Packit 4b6dd7
		json_builder_add_string_value (builder, mime_type);
Packit 4b6dd7
	}
Packit 4b6dd7
Packit 4b6dd7
	/* Upload to a folder: https://developers.google.com/drive/v2/web/folder */
Packit 4b6dd7
Packit 4b6dd7
	json_builder_set_member_name (builder, "parents");
Packit 4b6dd7
	json_builder_begin_array (builder);
Packit 4b6dd7
Packit 4b6dd7
	parent_folders_list = gdata_entry_look_up_links (GDATA_ENTRY (parsable), GDATA_LINK_PARENT);
Packit 4b6dd7
	for (i = parent_folders_list; i != NULL; i = i->next) {
Packit 4b6dd7
		GDataLink *_link = GDATA_LINK (i->data);
Packit 4b6dd7
		const gchar *id;
Packit 4b6dd7
Packit 4b6dd7
		id = gdata_documents_utils_get_id_from_link (_link);
Packit 4b6dd7
		if (id != NULL) {
Packit 4b6dd7
			json_builder_begin_object (builder);
Packit 4b6dd7
			json_builder_set_member_name (builder, "kind");
Packit 4b6dd7
			json_builder_add_string_value (builder, "drive#fileLink");
Packit 4b6dd7
			json_builder_set_member_name (builder, "id");
Packit 4b6dd7
			json_builder_add_string_value (builder, id);
Packit 4b6dd7
			json_builder_end_object (builder);
Packit 4b6dd7
		}
Packit 4b6dd7
	}
Packit 4b6dd7
Packit 4b6dd7
	json_builder_end_array (builder);
Packit 4b6dd7
Packit 4b6dd7
	g_list_free (parent_folders_list);
Packit 4b6dd7
Packit 4b6dd7
}
Packit 4b6dd7
Packit 4b6dd7
static void
Packit 4b6dd7
get_namespaces (GDataParsable *parsable, GHashTable *namespaces)
Packit 4b6dd7
{
Packit 4b6dd7
	/* Chain up to the parent class */
Packit 4b6dd7
	GDATA_PARSABLE_CLASS (gdata_documents_entry_parent_class)->get_namespaces (parsable, namespaces);
Packit 4b6dd7
Packit 4b6dd7
	g_hash_table_insert (namespaces, (gchar*) "docs", (gchar*) "http://schemas.google.com/docs/2007");
Packit 4b6dd7
}
Packit 4b6dd7
Packit 4b6dd7
static gchar *
Packit 4b6dd7
get_entry_uri (const gchar *id)
Packit 4b6dd7
{
Packit 4b6dd7
	return g_strconcat ("https://www.googleapis.com/drive/v2/files/", id, NULL);
Packit 4b6dd7
}
Packit 4b6dd7
Packit 4b6dd7
/**
Packit 4b6dd7
 * gdata_documents_entry_get_edited:
Packit 4b6dd7
 * @self: a #GDataDocumentsEntry
Packit 4b6dd7
 *
Packit 4b6dd7
 * Gets the #GDataDocumentsEntry:edited property. If the property is unset, -1 will be returned.
Packit 4b6dd7
 *
Packit 4b6dd7
 * Return value: the UNIX timestamp for the time the document was last edited, or -1
Packit 4b6dd7
 *
Packit 4b6dd7
 * Since: 0.4.0
Packit 4b6dd7
 * Deprecated: 0.17.0: Use gdata_entry_get_updated() instead. See #GDataDocumentsEntry:edited.
Packit 4b6dd7
 */
Packit 4b6dd7
gint64
Packit 4b6dd7
gdata_documents_entry_get_edited (GDataDocumentsEntry *self)
Packit 4b6dd7
{
Packit 4b6dd7
	g_return_val_if_fail (GDATA_IS_DOCUMENTS_ENTRY (self), -1);
Packit 4b6dd7
	return gdata_entry_get_updated (GDATA_ENTRY (self));
Packit 4b6dd7
}
Packit 4b6dd7
Packit 4b6dd7
/**
Packit 4b6dd7
 * gdata_documents_entry_get_last_viewed:
Packit 4b6dd7
 * @self: a #GDataDocumentsEntry
Packit 4b6dd7
 *
Packit 4b6dd7
 * Gets the #GDataDocumentsEntry:last-viewed property. If the property is unset, -1 will be returned.
Packit 4b6dd7
 *
Packit 4b6dd7
 * Return value: the UNIX timestamp for the time the document was last viewed, or -1
Packit 4b6dd7
 *
Packit 4b6dd7
 * Since: 0.4.0
Packit 4b6dd7
 */
Packit 4b6dd7
gint64
Packit 4b6dd7
gdata_documents_entry_get_last_viewed (GDataDocumentsEntry *self)
Packit 4b6dd7
{
Packit 4b6dd7
	g_return_val_if_fail (GDATA_IS_DOCUMENTS_ENTRY (self), -1);
Packit 4b6dd7
	return self->priv->last_viewed;
Packit 4b6dd7
}
Packit 4b6dd7
Packit 4b6dd7
/**
Packit 4b6dd7
 * gdata_documents_entry_get_path:
Packit 4b6dd7
 * @self: a #GDataDocumentsEntry
Packit 4b6dd7
 *
Packit 4b6dd7
 * Builds a path for the #GDataDocumentsEntry, starting from a root node and traversing the folders containing the document, then ending with the
Packit 4b6dd7
 * document's ID.
Packit 4b6dd7
 *
Packit 4b6dd7
 * An example path would be: <literal>/folder_id1/folder_id2/document_id</literal>.
Packit 4b6dd7
 *
Packit 4b6dd7
 * Note: the path is based on the entry/document IDs of the folders (#GDataEntry:id) and document (#GDataDocumentsEntry:document-id),
Packit 4b6dd7
 * and not the entries' human-readable names (#GDataEntry:title).
Packit 4b6dd7
 *
Packit 4b6dd7
 * Return value: the folder hierarchy path containing the document, or %NULL; free with g_free()
Packit 4b6dd7
 *
Packit 4b6dd7
 * Since: 0.4.0
Packit 4b6dd7
 */
Packit 4b6dd7
gchar *
Packit 4b6dd7
gdata_documents_entry_get_path (GDataDocumentsEntry *self)
Packit 4b6dd7
{
Packit 4b6dd7
	GList *element, *parent_folders_list = NULL;
Packit 4b6dd7
	GString *path;
Packit 4b6dd7
	const gchar *id;
Packit 4b6dd7
Packit 4b6dd7
	g_return_val_if_fail (GDATA_IS_DOCUMENTS_ENTRY (self), NULL);
Packit 4b6dd7
Packit 4b6dd7
	path = g_string_new ("/");
Packit 4b6dd7
	parent_folders_list = gdata_entry_look_up_links (GDATA_ENTRY (self), GDATA_LINK_PARENT);
Packit 4b6dd7
Packit 4b6dd7
	/* We check all the folders contained that are parents of the GDataDocumentsEntry */
Packit 4b6dd7
	for (element = parent_folders_list; element != NULL; element = element->next) {
Packit 4b6dd7
		guint i;
Packit 4b6dd7
		gchar *folder_id = NULL;
Packit 4b6dd7
		gchar **link_href_cut = g_strsplit (gdata_link_get_uri (GDATA_LINK (element->data)), "/", 0);
Packit 4b6dd7
Packit 4b6dd7
		/* Extract the folder ID from the folder URI, which is of the form:
Packit 4b6dd7
		 *   http://docs.google.com/feeds/documents/private/full/folder%3Afolder_id
Packit 4b6dd7
		 * We want the "folder_id" bit. */
Packit 4b6dd7
		for (i = 0;; i++) {
Packit 4b6dd7
			gchar **path_cut = NULL;
Packit 4b6dd7
Packit 4b6dd7
			if (link_href_cut[i] == NULL)
Packit 4b6dd7
				break;
Packit 4b6dd7
Packit 4b6dd7
			path_cut = g_strsplit (link_href_cut[i], "%3A", 2);
Packit 4b6dd7
			if (*path_cut != NULL) {
Packit 4b6dd7
				if (strcmp (path_cut[0], "folder") == 0){
Packit 4b6dd7
					folder_id = g_strdup (path_cut[1]);
Packit 4b6dd7
					g_strfreev (path_cut);
Packit 4b6dd7
					break;
Packit 4b6dd7
				}
Packit 4b6dd7
			}
Packit 4b6dd7
			g_strfreev (path_cut);
Packit 4b6dd7
		}
Packit 4b6dd7
		g_strfreev (link_href_cut);
Packit 4b6dd7
		g_assert (folder_id != NULL);
Packit 4b6dd7
Packit 4b6dd7
		/* Append the folder ID to our path */
Packit 4b6dd7
		g_string_append (path, folder_id);
Packit 4b6dd7
		g_string_append_c (path, '/');
Packit 4b6dd7
		g_free (folder_id);
Packit 4b6dd7
	}
Packit 4b6dd7
Packit 4b6dd7
	/* Append the entry ID */
Packit 4b6dd7
	id = gdata_entry_get_id (GDATA_ENTRY (self));
Packit 4b6dd7
	g_string_append (path, id);
Packit 4b6dd7
Packit 4b6dd7
	return g_string_free (path, FALSE);
Packit 4b6dd7
}
Packit 4b6dd7
Packit 4b6dd7
/**
Packit 4b6dd7
 * gdata_documents_entry_get_document_id:
Packit 4b6dd7
 * @self: a #GDataDocumentsEntry
Packit 4b6dd7
 *
Packit 4b6dd7
 * Gets the #GDataDocumentsEntry:document-id property. The
Packit 4b6dd7
 * <ulink type="http" url="https://developers.google.com/google-apps/documents-list/#terminology_used_in_this_guide">online GData Documentation</ulink>
Packit 4b6dd7
 * refers to these as “untyped resource IDs”.
Packit 4b6dd7
 *
Packit 4b6dd7
 * Return value: the document's document ID
Packit 4b6dd7
 *
Packit 4b6dd7
 * Since: 0.4.0
Packit 4b6dd7
 * Deprecated: 0.11.0: Use gdata_documents_entry_get_resource_id() instead. See #GDataDocumentsEntry:document-id.
Packit 4b6dd7
 */
Packit 4b6dd7
const gchar *
Packit 4b6dd7
gdata_documents_entry_get_document_id (GDataDocumentsEntry *self )
Packit 4b6dd7
{
Packit 4b6dd7
	g_return_val_if_fail (GDATA_IS_DOCUMENTS_ENTRY (self), NULL);
Packit 4b6dd7
	return gdata_entry_get_id (GDATA_ENTRY (self));
Packit 4b6dd7
}
Packit 4b6dd7
Packit 4b6dd7
/**
Packit 4b6dd7
 * gdata_documents_entry_get_resource_id:
Packit 4b6dd7
 * @self: a #GDataDocumentsEntry
Packit 4b6dd7
 *
Packit 4b6dd7
 * Gets the #GDataDocumentsEntry:resource-id property.
Packit 4b6dd7
 *
Packit 4b6dd7
 * Return value: the document's resource ID
Packit 4b6dd7
 *
Packit 4b6dd7
 * Since: 0.11.0
Packit 4b6dd7
 */
Packit 4b6dd7
const gchar *
Packit 4b6dd7
gdata_documents_entry_get_resource_id (GDataDocumentsEntry *self)
Packit 4b6dd7
{
Packit 4b6dd7
	g_return_val_if_fail (GDATA_IS_DOCUMENTS_ENTRY (self), NULL);
Packit 4b6dd7
	return self->priv->resource_id;
Packit 4b6dd7
}
Packit 4b6dd7
Packit 4b6dd7
/**
Packit 4b6dd7
 * gdata_documents_entry_set_writers_can_invite:
Packit 4b6dd7
 * @self: a #GDataDocumentsEntry
Packit 4b6dd7
 * @writers_can_invite: %TRUE if writers can invite other people to edit the document, %FALSE otherwise
Packit 4b6dd7
 *
Packit 4b6dd7
 * Sets the #GDataDocumentsEntry:writers-can-invite property to @writers_can_invite.
Packit 4b6dd7
 *
Packit 4b6dd7
 * Since: 0.4.0
Packit 4b6dd7
 */
Packit 4b6dd7
void
Packit 4b6dd7
gdata_documents_entry_set_writers_can_invite (GDataDocumentsEntry *self, gboolean writers_can_invite)
Packit 4b6dd7
{
Packit 4b6dd7
	g_return_if_fail (GDATA_IS_DOCUMENTS_ENTRY (self));
Packit 4b6dd7
	self->priv->writers_can_invite = writers_can_invite;
Packit 4b6dd7
	g_object_notify (G_OBJECT (self), "writers-can-invite");
Packit 4b6dd7
}
Packit 4b6dd7
Packit 4b6dd7
/**
Packit 4b6dd7
 * gdata_documents_entry_writers_can_invite:
Packit 4b6dd7
 * @self: a #GDataDocumentsEntry
Packit 4b6dd7
 *
Packit 4b6dd7
 * Gets the #GDataDocumentsEntry:writers-can-invite property.
Packit 4b6dd7
 *
Packit 4b6dd7
 * Return value: %TRUE if writers can invite other people to edit the document, %FALSE otherwise
Packit 4b6dd7
 *
Packit 4b6dd7
 * Since: 0.4.0
Packit 4b6dd7
 */
Packit 4b6dd7
gboolean
Packit 4b6dd7
gdata_documents_entry_writers_can_invite (GDataDocumentsEntry *self)
Packit 4b6dd7
{
Packit 4b6dd7
	g_return_val_if_fail (GDATA_IS_DOCUMENTS_ENTRY (self ), FALSE);
Packit 4b6dd7
	return self->priv->writers_can_invite;
Packit 4b6dd7
}
Packit 4b6dd7
Packit 4b6dd7
/**
Packit 4b6dd7
 * gdata_documents_entry_get_last_modified_by:
Packit 4b6dd7
 * @self: a #GDataDocumentsEntry
Packit 4b6dd7
 *
Packit 4b6dd7
 * Gets the #GDataDocumentsEntry:last-modified-by property.
Packit 4b6dd7
 *
Packit 4b6dd7
 * Return value: (transfer none): the author who last modified the document
Packit 4b6dd7
 *
Packit 4b6dd7
 * Since: 0.4.0
Packit 4b6dd7
 */
Packit 4b6dd7
GDataAuthor *
Packit 4b6dd7
gdata_documents_entry_get_last_modified_by (GDataDocumentsEntry *self)
Packit 4b6dd7
{
Packit 4b6dd7
	g_return_val_if_fail (GDATA_IS_DOCUMENTS_ENTRY (self), NULL);
Packit 4b6dd7
	return self->priv->last_modified_by;
Packit 4b6dd7
}
Packit 4b6dd7
Packit 4b6dd7
/**
Packit 4b6dd7
 * gdata_documents_entry_get_quota_used:
Packit 4b6dd7
 * @self: a #GDataDocumentsEntry
Packit 4b6dd7
 *
Packit 4b6dd7
 * Gets the #GDataDocumentsEntry:quota-used property.
Packit 4b6dd7
 *
Packit 4b6dd7
 * Return value: the number of quota bytes used by the document
Packit 4b6dd7
 *
Packit 4b6dd7
 * Since: 0.13.0
Packit 4b6dd7
 */
Packit 4b6dd7
goffset
Packit 4b6dd7
gdata_documents_entry_get_quota_used (GDataDocumentsEntry *self)
Packit 4b6dd7
{
Packit 4b6dd7
	g_return_val_if_fail (GDATA_IS_DOCUMENTS_ENTRY (self), 0);
Packit 4b6dd7
Packit 4b6dd7
	return self->priv->quota_used;
Packit 4b6dd7
}
Packit 4b6dd7
Packit 4b6dd7
/**
Packit 4b6dd7
 * gdata_documents_entry_get_file_size:
Packit 4b6dd7
 * @self: a #GDataDocumentsEntry
Packit 4b6dd7
 *
Packit 4b6dd7
 * Gets the #GDataDocumentsEntry:file-size property.
Packit 4b6dd7
 *
Packit 4b6dd7
 * Return value: the size of the document in bytes
Packit 4b6dd7
 *
Packit 4b6dd7
 * Since: 0.17.7
Packit 4b6dd7
 */
Packit 4b6dd7
goffset
Packit 4b6dd7
gdata_documents_entry_get_file_size (GDataDocumentsEntry *self)
Packit 4b6dd7
{
Packit 4b6dd7
	g_return_val_if_fail (GDATA_IS_DOCUMENTS_ENTRY (self), 0);
Packit 4b6dd7
Packit 4b6dd7
	return self->priv->file_size;
Packit 4b6dd7
}
Packit 4b6dd7
Packit 4b6dd7
/**
Packit 4b6dd7
 * gdata_documents_entry_is_deleted:
Packit 4b6dd7
 * @self: a #GDataDocumentsEntry
Packit 4b6dd7
 *
Packit 4b6dd7
 * Gets the #GDataDocumentsEntry:is-deleted property.
Packit 4b6dd7
 *
Packit 4b6dd7
 * Return value: %TRUE if the document has been deleted, %FALSE otherwise
Packit 4b6dd7
 *
Packit 4b6dd7
 * Since: 0.5.0
Packit 4b6dd7
 */
Packit 4b6dd7
gboolean
Packit 4b6dd7
gdata_documents_entry_is_deleted (GDataDocumentsEntry *self)
Packit 4b6dd7
{
Packit 4b6dd7
	g_return_val_if_fail (GDATA_IS_DOCUMENTS_ENTRY (self), FALSE);
Packit 4b6dd7
	return self->priv->is_deleted;
Packit 4b6dd7
}