+ if (refs_str == NULL)
+ return;
+
+ refs = g_mime_references_decode (refs_str);
+
+ for (r = refs; r; r = r->next) {
+ message_id = g_mime_references_get_message_id (r);
+ g_ptr_array_add (array, g_strdup (message_id));
+ }
+
+ g_mime_references_free (refs);
+}
+
+/* Given a string representing the body of a message, generate terms
+ * for it, (skipping quoted portions and signatures). */
+static void
+gen_terms_body_str (Xapian::TermGenerator term_gen,
+ char *body)
+{
+ char *line, *line_end, *next_line;
+
+ if (body == NULL)
+ return;
+
+ next_line = body;
+
+ while (1) {
+ line = next_line;
+ if (*line == '\0')
+ break;
+
+ next_line = strchr (line, '\n');
+ if (next_line == NULL) {
+ next_line = line + strlen (line);
+ }
+ line_end = next_line - 1;
+
+ /* Get to the next non-blank line. */
+ while (*next_line == '\n')
+ next_line++;
+
+ /* Skip blank lines. */
+ if (line_end < line)
+ continue;
+
+ /* Skip lines that are quotes. */
+ if (*line == '>')
+ continue;
+
+ /* Also skip lines introducing a quote on the next line. */
+ if (*line_end == ':' && *next_line == '>')
+ continue;
+
+ /* Finally, bail as soon as we see a signature. */
+ /* XXX: Should only do this if "near" the end of the message. */
+ if (strncmp (line, "-- ", 3) == 0 ||
+ strncmp (line, "----------", 10) == 0 ||
+ strncmp (line, "__________", 10) == 0)
+ break;
+
+ *(line_end + 1) = '\0';
+ gen_terms (term_gen, "body", line);
+ }
+}
+
+
+/* Callback to generate terms for each mime part of a message. */
+static void
+gen_terms_part (Xapian::TermGenerator term_gen,
+ GMimeObject *part)
+{
+ GMimeStream *stream;
+ GMimeDataWrapper *wrapper;
+ GByteArray *byte_array;
+ GMimeContentDisposition *disposition;
+ char *body;
+
+ if (GMIME_IS_MULTIPART (part)) {
+ GMimeMultipart *multipart = GMIME_MULTIPART (part);
+ int i;
+
+ for (i = 0; i < g_mime_multipart_get_count (multipart); i++) {
+ if (GMIME_IS_MULTIPART_SIGNED (multipart)) {
+ /* Don't index the signature. */
+ if (i == 1)
+ continue;
+ if (i > 1)
+ fprintf (stderr, "Warning: Unexpected extra parts of mutlipart/signed. Indexing anyway.\n");
+ }
+ gen_terms_part (term_gen,
+ g_mime_multipart_get_part (multipart, i));
+ }
+ return;
+ }
+
+ if (GMIME_IS_MESSAGE_PART (part)) {
+ GMimeMessage *message;
+
+ message = g_mime_message_part_get_message (GMIME_MESSAGE_PART (part));
+
+ gen_terms_part (term_gen, g_mime_message_get_mime_part (message));
+
+ return;
+ }
+
+ if (! (GMIME_IS_PART (part))) {
+ fprintf (stderr, "Warning: Not indexing unknown mime part: %s.\n",
+ g_type_name (G_OBJECT_TYPE (part)));
+ return;
+ }
+
+ disposition = g_mime_object_get_content_disposition (part);
+ if (disposition &&
+ strcmp (disposition->disposition, GMIME_DISPOSITION_ATTACHMENT) == 0)
+ {
+ const char *filename = g_mime_part_get_filename (GMIME_PART (part));
+ const char *extension;
+
+ add_term (term_gen.get_document (), "label", "attachment");
+ gen_terms (term_gen, "attachment", filename);
+
+ if (filename) {
+ extension = strchr (filename, '.');
+ if (extension) {
+ add_term (term_gen.get_document (), "attachment_extension",
+ extension + 1);
+ }
+ }
+
+ return;
+ }
+
+ byte_array = g_byte_array_new ();
+
+ stream = g_mime_stream_mem_new_with_byte_array (byte_array);
+ g_mime_stream_mem_set_owner (GMIME_STREAM_MEM (stream), FALSE);
+ wrapper = g_mime_part_get_content_object (GMIME_PART (part));
+ if (wrapper)
+ g_mime_data_wrapper_write_to_stream (wrapper, stream);
+
+ g_object_unref (stream);
+
+ g_byte_array_append (byte_array, (guint8 *) "\0", 1);
+ body = (char *) g_byte_array_free (byte_array, FALSE);
+
+ gen_terms_body_str (term_gen, body);
+
+ free (body);
+}
+
+static void
+index_file (Xapian::WritableDatabase db,
+ Xapian::TermGenerator term_gen,
+ const char *filename)