modest-ui-actions.h\
modest-widget-memory-priv.h \
modest-widget-memory.c\
- modest-widget-memory.h
+ modest-widget-memory.h\
+ modest-search.c\
+ modest-search.h\
+ modest-mime-part-search-stream.c\
+ modest-mime-part-search-stream.h
modest_CFLAGS = $(MAEMO_LAUNCHER_CFLAGS)
modest_LDFLAGS = $(MAEMO_LAUNCHER_LDFLAGS)
--- /dev/null
+#define _GNU_SOURCE
+
+#include <glib.h>
+#include <string.h>
+
+#include "modest-mime-part-search-stream.h"
+
+static GObjectClass *parent_class = NULL;
+
+static gssize
+modest_mime_part_search_stream_read (TnyStream *self, char *buffer, gsize n)
+{
+ ModestMimePartSearchStream *me = (ModestMimePartSearchStream *) self;
+
+ if (strcasestr (buffer, me->search_for) != NULL) {
+ me->found = TRUE;
+ return -1;
+ }
+
+ return (gssize) n;
+}
+
+static gssize
+modest_mime_part_search_stream_write (TnyStream *self, const char *buffer, gsize n)
+{
+ ModestMimePartSearchStream *me = (ModestMimePartSearchStream *) self;
+
+ if (strcasestr (buffer, me->search_for) != NULL) {
+ me->found = TRUE;
+ return -1;
+ }
+
+ return (gssize) n;
+}
+
+static gint
+modest_mime_part_search_stream_flush (TnyStream *self)
+{
+ return 0;
+}
+
+static gint
+modest_mime_part_search_stream_close (TnyStream *self)
+{
+ return 0;
+}
+
+static gboolean
+modest_mime_part_search_stream_is_eos (TnyStream *self)
+{
+ return TRUE;
+}
+
+static gint
+modest_mime_part_search_stream_reset (TnyStream *self)
+{
+ return 0;
+}
+
+static gssize
+modest_mime_part_search_stream_write_to_stream (TnyStream *self, TnyStream *output)
+{
+ char tmp_buf[4096];
+ ssize_t total = 0;
+ ssize_t nb_read;
+ ssize_t nb_written;
+
+ g_assert (TNY_IS_STREAM (output));
+
+ while (G_LIKELY (!tny_stream_is_eos (self)))
+ {
+ nb_read = tny_stream_read (self, tmp_buf, sizeof (tmp_buf));
+ if (G_UNLIKELY (nb_read < 0))
+ return -1;
+ else if (G_LIKELY (nb_read > 0)) {
+ nb_written = 0;
+
+ while (G_LIKELY (nb_written < nb_read))
+ {
+ ssize_t len = tny_stream_write (output, tmp_buf + nb_written,
+ nb_read - nb_written);
+ if (G_UNLIKELY (len < 0))
+ return -1;
+ nb_written += len;
+ }
+ total += nb_written;
+ }
+ }
+ return total;
+}
+
+
+TnyStream*
+modest_mime_part_search_stream_new (const char *search_for)
+{
+ ModestMimePartSearchStream *me = g_object_new (MODEST_TYPE_MIME_PART_SEARCH_STREAM, NULL);
+
+ me->search_for = g_strdup (search_for);
+
+ return TNY_STREAM (me);
+}
+
+static void
+modest_mime_part_search_stream_finalize (GObject *object)
+{
+ ModestMimePartSearchStream *me = g_object_new (MODEST_TYPE_MIME_PART_SEARCH_STREAM, NULL);
+
+ g_free (me->search_for);
+
+ parent_class->finalize (object);
+}
+
+static void
+modest_mime_part_search_stream_instance_init (GTypeInstance *instance, gpointer g_class)
+{
+ ModestMimePartSearchStream *me = (ModestMimePartSearchStream *) instance;
+
+ me->found = FALSE;
+}
+
+static void
+tny_stream_init (TnyStreamIface *klass)
+{
+ klass->read_func = modest_mime_part_search_stream_read;
+ klass->write_func = modest_mime_part_search_stream_write;
+ klass->flush_func = modest_mime_part_search_stream_flush;
+ klass->close_func = modest_mime_part_search_stream_close;
+ klass->is_eos_func = modest_mime_part_search_stream_is_eos;
+ klass->reset_func = modest_mime_part_search_stream_reset;
+ klass->write_to_stream_func = modest_mime_part_search_stream_write_to_stream;
+}
+
+static void
+modest_mime_part_search_stream_class_init (ModestMimePartSearchStreamClass *klass)
+{
+ GObjectClass *object_class;
+
+ parent_class = g_type_class_peek_parent (klass);
+ object_class = (GObjectClass*) klass;
+ object_class->finalize = modest_mime_part_search_stream_finalize;
+}
+
+GType
+modest_mime_part_search_stream_get_type (void)
+{
+ static GType type = 0;
+ if (G_UNLIKELY(type == 0))
+ {
+ static const GTypeInfo info =
+ {
+ sizeof (ModestMimePartSearchStreamClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) modest_mime_part_search_stream_class_init, /* class_init */
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (ModestMimePartSearchStream),
+ 0, /* n_preallocs */
+ modest_mime_part_search_stream_instance_init, /* instance_init */
+ NULL
+ };
+
+
+ static const GInterfaceInfo tny_stream_info =
+ {
+ (GInterfaceInitFunc) tny_stream_init, /* interface_init */
+ NULL, /* interface_finalize */
+ NULL /* interface_data */
+ };
+
+ type = g_type_register_static (G_TYPE_OBJECT,
+ "ModestMimePartSearchStream",
+ &info, 0);
+
+ g_type_add_interface_static (type, TNY_TYPE_STREAM,
+ &tny_stream_info);
+
+ }
+ return type;
+}
--- /dev/null
+#ifndef MODEST_MIME_PART_SEARCH_STREAM_H
+#define MODEST_MIME_PART_SEARCH_STREAM_H
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <tny-stream.h>
+
+G_BEGIN_DECLS
+
+#define MODEST_TYPE_MIME_PART_SEARCH_STREAM (modest_mime_part_search_stream_get_type ())
+#define MODEST_MIME_PART_SEARCH_STREAM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MODEST_TYPE_MIME_PART_SEARCH_STREAM, ModestMimePartSearchStream))
+#define MODEST_MIME_PART_SEARCH_STREAM_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST ((vtable), MODEST_TYPE_MIME_PART_SEARCH_STREAM, ModestMimePartSearchStreamClass))
+#define MODEST_IS_MIME_PART_SEARCH_STREAM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MODEST_TYPE_MIME_PART_SEARCH_STREAM))
+#define MODEST_IS_MIME_PART_SEARCH_STREAM_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), MODEST_TYPE_MIME_PART_SEARCH_STREAM))
+#define MODEST_MIME_PART_SEARCH_STREAM_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), MODEST_TYPE_MIME_PART_SEARCH_STREAM, ModestMimePartSearchStreamClass))
+
+typedef struct _ModestMimePartSearchStream ModestMimePartSearchStream;
+typedef struct _ModestMimePartSearchStreamClass ModestMimePartSearchStreamClass;
+
+struct _ModestMimePartSearchStream
+{
+ GObject parent;
+ gboolean found;
+ gchar *search_for;
+};
+
+struct _ModestMimePartSearchStreamClass
+{
+ GObjectClass parent;
+};
+
+GType modest_mime_part_search_stream_get_type (void);
+TnyStream* modest_mime_part_search_stream_new (const char *search_for);
+
+G_END_DECLS
+
+#endif
+
--- /dev/null
+#define _GNU_SOURCE
+
+#include <string.h>
+
+#include <tny-shared.h>
+#include <tny-folder.h>
+#include <tny-list.h>
+#include <tny-iterator.h>
+#include <tny-simple-list.h>
+
+#include "modest-search.h"
+#include "modest-mime-part-search-stream.h"
+
+static GList*
+add_header (GList *list, TnyHeader *header, TnyFolder *folder)
+{
+ gchar *furl = tny_folder_get_url_string (folder);
+ const gchar *uid = tny_header_get_uid (header);
+ gchar *str = g_strdup_printf ("%s/%s", furl, uid);
+ g_free (furl);
+ return g_list_prepend (list, str);
+}
+
+
+
+/**
+ * modest_search:
+ * @folder: a #TnyFolder instance
+ * @search: a #ModestSearch query
+ *
+ * This operation will search @folder for headers that match the query @search.
+ * It will return a doubly linked list with URIs that point to the message.
+ **/
+GList *
+modest_search (TnyFolder *folder, ModestSearch *search)
+{
+ GList *retval = NULL;
+ TnyIterator *iter;
+ TnyList *list = tny_simple_list_new ();
+ tny_folder_get_headers (folder, list, FALSE, NULL);
+
+ iter = tny_list_create_iterator (list);
+ while (!tny_iterator_is_done (iter))
+ {
+ TnyHeader *cur = (TnyHeader *) tny_iterator_get_current (iter);
+ time_t t = tny_header_get_date_sent (cur);
+
+ if (search->flags & MODEST_SEARCH_BEFORE)
+ if (!(t <= search->before))
+ goto go_next;
+
+ if (search->flags & MODEST_SEARCH_AFTER)
+ if (!(t >= search->after))
+ goto go_next;
+
+
+ if (search->flags & MODEST_SEARCH_SIZE)
+ if (tny_header_get_message_size (cur) < search->minsize)
+ goto go_next;
+
+ if (search->flags & MODEST_SEARCH_SUBJECT) {
+ if (strcasestr (tny_header_get_subject (cur), search->subject))
+ retval = add_header (retval, cur, folder);
+ } else if (search->flags & MODEST_SEARCH_SENDER) {
+ if (strcasestr (tny_header_get_from (cur), search->subject))
+ retval = add_header (retval, cur, folder);
+ } else if (search->flags & MODEST_SEARCH_RECIPIENT) {
+ if (strcasestr (tny_header_get_to (cur), search->subject))
+ retval = add_header (retval, cur, folder);
+ } else if (search->flags & MODEST_SEARCH_BODY)
+ {
+ TnyHeaderFlags flags = tny_header_get_flags (cur);
+
+ if (flags & TNY_HEADER_FLAG_CACHED)
+ {
+ GError *err = NULL;
+ TnyMsg *msg = tny_folder_get_msg (folder, cur, &err);
+
+ if (err == NULL)
+ {
+ TnyIterator *piter;
+ TnyList *parts = tny_simple_list_new ();
+ tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
+ piter = tny_list_create_iterator (parts);
+
+ while (!tny_iterator_is_done (piter))
+ {
+ TnyStream *stream;
+ TnyMimePart *pcur = (TnyMimePart *) tny_iterator_get_current (piter);
+
+ stream = modest_mime_part_search_stream_new (search->body);
+
+ tny_mime_part_decode_to_stream (pcur, stream);
+
+ if (((ModestMimePartSearchStream *) stream)->found)
+ retval = add_header (retval, cur, folder);
+
+ g_object_unref (stream);
+ g_object_unref (pcur);
+ tny_iterator_next (piter);
+ }
+ g_object_unref (piter);
+ g_object_unref (parts);
+ } else
+ g_error_free (err);
+
+ if (msg)
+ g_object_unref (msg);
+ }
+ }
+
+
+
+go_next:
+ g_object_unref (cur);
+ tny_iterator_next (iter);
+ }
+ g_object_unref (iter);
+ g_object_unref (list);
+
+ return retval;
+}
+
--- /dev/null
+#ifndef MODEST_SEARCH_H
+#define MODEST_SEARCH_H
+
+typedef enum {
+ MODEST_SEARCH_SUBJECT = 0<<1,
+ MODEST_SEARCH_SENDER = 0<<2,
+ MODEST_SEARCH_RECIPIENT = 0<<3,
+ MODEST_SEARCH_SIZE = 0<<4,
+ MODEST_SEARCH_BEFORE = 0<<5,
+ MODEST_SEARCH_AFTER = 0<<6,
+ MODEST_SEARCH_BODY = 0<<7
+} ModestSearchFlags;
+
+typedef struct {
+ gchar *subject, *from, *recipient, *body;
+ time_t before, after;
+ guint minsize;
+ ModestSearchFlags flags;
+} ModestSearch;
+
+GList * modest_search (TnyFolder *folder, ModestSearch *search);
+
+#endif
+