+static const char *
+skip_re_in_subject (const char *subject)
+{
+ const char *s = subject;
+
+ while (*s) {
+ while (*s && isspace (*s))
+ s++;
+ if (strncasecmp (s, "re:", 3) == 0)
+ s += 3;
+ else
+ break;
+ }
+
+ return s;
+}
+
+/* Add a term for each message-id in the References header of the
+ * message. */
+static void
+parse_references (GPtrArray *array,
+ const char *refs)
+{
+ const char *end, *next;
+
+ if (refs == NULL)
+ return;
+
+ while (*refs) {
+ while (*refs && isspace (*refs))
+ refs++;
+ if (*refs == '<')
+ refs++;
+ end = refs;
+ while (*end && !isspace (*end))
+ end++;
+ next = end;
+ end--;
+ if (end > refs && *end == '>')
+ end--;
+ if (end > refs) {
+ g_ptr_array_add (array, g_strndup (refs, end - refs + 1));
+ }
+ refs = next;
+ }
+}
+
+/* Generate terms for the body of a message, given the filename of the
+ * message and the offset at which the headers of the message end,
+ * (and hence the body begins). */
+static void
+gen_terms_body (Xapian::TermGenerator term_gen,
+ const char * filename,
+ gint64 body_offset)
+{
+ GIOChannel *channel;
+ GIOStatus gio_status;
+ GError *error = NULL;
+ char *p, *body_line = NULL, *prev_line = NULL;
+
+ channel = g_io_channel_new_file (filename, "r", &error);
+ if (channel == NULL) {
+ fprintf (stderr, "Error: %s\n", error->message);
+ exit (1);
+ }
+
+ gio_status = g_io_channel_seek_position (channel, body_offset,
+ G_SEEK_SET, &error);
+ if (gio_status != G_IO_STATUS_NORMAL) {
+ fprintf (stderr, "Error: %s\n", error->message);
+ exit (1);
+ }
+
+ while (1) {
+ if (body_line)
+ g_free (body_line);
+
+ gio_status = g_io_channel_read_line (channel, &body_line,
+ NULL, NULL, &error);
+ if (gio_status == G_IO_STATUS_EOF)
+ break;
+ if (gio_status != G_IO_STATUS_NORMAL) {
+ fprintf (stderr, "Error: %s\n", error->message);
+ exit (1);
+ }
+
+ if (strlen (body_line) == 0)
+ continue;
+
+ /* If the line looks like it might be introducing a quote,
+ * save it until we see if the next line begins a quote. */
+ p = body_line + strlen (body_line) - 1;
+ while (p > body_line and isspace (*p))
+ p--;
+ if (*p == ':') {
+ prev_line = body_line;
+ body_line = NULL;
+ continue;
+ }
+
+ /* Skip quoted lines, (and previous lines that introduced them) */
+ if (body_line[0] == '>') {
+ if (prev_line) {
+ g_free (prev_line);
+ prev_line = NULL;
+ }
+ continue;
+ }
+
+ /* Now that we're not looking at a quote we can add the prev_line */
+ if (prev_line) {
+ gen_terms (term_gen, "body", prev_line);
+ g_free (prev_line);
+ prev_line = NULL;
+ }
+
+ /* Skip signatures */
+ /* XXX: Should only do this if "near" the end of the message. */
+ if (strncmp (body_line, "-- ", 3) == 0 ||
+ strncmp (body_line, "----------", 10) == 0 ||
+ strncmp (body_line, "__________", 10) == 0)
+ break;
+
+ gen_terms (term_gen, "body", body_line);
+ }
+
+ if (body_line)
+ g_free (body_line);
+
+ g_io_channel_close (channel);
+}
+
+static void
+index_file (Xapian::WritableDatabase db,
+ Xapian::TermGenerator term_gen,
+ const char *filename)