/*
 * Queue @id and @vcard to be sent as a change notification.
 */
static void
notify_add (EDataBookView *view, const gchar *id, const gchar *vcard)
{
    EDataBookViewPrivate *priv = view->priv;
    gchar *utf8_vcard;

    send_pending_changes (view);
    send_pending_removes (view);

    if (priv->adds->len == THRESHOLD_ITEMS) {
        send_pending_adds (view);
    }

    utf8_vcard = e_util_utf8_make_valid (vcard);
    g_array_append_val (priv->adds, utf8_vcard);
    g_hash_table_insert (priv->ids, e_util_utf8_make_valid (id),
                         GUINT_TO_POINTER (1));

    ensure_pending_flush_timeout (view);
}
Esempio n. 2
0
static void
add_to_array_cb (gpointer key,
                 gpointer value,
                 gpointer ptr_array)
{
	if (key && value && ptr_array) {
		gchar *str = g_strconcat (key, ":", value, NULL);

		g_ptr_array_add (ptr_array, e_util_utf8_make_valid (str));

		g_free (str);
	}
}
static gboolean
id_is_in_view (EDataBookView *book_view, const gchar *id)
{
    gchar *valid_id;
    gboolean res;

    g_return_val_if_fail (book_view != NULL, FALSE);
    g_return_val_if_fail (id != NULL, FALSE);

    valid_id = e_util_utf8_make_valid (id);
    res = g_hash_table_lookup (book_view->priv->ids, valid_id) != NULL;
    g_free (valid_id);

    return res;
}
/*
 * Queue @vcard to be sent as a change notification.
 */
static void
notify_change (EDataBookView *view, const gchar *vcard)
{
    EDataBookViewPrivate *priv = view->priv;
    gchar *utf8_vcard;

    send_pending_adds (view);
    send_pending_removes (view);

    if (priv->changes->len == THRESHOLD_ITEMS) {
        send_pending_changes (view);
    }

    utf8_vcard = e_util_utf8_make_valid (vcard);
    g_array_append_val (priv->changes, utf8_vcard);

    ensure_pending_flush_timeout (view);
}
/**
 * e_data_book_view_new:
 * @book: The #EDataBook to search
 * @card_query: The query as a string
 * @card_sexp: The query as an #EBookBackendSExp
 * @max_results: The maximum number of results to return
 *
 * Create a new #EDataBookView for the given #EBook, filtering on #card_sexp,
 * and place it on DBus at the object path #path.
 */
EDataBookView *
e_data_book_view_new (EDataBook *book, const gchar *card_query, EBookBackendSExp *card_sexp, gint max_results)
{
    EDataBookView *view;
    EDataBookViewPrivate *priv;

    view = g_object_new (E_TYPE_DATA_BOOK_VIEW, NULL);
    priv = view->priv;

    priv->book = book;
    /* Attach a weak reference to the book, so if it dies the book view is destroyed too */
    g_object_weak_ref (G_OBJECT (priv->book), book_destroyed_cb, view);
    priv->backend = g_object_ref (e_data_book_get_backend (book));
    priv->card_query = e_util_utf8_make_valid (card_query);
    priv->card_sexp = card_sexp;
    priv->max_results = max_results;

    return view;
}
/*
 * Queue @id to be sent as a change notification.
 */
static void
notify_remove (EDataBookView *view, const gchar *id)
{
    EDataBookViewPrivate *priv = view->priv;
    gchar *valid_id;

    send_pending_adds (view);
    send_pending_changes (view);

    if (priv->removes->len == THRESHOLD_ITEMS) {
        send_pending_removes (view);
    }

    valid_id = e_util_utf8_make_valid (id);
    g_array_append_val (priv->removes, valid_id);
    g_hash_table_remove (priv->ids, valid_id);

    ensure_pending_flush_timeout (view);
}
/**
 * e_data_cal_view_notify_objects_added:
 * @query: A query object.
 * @objects: List of objects that have been added.
 *
 * Notifies all query listeners of the addition of a list of objects.
 */
void
e_data_cal_view_notify_objects_added (EDataCalView *view, const GList *objects)
{
	EDataCalViewPrivate *priv;
	const GList *l;

	g_return_if_fail (view && E_IS_DATA_CAL_VIEW (view));
	priv = view->priv;

	if (objects == NULL)
		return;

	g_mutex_lock (priv->pending_mutex);

	for (l = objects; l; l = l->next) {
		notify_add (view, e_util_utf8_make_valid (l->data));
	}

	g_mutex_unlock (priv->pending_mutex);
}
/**
 * e_data_cal_view_notify_objects_modified:
 * @query: A query object.
 * @objects: List of modified objects.
 *
 * Notifies all query listeners of the modification of a list of objects.
 */
void
e_data_cal_view_notify_objects_modified (EDataCalView *view, const GList *objects)
{
	EDataCalViewPrivate *priv;
	const GList *l;

	g_return_if_fail (view && E_IS_DATA_CAL_VIEW (view));
	priv = view->priv;

	if (objects == NULL)
		return;

	g_mutex_lock (priv->pending_mutex);

	for (l = objects; l; l = l->next) {
		/* TODO: send add/remove/change as relevant, based on ->ids */
		notify_change (view, e_util_utf8_make_valid (l->data));
	}

	g_mutex_unlock (priv->pending_mutex);
}
static void
notify_remove (EDataCalView *view, ECalComponentId *id)
{
	EDataCalViewPrivate *priv = view->priv;
	gchar *uid;

	send_pending_adds (view);
	send_pending_changes (view);

	if (priv->removes->len == THRESHOLD_ITEMS) {
		send_pending_removes (view);
	}

	/* TODO: store ECalComponentId instead of just uid*/
	uid = e_util_utf8_make_valid (id->uid);
	g_array_append_val (priv->removes, uid);

	g_hash_table_remove (priv->ids, id);

	ensure_pending_flush_timeout (view);
}
static gboolean
emfe_text_html_format (EMailFormatterExtension *extension,
                       EMailFormatter *formatter,
                       EMailFormatterContext *context,
                       EMailPart *part,
                       GOutputStream *stream,
                       GCancellable *cancellable)
{
	if (g_cancellable_is_cancelled (cancellable))
		return FALSE;

	if (context->mode == E_MAIL_FORMATTER_MODE_RAW) {
		e_mail_formatter_format_text (
			formatter, part, stream, cancellable);

	} else if (context->mode == E_MAIL_FORMATTER_MODE_PRINTING) {
		GOutputStream *decoded_stream;
		GString *string;
		gchar *pos;
		GList *tags, *iter;
		gboolean valid;
		gchar *tag;
		const gchar *document_end;
		gpointer data;
		gsize length;
		gint i;

		decoded_stream = g_memory_output_stream_new_resizable ();

		/* FORMATTER FIXME: See above */
		e_mail_formatter_format_text (
			formatter, part, decoded_stream, cancellable);

		data = g_memory_output_stream_get_data (
			G_MEMORY_OUTPUT_STREAM (decoded_stream));
		length = g_memory_output_stream_get_data_size (
			G_MEMORY_OUTPUT_STREAM (decoded_stream));

		string = g_string_new_len ((gchar *) data, length);

		g_object_unref (decoded_stream);

		if (!g_utf8_validate (string->str, -1, NULL)) {
			gchar *valid_utf8;

			valid_utf8 = e_util_utf8_make_valid (string->str);
			g_string_free (string, TRUE);
			string = g_string_new (valid_utf8);
			g_free (valid_utf8);
		}

		tags = NULL;
		pos = string->str;
		valid = FALSE;

		do {
			gchar *tmp;
			gchar *closing;
			gchar *opening;

			tmp = g_utf8_find_next_char (pos, NULL);
			pos = g_utf8_strchr (tmp, -1, '<');
			if (!pos)
				break;

			opening = pos;
			closing = g_utf8_strchr (pos, -1, '>');

			/* Find where the actual tag name begins */
			while (tag = g_utf8_find_next_char (pos, NULL), tag != NULL) {
				gunichar c = g_utf8_get_char (tag);
				if (!g_unichar_isspace (c))
					break;
			}

			if (g_ascii_strncasecmp (tag, "style", 5) == 0) {
				tags = g_list_append (
					tags,
					get_tag (string->str, "style", opening, closing));
			} else if (g_ascii_strncasecmp (tag, "script", 6) == 0) {
				tags = g_list_append (
					tags,
					get_tag (string->str, "script", opening, closing));
			} else if (g_ascii_strncasecmp (tag, "link", 4) == 0) {
				tags = g_list_append (
					tags,
					get_tag (string->str, "link", opening, closing));
			} else if (g_ascii_strncasecmp (tag, "body", 4) == 0) {
				valid = TRUE;
				break;
			}

		} while (pos);

		/* Something's wrong, let's write the entire HTML and hope
		 * that WebKit can handle it */
		if (!valid) {
			EMailFormatterContext c = {
				.part_list = context->part_list,
				.flags = context->flags,
				.mode = E_MAIL_FORMATTER_MODE_RAW,
			};

			emfe_text_html_format (
				extension, formatter, &c,
				part, stream, cancellable);
			return FALSE;
		}

		/*	       include the "body" as well -----v */
		g_string_erase (string, 0, tag - string->str + 4);
		g_string_prepend (string, "<div ");

		for (iter = tags; iter; iter = iter->next) {
			if (iter->data)
				g_string_prepend (string, iter->data);
		}

		g_list_free_full (tags, g_free);

		document_end = NULL;
		/* We can probably use ASCII functions here */
		if (g_strrstr (string->str, "</body>")) {
			document_end = ">ydob/<";
		}

		if (g_strrstr (string->str, "</html>")) {
			if (document_end) {
				document_end = ">lmth/<>ydob/<";
			} else {
				document_end = ">lmth/<";
			}
		}

		if (document_end) {
			length = strlen (document_end);
			tag = string->str + string->len - 1;
			i = 0;
			valid = FALSE;
			while (i < length - 1) {
				gunichar c;

				c = g_utf8_get_char (tag);
				if (g_unichar_isspace (c)) {
					tag = g_utf8_find_prev_char (string->str, tag);
					continue;
				}

				c = g_unichar_tolower (c);

				if (c == document_end[i]) {
					tag = g_utf8_find_prev_char (string->str, tag);
					i++;
					valid = TRUE;
					continue;
				}

				tag = g_utf8_find_prev_char (string->str, tag);
				valid = FALSE;
			}
		} else {
			/* do not cut, if there is no end tag */
			valid = FALSE;
		}

		if (valid)
			g_string_truncate (string, tag - string->str);

		g_output_stream_write_all (
			stream, string->str, string->len,
			NULL, cancellable, NULL);

		g_string_free (string, TRUE);
	} else {