Esempio n. 1
0
/* Print a message in "mboxrd" format as documented, for example,
 * here:
 *
 * http://qmail.org/qmail-manual-html/man5/mbox.html
 */
static notmuch_status_t
format_part_mbox (const void *ctx, unused (sprinter_t *sp), mime_node_t *node,
		  unused (int indent),
		  unused (const notmuch_show_params_t *params))
{
    notmuch_message_t *message = node->envelope_file;

    const char *filename;
    FILE *file;
    const char *from;

    time_t date;
    struct tm date_gmtime;
    char date_asctime[26];

    char *line = NULL;
    size_t line_size;
    ssize_t line_len;

    if (!message)
	INTERNAL_ERROR ("format_part_mbox requires a root part");

    filename = notmuch_message_get_filename (message);
    file = fopen (filename, "r");
    if (file == NULL) {
	fprintf (stderr, "Failed to open %s: %s\n",
		 filename, strerror (errno));
	return NOTMUCH_STATUS_FILE_ERROR;
    }

    from = notmuch_message_get_header (message, "from");
    from = _extract_email_address (ctx, from);

    date = notmuch_message_get_date (message);
    gmtime_r (&date, &date_gmtime);
    asctime_r (&date_gmtime, date_asctime);

    printf ("From %s %s", from, date_asctime);

    while ((line_len = getline (&line, &line_size, file)) != -1 ) {
	if (_is_from_line (line))
	    putchar ('>');
	printf ("%s", line);
    }

    printf ("\n");

    fclose (file);

    return NOTMUCH_STATUS_SUCCESS;
}
Esempio n. 2
0
static int
msg_header(Tcl_Interp *interp, notmuch_message_t *msg, int argc, const char *argv[]) {
    if (argc != 1) {
        tcl_result_printf(interp, "expected: msg header <header>");
        return TCL_ERROR;
    }

    const char *value = notmuch_message_get_header(msg, argv[0]);

    if (value == NULL) {
        return TCL_ERROR;
    }

    tcl_result_printf(interp, "%s", value);
    return TCL_OK;
}
Esempio n. 3
0
/* Get a nice, single-line summary of message. */
static const char *
_get_one_line_summary (const void *ctx, notmuch_message_t *message)
{
    const char *from;
    time_t date;
    const char *relative_date;
    const char *tags;

    from = notmuch_message_get_header (message, "from");

    date = notmuch_message_get_date (message);
    relative_date = notmuch_time_relative_date (ctx, date);

    tags = _get_tags_as_string (ctx, message);

    return talloc_asprintf (ctx, "%s (%s) (%s)",
                            from, relative_date, tags);
}
Esempio n. 4
0
static void
format_headers_text (const void *ctx, notmuch_message_t *message)
{
    const char *headers[] = {
	"Subject", "From", "To", "Cc", "Bcc", "Date"
    };
    const char *name, *value;
    unsigned int i;

    printf ("%s\n", _get_one_line_summary (ctx, message));

    for (i = 0; i < ARRAY_SIZE (headers); i++) {
	name = headers[i];
	value = notmuch_message_get_header (message, name);
	if (value && strlen (value))
	    printf ("%s: %s\n", name, value);
    }
}
Esempio n. 5
0
/* Print a message in "mboxrd" format as documented, for example,
 * here:
 *
 * http://qmail.org/qmail-manual-html/man5/mbox.html
 */
static void
format_message_mbox (const void *ctx,
		     notmuch_message_t *message,
		     unused (int indent))
{
    const char *filename;
    FILE *file;
    const char *from;

    time_t date;
    struct tm date_gmtime;
    char date_asctime[26];

    char *line = NULL;
    size_t line_size;
    ssize_t line_len;

    filename = notmuch_message_get_filename (message);
    file = fopen (filename, "r");
    if (file == NULL) {
	fprintf (stderr, "Failed to open %s: %s\n",
		 filename, strerror (errno));
	return;
    }

    from = notmuch_message_get_header (message, "from");
    from = _extract_email_address (ctx, from);

    date = notmuch_message_get_date (message);
    gmtime_r (&date, &date_gmtime);
    asctime_r (&date_gmtime, date_asctime);

    printf ("From %s %s", from, date_asctime);

    while ((line_len = getline (&line, &line_size, file)) != -1 ) {
	if (_is_from_line (line))
	    putchar ('>');
	printf ("%s", line);
    }

    printf ("\n");

    fclose (file);
}
Esempio n. 6
0
/*
 * Try to find user's email address in one of the extra To-like
 * headers: Envelope-To, X-Original-To, and Delivered-To (searched in
 * that order).
 *
 * Return the address that was found, if any, and NULL otherwise.
 */
static const char *
get_from_in_to_headers (notmuch_config_t *config, notmuch_message_t *message)
{
    size_t i;
    const char *tohdr, *addr;
    const char *to_headers[] = {
	"Envelope-to",
	"X-Original-To",
	"Delivered-To",
    };

    for (i = 0; i < ARRAY_SIZE (to_headers); i++) {
	tohdr = notmuch_message_get_header (message, to_headers[i]);

	/* Note: tohdr potentially contains a list of email addresses. */
	addr = user_address_in_string (tohdr, config);
	if (addr)
	    return addr;
    }

    return NULL;
}
Esempio n. 7
0
/*
 * Get the concatenated Received: headers and search from the front
 * (last Received: header added) and try to extract from them
 * indications to which email address this message was delivered.
 *
 * The Received: header is special in our get_header function and is
 * always concatenated.
 *
 * Return the address that was found, if any, and NULL otherwise.
 */
static const char *
guess_from_in_received_headers (notmuch_config_t *config,
				notmuch_message_t *message)
{
    const char *received, *addr;
    char *sanitized;

    received = notmuch_message_get_header (message, "received");
    if (! received)
	return NULL;

    sanitized = sanitize_string (NULL, received);
    if (! sanitized)
	return NULL;

    addr = guess_from_in_received_for (config, sanitized);
    if (! addr)
	addr = guess_from_in_received_by (config, sanitized);

    talloc_free (sanitized);

    return addr;
}
Esempio n. 8
0
static GMimeMessage *
create_reply_message(void *ctx,
		     notmuch_config_t *config,
		     notmuch_message_t *message,
		     notmuch_bool_t reply_all)
{
    const char *subject, *from_addr = NULL;
    const char *in_reply_to, *orig_references, *references;

    /* The 1 means we want headers in a "pretty" order. */
    GMimeMessage *reply = g_mime_message_new (1);
    if (reply == NULL) {
	fprintf (stderr, "Out of memory\n");
	return NULL;
    }

    subject = notmuch_message_get_header (message, "subject");
    if (subject) {
	if (strncasecmp (subject, "Re:", 3))
	    subject = talloc_asprintf (ctx, "Re: %s", subject);
	g_mime_message_set_subject (reply, subject);
    }

    from_addr = add_recipients_from_message (reply, config,
					     message, reply_all);

    /*
     * Sadly, there is no standard way to find out to which email
     * address a mail was delivered - what is in the headers depends
     * on the MTAs used along the way.
     *
     * If none of the user's email addresses are in the To: or Cc:
     * headers, we try a number of heuristics which hopefully will
     * answer this question.
     *
     * First, check for Envelope-To:, X-Original-To:, and
     * Delivered-To: headers.
     */
    if (from_addr == NULL)
	from_addr = get_from_in_to_headers (config, message);

    /*
     * Check for a (for <*****@*****.**>) clause in Received: headers,
     * and the domain part of known email addresses in the 'by' part
     * of Received: headers
     */
    if (from_addr == NULL)
	from_addr = guess_from_in_received_headers (config, message);

    /* Default to user's primary address. */
    if (from_addr == NULL)
	from_addr = notmuch_config_get_user_primary_email (config);

    from_addr = talloc_asprintf (ctx, "%s <%s>",
				 notmuch_config_get_user_name (config),
				 from_addr);
    g_mime_object_set_header (GMIME_OBJECT (reply),
			      "From", from_addr);

    in_reply_to = talloc_asprintf (ctx, "<%s>",
				   notmuch_message_get_message_id (message));

    g_mime_object_set_header (GMIME_OBJECT (reply),
			      "In-Reply-To", in_reply_to);

    orig_references = notmuch_message_get_header (message, "references");
    if (!orig_references)
	/* Treat errors like missing References headers. */
	orig_references = "";
    references = talloc_asprintf (ctx, "%s%s%s",
				  *orig_references ? orig_references : "",
				  *orig_references ? " " : "",
				  in_reply_to);
    g_mime_object_set_header (GMIME_OBJECT (reply),
			      "References", references);

    return reply;
}
Esempio n. 9
0
/* Augment the recipients of 'reply' from the "Reply-to:", "From:",
 * "To:", "Cc:", and "Bcc:" headers of 'message'.
 *
 * If 'reply_all' is true, use sender and all recipients, otherwise
 * scan the headers for the first that contains something other than
 * the user's addresses and add the recipients from this header
 * (typically this would be reply-to-sender, but also handles reply to
 * user's own message in a sensible way).
 *
 * If any of the user's addresses were found in these headers, the
 * first of these returned, otherwise NULL is returned.
 */
static const char *
add_recipients_from_message (GMimeMessage *reply,
			     notmuch_config_t *config,
			     notmuch_message_t *message,
			     notmuch_bool_t reply_all)
{
    struct {
	const char *header;
	const char *fallback;
	GMimeRecipientType recipient_type;
    } reply_to_map[] = {
	{ "reply-to", "from", GMIME_RECIPIENT_TYPE_TO  },
	{ "to",         NULL, GMIME_RECIPIENT_TYPE_TO  },
	{ "cc",         NULL, GMIME_RECIPIENT_TYPE_CC  },
	{ "bcc",        NULL, GMIME_RECIPIENT_TYPE_BCC }
    };
    const char *from_addr = NULL;
    unsigned int i;
    unsigned int n = 0;

    /* Some mailing lists munge the Reply-To header despite it being A Bad
     * Thing, see http://www.unicom.com/pw/reply-to-harmful.html
     *
     * The munging is easy to detect, because it results in a
     * redundant reply-to header, (with an address that already exists
     * in either To or Cc). So in this case, we ignore the Reply-To
     * field and use the From header. This ensures the original sender
     * will get the reply even if not subscribed to the list. Note
     * that the address in the Reply-To header will always appear in
     * the reply.
     */
    if (reply_to_header_is_redundant (message)) {
	reply_to_map[0].header = "from";
	reply_to_map[0].fallback = NULL;
    }

    for (i = 0; i < ARRAY_SIZE (reply_to_map); i++) {
	const char *recipients;

	recipients = notmuch_message_get_header (message,
						 reply_to_map[i].header);
	if ((recipients == NULL || recipients[0] == '\0') && reply_to_map[i].fallback)
	    recipients = notmuch_message_get_header (message,
						     reply_to_map[i].fallback);

	n += scan_address_string (recipients, config, reply,
				  reply_to_map[i].recipient_type, &from_addr);

	if (!reply_all && n) {
	    /* Stop adding new recipients in reply-to-sender mode if
	     * we have added some recipient(s) above.
	     *
	     * This also handles the case of user replying to his own
	     * message, where reply-to/from is not a recipient. In
	     * this case there may be more than one recipient even if
	     * not replying to all.
	     */
	    reply = NULL;

	    /* From address and some recipients are enough, bail out. */
	    if (from_addr)
		break;
	}
    }

    return from_addr;
}
Esempio n. 10
0
/* This format is currently tuned for a git send-email --notmuch hook */
static int
notmuch_reply_format_headers_only(void *ctx,
				  notmuch_config_t *config,
				  notmuch_query_t *query,
				  unused (notmuch_show_params_t *params),
				  notmuch_bool_t reply_all,
				  unused (sprinter_t *sp))
{
    GMimeMessage *reply;
    notmuch_messages_t *messages;
    notmuch_message_t *message;
    const char *in_reply_to, *orig_references, *references;
    char *reply_headers;
    notmuch_status_t status;

    status = notmuch_query_search_messages_st (query, &messages);
    if (print_status_query ("notmuch reply", query, status))
	return 1;

    for (;
	 notmuch_messages_valid (messages);
	 notmuch_messages_move_to_next (messages))
    {
	message = notmuch_messages_get (messages);

	/* The 0 means we do not want headers in a "pretty" order. */
	reply = g_mime_message_new (0);
	if (reply == NULL) {
	    fprintf (stderr, "Out of memory\n");
	    return 1;
	}

	in_reply_to = talloc_asprintf (ctx, "<%s>",
			     notmuch_message_get_message_id (message));

        g_mime_object_set_header (GMIME_OBJECT (reply),
				  "In-Reply-To", in_reply_to);


	orig_references = notmuch_message_get_header (message, "references");

	/* We print In-Reply-To followed by References because git format-patch treats them
         * specially.  Git does not interpret the other headers specially
	 */
	references = talloc_asprintf (ctx, "%s%s%s",
				      orig_references ? orig_references : "",
				      orig_references ? " " : "",
				      in_reply_to);
	g_mime_object_set_header (GMIME_OBJECT (reply),
				  "References", references);

	(void)add_recipients_from_message (reply, config, message, reply_all);

	reply_headers = g_mime_object_to_string (GMIME_OBJECT (reply));
	printf ("%s", reply_headers);
	free (reply_headers);

	g_object_unref (G_OBJECT (reply));
	reply = NULL;

	notmuch_message_destroy (message);
    }
    return 0;
}
Esempio n. 11
0
static int
notmuch_reply_format_default(void *ctx,
			     notmuch_config_t *config,
			     notmuch_query_t *query,
			     notmuch_show_params_t *params)
{
    GMimeMessage *reply;
    notmuch_messages_t *messages;
    notmuch_message_t *message;
    const char *subject, *from_addr = NULL;
    const char *in_reply_to, *orig_references, *references;
    const notmuch_show_format_t *format = &format_reply;

    for (messages = notmuch_query_search_messages (query);
	 notmuch_messages_valid (messages);
	 notmuch_messages_move_to_next (messages))
    {
	message = notmuch_messages_get (messages);

	/* The 1 means we want headers in a "pretty" order. */
	reply = g_mime_message_new (1);
	if (reply == NULL) {
	    fprintf (stderr, "Out of memory\n");
	    return 1;
	}

	subject = notmuch_message_get_header (message, "subject");
	if (subject) {
	    if (strncasecmp (subject, "Re:", 3))
		subject = talloc_asprintf (ctx, "Re: %s", subject);
	    g_mime_message_set_subject (reply, subject);
	}

	from_addr = add_recipients_from_message (reply, config, message);

	if (from_addr == NULL)
	    from_addr = guess_from_received_header (config, message);

	if (from_addr == NULL)
	    from_addr = notmuch_config_get_user_primary_email (config);

	from_addr = talloc_asprintf (ctx, "%s <%s>",
				     notmuch_config_get_user_name (config),
				     from_addr);
	g_mime_object_set_header (GMIME_OBJECT (reply),
				  "From", from_addr);

	in_reply_to = talloc_asprintf (ctx, "<%s>",
			     notmuch_message_get_message_id (message));

	g_mime_object_set_header (GMIME_OBJECT (reply),
				  "In-Reply-To", in_reply_to);

	orig_references = notmuch_message_get_header (message, "references");
	references = talloc_asprintf (ctx, "%s%s%s",
				      orig_references ? orig_references : "",
				      orig_references ? " " : "",
				      in_reply_to);
	g_mime_object_set_header (GMIME_OBJECT (reply),
				  "References", references);

	show_reply_headers (reply);

	g_object_unref (G_OBJECT (reply));
	reply = NULL;

	printf ("On %s, %s wrote:\n",
		notmuch_message_get_header (message, "date"),
		notmuch_message_get_header (message, "from"));

	show_message_body (notmuch_message_get_filename (message),
			   format, params);

	notmuch_message_destroy (message);
    }
    return 0;
}
Esempio n. 12
0
static const char *
guess_from_received_header (notmuch_config_t *config, notmuch_message_t *message)
{
    const char *received,*primary,*by;
    const char **other;
    char *tohdr;
    char *mta,*ptr,*token;
    char *domain=NULL;
    char *tld=NULL;
    const char *delim=". \t";
    size_t i,j,other_len;

    const char *to_headers[] = {"Envelope-to", "X-Original-To"};

    primary = notmuch_config_get_user_primary_email (config);
    other = notmuch_config_get_user_other_email (config, &other_len);

    /* sadly, there is no standard way to find out to which email
     * address a mail was delivered - what is in the headers depends
     * on the MTAs used along the way. So we are trying a number of
     * heuristics which hopefully will answer this question.

     * We only got here if none of the users email addresses are in
     * the To: or Cc: header. From here we try the following in order:
     * 1) check for an Envelope-to: header
     * 2) check for an X-Original-To: header
     * 3) check for a (for <*****@*****.**>) clause in Received: headers
     * 4) check for the domain part of known email addresses in the
     *    'by' part of Received headers
     * If none of these work, we give up and return NULL
     */
    for (i = 0; i < sizeof(to_headers)/sizeof(*to_headers); i++) {
	tohdr = xstrdup(notmuch_message_get_header (message, to_headers[i]));
	if (tohdr && *tohdr) {
	    /* tohdr is potentialy a list of email addresses, so here we
	     * check if one of the email addresses is a substring of tohdr
	     */
	    if (strcasestr(tohdr, primary)) {
		free(tohdr);
		return primary;
	    }
	    for (j = 0; j < other_len; j++)
		if (strcasestr (tohdr, other[j])) {
		    free(tohdr);
		    return other[j];
		}
	    free(tohdr);
	}
    }

    /* We get the concatenated Received: headers and search from the
     * front (last Received: header added) and try to extract from
     * them indications to which email address this message was
     * delivered.
     * The Received: header is special in our get_header function
     * and is always concatenated.
     */
    received = notmuch_message_get_header (message, "received");
    if (received == NULL)
	return NULL;

    /* First we look for a " for <*****@*****.**>" in the received
     * header
     */
    ptr = strstr (received, " for ");
    if (ptr) {
	/* the text following is potentialy a list of email addresses,
	 * so again we check if one of the email addresses is a
	 * substring of ptr
	 */
	if (strcasestr(ptr, primary)) {
	    return primary;
	}
	for (i = 0; i < other_len; i++)
	    if (strcasestr (ptr, other[i])) {
		return other[i];
	    }
    }
    /* Finally, we parse all the " by MTA ..." headers to guess the
     * email address that this was originally delivered to.
     * We extract just the MTA here by removing leading whitespace and
     * assuming that the MTA name ends at the next whitespace.
     * We test for *(by+4) to be non-'\0' to make sure there's
     * something there at all - and then assume that the first
     * whitespace delimited token that follows is the receiving
     * system in this step of the receive chain
     */
    by = received;
    while((by = strstr (by, " by ")) != NULL) {
	by += 4;
	if (*by == '\0')
	    break;
	mta = xstrdup (by);
	token = strtok(mta," \t");
	if (token == NULL) {
	    free (mta);
	    break;
	}
	/* Now extract the last two components of the MTA host name
	 * as domain and tld.
	 */
	domain = tld = NULL;
	while ((ptr = strsep (&token, delim)) != NULL) {
	    if (*ptr == '\0')
		continue;
	    domain = tld;
	    tld = ptr;
	}

	if (domain) {
	    /* Recombine domain and tld and look for it among the configured
	     * email addresses.
	     * This time we have a known domain name and nothing else - so
	     * the test is the other way around: we check if this is a
	     * substring of one of the email addresses.
	     */
	    *(tld-1) = '.';

	    if (strcasestr(primary, domain)) {
		free(mta);
		return primary;
	    }
	    for (i = 0; i < other_len; i++)
		if (strcasestr (other[i],domain)) {
		    free(mta);
		    return other[i];
		}
	}
	free (mta);
    }

    return NULL;
}
Esempio n. 13
0
static int
do_search_messages (search_context_t *ctx)
{
    notmuch_message_t *message;
    notmuch_messages_t *messages;
    notmuch_filenames_t *filenames;
    sprinter_t *format = ctx->format;
    int i;
    notmuch_status_t status;

    if (ctx->offset < 0) {
	unsigned count;
	notmuch_status_t status;
	status = notmuch_query_count_messages_st (ctx->query, &count);
	if (print_status_query ("notmuch search", ctx->query, status))
	    return 1;

	ctx->offset += count;
	if (ctx->offset < 0)
	    ctx->offset = 0;
    }

    status = notmuch_query_search_messages_st (ctx->query, &messages);
    if (print_status_query ("notmuch search", ctx->query, status))
	return 1;

    format->begin_list (format);

    for (i = 0;
	 notmuch_messages_valid (messages) && (ctx->limit < 0 || i < ctx->offset + ctx->limit);
	 notmuch_messages_move_to_next (messages), i++)
    {
	if (i < ctx->offset)
	    continue;

	message = notmuch_messages_get (messages);

	if (ctx->output == OUTPUT_FILES) {
	    int j;
	    filenames = notmuch_message_get_filenames (message);

	    for (j = 1;
		 notmuch_filenames_valid (filenames);
		 notmuch_filenames_move_to_next (filenames), j++)
	    {
		if (ctx->dupe < 0 || ctx->dupe == j) {
		    format->string (format, notmuch_filenames_get (filenames));
		    format->separator (format);
		}
	    }
	    
	    notmuch_filenames_destroy( filenames );

	} else if (ctx->output == OUTPUT_MESSAGES) {
            /* special case 1 for speed */
            if (ctx->dupe <= 1 || ctx->dupe <= _count_filenames (message)) {
                format->set_prefix (format, "id");
                format->string (format,
                                notmuch_message_get_message_id (message));
                format->separator (format);
            }
	} else {
	    if (ctx->output & OUTPUT_SENDER) {
		const char *addrs;

		addrs = notmuch_message_get_header (message, "from");
		process_address_header (ctx, addrs);
	    }

	    if (ctx->output & OUTPUT_RECIPIENTS) {
		const char *hdrs[] = { "to", "cc", "bcc" };
		const char *addrs;
		size_t j;

		for (j = 0; j < ARRAY_SIZE (hdrs); j++) {
		    addrs = notmuch_message_get_header (message, hdrs[j]);
		    process_address_header (ctx, addrs);
		}
	    }
	}

	notmuch_message_destroy (message);
    }

    if (ctx->addresses &&
	(ctx->output & OUTPUT_COUNT || ctx->dedup == DEDUP_ADDRESS))
	g_hash_table_foreach (ctx->addresses, print_hash_value, ctx);

    notmuch_messages_destroy (messages);

    format->end (format);

    return 0;
}
int main (int argc, char** argv) {
  GFile              *db_dir, *db_file;
  notmuch_status_t    status;
  notmuch_database_t *db   = NULL;
  notmuch_query_t *query = NULL;
  notmuch_messages_t *messages = NULL;
  notmuch_message_t *message = NULL;
  GMainLoop          *loop = NULL;

  const char *query_string = "date:2014-02-01..";

  if (argc != 2)
  {
    g_warning ("Usage: %s EVOLUTION_MAILDIR", argv[0]);
    return 1;
  }

  db_dir = g_file_new_for_path (argv[1]);
  db_file = g_file_get_child (db_dir, ".notmuch");

  if (!g_file_query_exists (db_dir, NULL))
  {
    g_object_unref (db_dir);
    g_object_unref (db_file);
    g_error ("directory %s does not exists");
    return 2;
  }

  if (!g_file_query_exists (db_file, NULL))
    status = notmuch_database_create (argv[1], &db);
  else
    status = notmuch_database_open (argv[1], NOTMUCH_DATABASE_MODE_READ_WRITE, &db);

  if (status)
  {
    g_error ("Could not open database: %d", status);
    g_object_unref (db_dir);
    g_object_unref (db_file);
    notmuch_database_destroy (db);
    return 3;
  }


  scan_directory (db, db_dir);
  //loop = g_main_loop_new (NULL, FALSE);
  //g_main_loop_run (loop);

  query = notmuch_query_create (db, query_string);

  if (!query) {
    g_error ("Could not create query from string = \"%s\"", query_string);
    notmuch_database_destroy (db);
    g_object_unref (db_file);
    g_object_unref (db_dir);
    return 4;
  }

  g_message ("Query results -\n\n");

  for (messages = notmuch_query_search_messages (query);
         notmuch_messages_valid (messages);
         notmuch_messages_move_to_next (messages)) {

    message = notmuch_messages_get (messages);

    g_message ("Message file: %s", notmuch_message_get_filename (message));
    g_message ("Message ID: %s", notmuch_message_get_message_id (message));
    g_message ("Message Sender: %s", notmuch_message_get_header (message, "from"));
    g_message ("Message Recipients: %s", notmuch_message_get_header (message, "to"));
    g_message ("Message Subject: %s", notmuch_message_get_header (message, "subject"));
    g_message ("Message date: %s\n", notmuch_message_get_header (message, "date"));

    notmuch_message_destroy (message);
  }

  notmuch_query_destroy (query);

  notmuch_database_destroy (db);
  g_object_unref (db_file);
  g_object_unref (db_dir);
  return 0;
}