static SoupMessage *
get_soup_message (GDataAccessHandler *access_handler, GDataAccessRule *rule, const gchar *method)
{
	GDataLink *link;
	SoupMessage *message;
	GString *uri_string;
	gchar *uri;
	const gchar *scope_type, *scope_value;

	/* Get the edit URI */
	link = gdata_entry_look_up_link (GDATA_ENTRY (rule), "edit");
	if (link != NULL)
		return soup_message_new (method, link->href);

	/* Try building the URI instead */
	link = gdata_entry_look_up_link (GDATA_ENTRY (access_handler), "http://schemas.google.com/acl/2007#accessControlList");
	g_assert (link != NULL);
	gdata_access_rule_get_scope (rule, &scope_type, &scope_value);

	uri_string = g_string_sized_new (strlen (link->href) + 30);
	g_string_append_printf (uri_string, "%s/", link->href);
	g_string_append_uri_escaped (uri_string, scope_type, NULL, TRUE);
	if (scope_value != NULL) {
		g_string_append (uri_string, "%3A");
		g_string_append_uri_escaped (uri_string, scope_value, NULL, TRUE);
	}

	uri = g_string_free (uri_string, FALSE);
	message = soup_message_new (method, uri);
	g_free (uri);

	return message;
}
/**
 * gdata_youtube_comment_set_parent_comment_uri:
 * @self: a #GDataYouTubeComment
 * @parent_comment_uri: a new parent comment URI, or %NULL
 *
 * Sets the #GDataYouTubeComment:parent-comment-uri property to @parent_comment_uri.
 *
 * Set @parent_comment_uri to %NULL to unset the #GDataYouTubeComment:parent-comment-uri property in the comment (i.e. make the comment a top-level
 * comment).
 *
 * See the <ulink type="http" url="http://code.google.com/apis/youtube/2.0/developers_guide_protocol_comments.html#Retrieve_comments">online
 * documentation</ulink> for more information.
 *
 * Since: 0.10.0
 */
void
gdata_youtube_comment_set_parent_comment_uri (GDataYouTubeComment *self, const gchar *parent_comment_uri)
{
	GDataLink *link_;

	g_return_if_fail (GDATA_IS_YOUTUBE_COMMENT (self));
	g_return_if_fail (parent_comment_uri == NULL || *parent_comment_uri != '\0');

	link_ = gdata_entry_look_up_link (GDATA_ENTRY (self), GDATA_LINK_PARENT_COMMENT_URI);

	if ((link_ == NULL && parent_comment_uri == NULL) ||
	    (link_ != NULL && parent_comment_uri != NULL && g_strcmp0 (gdata_link_get_uri (link_), parent_comment_uri) == 0)) {
		/* Nothing to do. */
		return;
	} else if (link_ == NULL && parent_comment_uri != NULL) {
		/* Add the new link. */
		link_ = gdata_link_new (parent_comment_uri, GDATA_LINK_PARENT_COMMENT_URI);
		gdata_entry_add_link (GDATA_ENTRY (self), link_);
		g_object_unref (link_);
	} else if (link_ != NULL && parent_comment_uri == NULL) {
		/* Remove the old link. */
		gdata_entry_remove_link (GDATA_ENTRY (self), link_);
	} else if (link_ != NULL && parent_comment_uri != NULL) {
		/* Update the existing link. */
		gdata_link_set_uri (link_, parent_comment_uri);
	}

	g_object_notify (G_OBJECT (self), "parent-comment-uri");
}
/**
 * gdata_access_handler_get_rules:
 * @self: a #GDataAccessHandler
 * @service: a #GDataService
 * @cancellable: optional #GCancellable object, or %NULL
 * @progress_callback: a #GDataQueryProgressCallback to call when a rule is loaded, or %NULL
 * @progress_user_data: data to pass to the @progress_callback function
 * @error: a #GError, or %NULL
 *
 * Retrieves a #GDataFeed containing all the access rules which apply to the given #GDataAccessHandler. Only the owner of a #GDataAccessHandler may
 * view its rule feed.
 *
 * If @cancellable is not %NULL, then the operation can be cancelled by triggering the @cancellable object from another thread.
 * If the operation was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
 *
 * A %GDATA_SERVICE_ERROR_WITH_QUERY will be returned if the server indicates there is a problem with the query.
 *
 * For each rule in the response feed, @progress_callback will be called in the main thread. If there was an error parsing the XML response,
 * a #GDataParserError will be returned.
 *
 * Return value: a #GDataFeed of access control rules, or %NULL; unref with g_object_unref()
 *
 * Since: 0.3.0
 **/
GDataFeed *
gdata_access_handler_get_rules (GDataAccessHandler *self, GDataService *service, GCancellable *cancellable, GDataQueryProgressCallback progress_callback,
				gpointer progress_user_data, GError **error)
{
	GDataServiceClass *klass;
	GDataFeed *feed;
	GDataLink *link;
	SoupMessage *message;
	guint status;

	/* TODO: async version */
	g_return_val_if_fail (GDATA_IS_ENTRY (self), NULL);
	g_return_val_if_fail (GDATA_IS_SERVICE (service), NULL);

	/* Get the ACL URI */
	link = gdata_entry_look_up_link (GDATA_ENTRY (self), "http://schemas.google.com/acl/2007#accessControlList");
	g_assert (link != NULL);
	message = soup_message_new (SOUP_METHOD_GET, link->href);

	/* Make sure subclasses set their headers */
	klass = GDATA_SERVICE_GET_CLASS (service);
	if (klass->append_query_headers != NULL)
		klass->append_query_headers (service, message);

	/* Send the message */
	status = _gdata_service_send_message (service, message, error);
	if (status == SOUP_STATUS_NONE) {
		g_object_unref (message);
		return NULL;
	}

	/* Check for cancellation */
	if (g_cancellable_set_error_if_cancelled (cancellable, error) == TRUE) {
		g_object_unref (message);
		return NULL;
	}

	if (status != 200) {
		/* Error */
		g_assert (klass->parse_error_response != NULL);
		klass->parse_error_response (service, GDATA_SERVICE_ERROR_WITH_QUERY, status, message->reason_phrase, message->response_body->data,
					     message->response_body->length, error);
		g_object_unref (message);
		return NULL;
	}

	g_assert (message->response_body->data != NULL);

	feed = _gdata_feed_new_from_xml (GDATA_TYPE_FEED, message->response_body->data, message->response_body->length, GDATA_TYPE_ACCESS_RULE,
					 progress_callback, progress_user_data, error);
	g_object_unref (message);

	return feed;
}
static gboolean
account_miner_job_process_entry (TrackerSparqlConnection *connection,
                                 GHashTable *previous_resources,
                                 const gchar *datasource_urn,
                                 GDataDocumentsService *service,
                                 GDataDocumentsEntry *doc_entry,
                                 GCancellable *cancellable,
                                 GError **error)
{
  GDataEntry *entry = GDATA_ENTRY (doc_entry);
  gchar *resource = NULL;
  gchar *date, *identifier;
  const gchar *class = NULL;
  const gchar *mimetype_override = NULL;
  gboolean mtime_changed, resource_exists;
  gint64 new_mtime;

  GList *authors, *l, *parents = NULL;
  GDataAuthor *author;
  GDataLink *parent;

  GDataLink *alternate;
  const gchar *alternate_uri;

  GList *categories;
  GDataCategory *category;
  gboolean starred = FALSE;

  GDataFeed *access_rules = NULL;

  if (GDATA_IS_DOCUMENTS_FOLDER (doc_entry))
    {
      GDataLink *link;

      link = gdata_entry_look_up_link (entry, GDATA_LINK_SELF);
      identifier = g_strdup_printf ("gd:collection:%s%s", PREFIX_DRIVE, gdata_link_get_uri (link));
    }
  else
    {
      const gchar *id;

      id = gdata_entry_get_id (entry);
      identifier = g_strdup_printf ("%s%s", PREFIX_DRIVE, id);
    }

  /* remove from the list of the previous resources, if any */
  if (previous_resources != NULL)
    g_hash_table_remove (previous_resources, identifier);

  if (GDATA_IS_DOCUMENTS_PRESENTATION (doc_entry))
    class = "nfo:Presentation";
  else if (GDATA_IS_DOCUMENTS_SPREADSHEET (doc_entry))
static GDataFeed *
gdata_access_handler_real_get_rules (GDataAccessHandler *self,
                                     GDataService *service,
                                     GCancellable *cancellable,
                                     GDataQueryProgressCallback progress_callback,
                                     gpointer progress_user_data,
                                     GError **error)
{
	GDataAccessHandlerIface *iface;
	GDataAuthorizationDomain *domain = NULL;
	GDataFeed *feed;
	GDataLink *_link;
	SoupMessage *message;
	SoupMessageHeaders *headers;
	const gchar *content_type;

	_link = gdata_entry_look_up_link (GDATA_ENTRY (self), GDATA_LINK_ACCESS_CONTROL_LIST);
	g_assert (_link != NULL);

	iface = GDATA_ACCESS_HANDLER_GET_IFACE (self);
	if (iface->get_authorization_domain != NULL) {
		domain = iface->get_authorization_domain (self);
	}

	message = _gdata_service_query (service, domain, gdata_link_get_uri (_link), NULL, cancellable, error);
	if (message == NULL) {
		return NULL;
	}

	g_assert (message->response_body->data != NULL);

	headers = message->response_headers;
	content_type = soup_message_headers_get_content_type (headers, NULL);

	if (g_strcmp0 (content_type, "application/json") == 0) {
		/* Definitely JSON. */
		g_debug("JSON content type detected.");
		feed = _gdata_feed_new_from_json (GDATA_TYPE_FEED, message->response_body->data, message->response_body->length, GDATA_TYPE_ACCESS_RULE,
		                                  progress_callback, progress_user_data, error);
	} else {
		/* Potentially XML. Don't bother checking the Content-Type, since the parser
		 * will fail gracefully if the response body is not valid XML. */
		g_debug("XML content type detected.");
		feed = _gdata_feed_new_from_xml (GDATA_TYPE_FEED, message->response_body->data, message->response_body->length, GDATA_TYPE_ACCESS_RULE,
		                                 progress_callback, progress_user_data, error);
	}

	g_object_unref (message);

	return feed;
}
/**
 * gdata_youtube_comment_get_parent_comment_uri:
 * @self: a #GDataYouTubeComment
 *
 * Gets the #GDataYouTubeComment:parent-comment-uri property.
 *
 * Return value: the parent comment URI, or %NULL
 *
 * Since: 0.10.0
 */
const gchar *
gdata_youtube_comment_get_parent_comment_uri (GDataYouTubeComment *self)
{
	GDataLink *link_;

	g_return_val_if_fail (GDATA_IS_YOUTUBE_COMMENT (self), NULL);

	link_ = gdata_entry_look_up_link (GDATA_ENTRY (self), GDATA_LINK_PARENT_COMMENT_URI);
	if (link_ == NULL) {
		return NULL;
	}

	return gdata_link_get_uri (link_);
}
static gboolean
account_miner_job_process_entry (GomAccountMinerJob *job,
                                 GDataDocumentsEntry *doc_entry,
                                 GError **error)
{
  GDataEntry *entry = GDATA_ENTRY (doc_entry);
  gchar *resource = NULL;
  gchar *date, *identifier;
  const gchar *class = NULL;
  const gchar *mimetype_override = NULL;
  gboolean mtime_changed, resource_exists;
  gint64 new_mtime;

  GList *authors, *l, *parents = NULL;
  GDataAuthor *author;
  GDataLink *parent;

  GDataLink *alternate;
  const gchar *alternate_uri;

  GList *categories;
  GDataCategory *category;
  gboolean starred = FALSE;

  GDataFeed *access_rules = NULL;

  if (GDATA_IS_DOCUMENTS_FOLDER (doc_entry))
    {
      GDataLink *link;

      link = gdata_entry_look_up_link (entry, GDATA_LINK_SELF);
      identifier = g_strdup_printf ("gd:collection:%s", gdata_link_get_uri (link));
    }
  else
    identifier = g_strdup (gdata_entry_get_id (entry));

  /* remove from the list of the previous resources */
  g_hash_table_remove (job->previous_resources, identifier);

  if (GDATA_IS_DOCUMENTS_PRESENTATION (doc_entry))
    class = "nfo:Presentation";
  else if (GDATA_IS_DOCUMENTS_SPREADSHEET (doc_entry))
static void
resolve_t_param (TotemYouTubePlugin *self, GDataEntry *entry, GtkTreeIter *iter, guint tree_view, GCancellable *cancellable)
{
	GDataLink *page_link;
	TParamData *data;

	/* We have to get the t parameter from the actual HTML video page, since Google changed how their URIs work */
	page_link = gdata_entry_look_up_link (entry, GDATA_LINK_ALTERNATE);
	g_assert (page_link != NULL);

	data = g_slice_new (TParamData);
	data->plugin = g_object_ref (self);
	data->entry = g_object_ref (entry);
	data->path = gtk_tree_model_get_path (GTK_TREE_MODEL (self->list_store[tree_view]), iter);
	data->tree_view = tree_view;
	data->cancellable = g_object_ref (cancellable);

	data->message = soup_message_new (SOUP_METHOD_GET, gdata_link_get_uri (page_link));
	data->cancelled_id = g_cancellable_connect (cancellable, (GCallback) resolve_t_param_cancelled_cb, data, NULL);

	/* Send the message. Consumes a reference to data->message after resolve_t_param_cb() finishes */
	soup_session_queue_message (self->session, data->message, (SoupSessionCallback) resolve_t_param_cb, data);
}
void
open_in_web_browser_activate_cb (GtkAction *action, TotemYouTubePlugin *self)
{
	GtkTreeSelection *selection;
	GtkTreeModel *model;
	GList *paths, *path;

	selection = gtk_tree_view_get_selection (self->tree_view[self->current_tree_view]);
	paths = gtk_tree_selection_get_selected_rows (selection, &model);

	for (path = paths; path != NULL; path = path->next) {
		GtkTreeIter iter;
		GDataYouTubeVideo *video;
		GDataLink *link;
		GError *error = NULL;

		if (gtk_tree_model_get_iter (model, &iter, (GtkTreePath*) (path->data)) == FALSE)
			continue;

		/* Get the HTML page for the video; its <link rel="alternate" ... /> */
		gtk_tree_model_get (model, &iter, 3, &video, -1);
		link = gdata_entry_look_up_link (GDATA_ENTRY (video), GDATA_LINK_ALTERNATE);
		g_object_unref (video);

		/* Display the page */
		if (gtk_show_uri (gtk_widget_get_screen (GTK_WIDGET (self->bvw)), gdata_link_get_uri (link), GDK_CURRENT_TIME, &error) == FALSE) {
			GtkWindow *window = totem_get_main_window (self->totem);
			totem_interface_error (_("Error Opening Video in Web Browser"), error->message, window);
			g_object_unref (window);
			g_error_free (error);
		}
	}

	g_list_foreach (paths, (GFunc) gtk_tree_path_free, NULL);
	g_list_free (paths);
}
/**
 * gdata_access_handler_insert_rule:
 * @self: a #GDataAccessHandler
 * @service: a #GDataService
 * @rule: the #GDataAccessRule to insert
 * @cancellable: optional #GCancellable object, or %NULL
 * @error: a #GError, or %NULL
 *
 * Inserts @rule in the access control list of the #GDataAccessHandler.
 *
 * The service will return an updated version of the rule, which is the return value of this function on success.
 *
 * If @cancellable is not %NULL, then the operation can be cancelled by triggering the @cancellable object from another thread.
 * If the operation was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
 *
 * If the rule is marked as already having been inserted a %GDATA_SERVICE_ERROR_ENTRY_ALREADY_INSERTED error will be returned immediately
 * (there will be no network requests).
 *
 * If there is an error inserting the rule, a %GDATA_SERVICE_ERROR_WITH_INSERTION error will be returned.
 *
 * Return value: an updated #GDataAccessRule, or %NULL
 *
 * Since: 0.3.0
 **/
GDataAccessRule *
gdata_access_handler_insert_rule (GDataAccessHandler *self, GDataService *service, GDataAccessRule *rule, GCancellable *cancellable, GError **error)
{
	GDataServiceClass *klass;
	GDataAccessRule *updated_rule;
	GDataLink *link;
	SoupMessage *message;
	gchar *upload_data;
	guint status;

	g_return_val_if_fail (GDATA_IS_ENTRY (self), NULL);
	g_return_val_if_fail (GDATA_IS_SERVICE (service), NULL);
	g_return_val_if_fail (GDATA_IS_ACCESS_RULE (rule), NULL);

	if (gdata_entry_is_inserted (GDATA_ENTRY (rule)) == TRUE) {
		g_set_error_literal (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_ENTRY_ALREADY_INSERTED,
				     _("The rule has already been inserted."));
		return NULL;
	}

	/* Get the ACL URI */
	link = gdata_entry_look_up_link (GDATA_ENTRY (self), "http://schemas.google.com/acl/2007#accessControlList");
	g_assert (link != NULL);
	message = soup_message_new (SOUP_METHOD_POST, link->href);

	/* Make sure subclasses set their headers */
	klass = GDATA_SERVICE_GET_CLASS (service);
	if (klass->append_query_headers != NULL)
		klass->append_query_headers (service, message);

	/* Append the data */
	upload_data = gdata_entry_get_xml (GDATA_ENTRY (rule));
	soup_message_set_request (message, "application/atom+xml", SOUP_MEMORY_TAKE, upload_data, strlen (upload_data));

	/* Send the message */
	status = _gdata_service_send_message (service, message, error);
	if (status == SOUP_STATUS_NONE) {
		g_object_unref (message);
		return NULL;
	}

	/* Check for cancellation */
	if (g_cancellable_set_error_if_cancelled (cancellable, error) == TRUE) {
		g_object_unref (message);
		return NULL;
	}

	if (status != 201) {
		/* Error */
		g_assert (klass->parse_error_response != NULL);
		klass->parse_error_response (service, GDATA_SERVICE_ERROR_WITH_INSERTION, status, message->reason_phrase, message->response_body->data,
					     message->response_body->length, error);
		g_object_unref (message);
		return NULL;
	}

	/* Build the updated entry */
	g_assert (message->response_body->data != NULL);

	/* Parse the XML; create and return a new GDataEntry of the same type as @entry */
	updated_rule = GDATA_ACCESS_RULE (_gdata_entry_new_from_xml (G_OBJECT_TYPE (rule), message->response_body->data,
					  message->response_body->length, error));
	g_object_unref (message);

	return updated_rule;
}