<commit_before>/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-store.c : Abstract class for an email store */

/*
 * Authors:
 *  <NAME> <<EMAIL>>
 *  <NAME> <<EMAIL>>
 *
 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of version 2 of the GNU Lesser General Public
 * License as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
 * USA
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <errno.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>

#include <glib/gi18n-lib.h>

#include "camel-db.h"
#include "camel-debug.h"
#include "camel-folder.h"
#include "camel-marshal.h"
#include "camel-session.h"
#include "camel-store.h"
#include "camel-store-settings.h"
#include "camel-subscribable.h"
#include "camel-vtrash-folder.h"

#define d(x)
#define w(x)

#define CAMEL_STORE_GET_PRIVATE(obj) \
	(G_TYPE_INSTANCE_GET_PRIVATE \
	((obj), CAMEL_TYPE_STORE, CamelStorePrivate))

typedef struct _AsyncContext AsyncContext;
typedef struct _SignalData SignalData;

struct _CamelStorePrivate {
	GStaticRecMutex folder_lock;	/* for locking folder operations */
};

struct _AsyncContext {
	/* arguments */
	gchar *folder_name_1;
	gchar *folder_name_2;
	gboolean expunge;
	guint32 flags;

	/* results */
	CamelFolder *folder;
	CamelFolderInfo *folder_info;
};

struct _SignalData {
	CamelStore *store;
	CamelFolder *folder;
	CamelFolderInfo *folder_info;
	gchar *folder_name;
};

enum {
	FOLDER_CREATED,
	FOLDER_DELETED,
	FOLDER_OPENED,
	FOLDER_RENAMED,
	LAST_SIGNAL
};

static guint signals[LAST_SIGNAL];
static GInitableIface *parent_initable_interface;

/* Forward Declarations */
static void camel_store_initable_init (GInitableIface *interface);

G_DEFINE_ABSTRACT_TYPE_WITH_CODE (
	CamelStore, camel_store, CAMEL_TYPE_SERVICE,
	G_IMPLEMENT_INTERFACE (
		G_TYPE_INITABLE, camel_store_initable_init))

static void
async_context_free (AsyncContext *async_context)
{
	g_free (async_context->folder_name_1);
	g_free (async_context->folder_name_2);

	if (async_context->folder != NULL)
		g_object_unref (async_context->folder);

	camel_folder_info_free (async_context->folder_info);

	g_slice_free (AsyncContext, async_context);
}

static void
signal_data_free (SignalData *data)
{
	if (data->store != NULL)
		g_object_unref (data->store);

	if (data->folder != NULL)
		g_object_unref (data->folder);

	if (data->folder_info != NULL)
		camel_folder_info_free (data->folder_info);

	g_free (data->folder_name);

	g_slice_free (SignalData, data);
}

static gboolean
store_emit_folder_created_cb (SignalData *data)
{
	g_signal_emit (
		data->store,
		signals[FOLDER_CREATED], 0,
		data->folder_info);

	return FALSE;
}

static gboolean
store_emit_folder_deleted_cb (SignalData *data)
{
	g_signal_emit (
		data->store,
		signals[FOLDER_DELETED], 0,
		data->folder_info);

	return FALSE;
}

static gboolean
store_emit_folder_opened_cb (SignalData *data)
{
	g_signal_emit (
		data->store,
		signals[FOLDER_OPENED], 0,
		data->folder);

	return FALSE;
}

static gboolean
store_emit_folder_renamed_cb (SignalData *data)
{
	g_signal_emit (
		data->store,
		signals[FOLDER_RENAMED], 0,
		data->folder_name,
		data->folder_info);

	return FALSE;
}

/**
 * ignore_no_such_table_exception:
 * Clears the exception 'ex' when it's the 'no such table' exception.
 **/
static void
ignore_no_such_table_exception (GError **error)
{
	if (error == NULL || *error == NULL)
		return;

	if (g_ascii_strncasecmp ((*error)->message, "no such table", 13) == 0)
		g_clear_error (error);
}

/* deletes folder/removes it from the folder cache, if it's there */
static void
cs_delete_cached_folder (CamelStore *store,
                         const gchar *folder_name)
{
	CamelFolder *folder;
	CamelVeeFolder *vfolder;

	if (store->folders == NULL)
		return;

	folder = camel_object_bag_get (store->folders, folder_name);
	if (folder == NULL)
		return;

	if (store->flags & CAMEL_STORE_VTRASH) {
		vfolder = camel_object_bag_get (
			store->folders, CAMEL_VTRASH_NAME);
		if (vfolder != NULL) {
			camel_vee_folder_remove_folder (vfolder, folder);
			g_object_unref (vfolder);
		}
	}

	if (store->flags & CAMEL_STORE_VJUNK) {
		vfolder = camel_object_bag_get (
			store->folders, CAMEL_VJUNK_NAME);
		if (vfolder != NULL) {
			camel_vee_folder_remove_folder (vfolder, folder);
			g_object_unref (vfolder);
		}
	}

	camel_folder_delete (folder);

	camel_object_bag_remove (store->folders, folder);
	g_object_unref (folder);
}

static CamelFolder *
store_get_special (CamelStore *store,
                   camel_vtrash_folder_t type)
{
	CamelFolder *folder;
	GPtrArray *folders;
	gint i;

	folder = camel_vtrash_folder_new (store, type);
	folders = camel_object_bag_list (store->folders);
	for (i = 0; i < folders->len; i++) {
		if (!CAMEL_IS_VTRASH_FOLDER (folders->pdata[i]))
			camel_vee_folder_add_folder ((CamelVeeFolder *) folder, (CamelFolder *) folders->pdata[i]);
		g_object_unref (folders->pdata[i]);
	}
	g_ptr_array_free (folders, TRUE);

	return folder;
}

static void
store_finalize (GObject *object)
{
	CamelStore *store = CAMEL_STORE (object);

	if (store->folders != NULL)
		camel_object_bag_destroy (store->folders);

	g_static_rec_mutex_free (&store->priv->folder_lock);

	if (store->cdb_r != NULL) {
		camel_db_close (store->cdb_r);
		store->cdb_r = NULL;
		store->cdb_w = NULL;
	}

	/* Chain up to parent's finalize() method. */
	G_OBJECT_CLASS (camel_store_parent_class)->finalize (object);
}

static void
store_constructed (GObject *object)
{
	CamelStore *store;
	CamelStoreClass *class;

	/* Chain up to parent's constructed() method. */
	G_OBJECT_CLASS (camel_store_parent_class)->constructed (object);

	store = CAMEL_STORE (object);
	class = CAMEL_STORE_GET_CLASS (store);

	g_return_if_fail (class->hash_folder_name != NULL);
	g_return_if_fail (class->compare_folder_name != NULL);

	store->folders = camel_object_bag_new (
		class->hash_folder_name,
		class->compare_folder_name,
		(CamelCopyFunc) g_strdup, g_free);
}

static gboolean
store_can_refresh_folder (CamelStore *store,
                          CamelFolderInfo *info,
                          GError **error)
{
	return ((info->flags & CAMEL_FOLDER_TYPE_MASK) == CAMEL_FOLDER_TYPE_INBOX);
}

static CamelFolder *
store_get_inbox_folder_sync (CamelStore *store,
                             GCancellable *cancellable,
                             GError **error)
{
	CamelStoreClass *class;
	CamelFolder *folder;

	/* Assume the inbox's name is "inbox" and open with default flags. */
	class = CAMEL_STORE_GET_CLASS (store);
	folder = class->get_folder_sync (store, "inbox", 0, cancellable, error);
	CAMEL_CHECK_GERROR (store, get_folder_sync, folder != NULL, error);

	return folder;
}

static CamelFolder *
store_get_junk_folder_sync (CamelStore *store,
                            GCancellable *cancellable,
                            GError **error)<commit_msg>store_get_inbox_folder_sync: Add a NULL check.<commit_after>/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-store.c : Abstract class for an email store */

/*
 * Authors:
 *  <NAME> <<EMAIL>>
 *  <NAME> <<EMAIL>>
 *
 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of version 2 of the GNU Lesser General Public
 * License as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
 * USA
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <errno.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>

#include <glib/gi18n-lib.h>

#include "camel-db.h"
#include "camel-debug.h"
#include "camel-folder.h"
#include "camel-marshal.h"
#include "camel-session.h"
#include "camel-store.h"
#include "camel-store-settings.h"
#include "camel-subscribable.h"
#include "camel-vtrash-folder.h"

#define d(x)
#define w(x)

#define CAMEL_STORE_GET_PRIVATE(obj) \
	(G_TYPE_INSTANCE_GET_PRIVATE \
	((obj), CAMEL_TYPE_STORE, CamelStorePrivate))

typedef struct _AsyncContext AsyncContext;
typedef struct _SignalData SignalData;

struct _CamelStorePrivate {
	GStaticRecMutex folder_lock;	/* for locking folder operations */
};

struct _AsyncContext {
	/* arguments */
	gchar *folder_name_1;
	gchar *folder_name_2;
	gboolean expunge;
	guint32 flags;

	/* results */
	CamelFolder *folder;
	CamelFolderInfo *folder_info;
};

struct _SignalData {
	CamelStore *store;
	CamelFolder *folder;
	CamelFolderInfo *folder_info;
	gchar *folder_name;
};

enum {
	FOLDER_CREATED,
	FOLDER_DELETED,
	FOLDER_OPENED,
	FOLDER_RENAMED,
	LAST_SIGNAL
};

static guint signals[LAST_SIGNAL];
static GInitableIface *parent_initable_interface;

/* Forward Declarations */
static void camel_store_initable_init (GInitableIface *interface);

G_DEFINE_ABSTRACT_TYPE_WITH_CODE (
	CamelStore, camel_store, CAMEL_TYPE_SERVICE,
	G_IMPLEMENT_INTERFACE (
		G_TYPE_INITABLE, camel_store_initable_init))

static void
async_context_free (AsyncContext *async_context)
{
	g_free (async_context->folder_name_1);
	g_free (async_context->folder_name_2);

	if (async_context->folder != NULL)
		g_object_unref (async_context->folder);

	camel_folder_info_free (async_context->folder_info);

	g_slice_free (AsyncContext, async_context);
}

static void
signal_data_free (SignalData *data)
{
	if (data->store != NULL)
		g_object_unref (data->store);

	if (data->folder != NULL)
		g_object_unref (data->folder);

	if (data->folder_info != NULL)
		camel_folder_info_free (data->folder_info);

	g_free (data->folder_name);

	g_slice_free (SignalData, data);
}

static gboolean
store_emit_folder_created_cb (SignalData *data)
{
	g_signal_emit (
		data->store,
		signals[FOLDER_CREATED], 0,
		data->folder_info);

	return FALSE;
}

static gboolean
store_emit_folder_deleted_cb (SignalData *data)
{
	g_signal_emit (
		data->store,
		signals[FOLDER_DELETED], 0,
		data->folder_info);

	return FALSE;
}

static gboolean
store_emit_folder_opened_cb (SignalData *data)
{
	g_signal_emit (
		data->store,
		signals[FOLDER_OPENED], 0,
		data->folder);

	return FALSE;
}

static gboolean
store_emit_folder_renamed_cb (SignalData *data)
{
	g_signal_emit (
		data->store,
		signals[FOLDER_RENAMED], 0,
		data->folder_name,
		data->folder_info);

	return FALSE;
}

/**
 * ignore_no_such_table_exception:
 * Clears the exception 'ex' when it's the 'no such table' exception.
 **/
static void
ignore_no_such_table_exception (GError **error)
{
	if (error == NULL || *error == NULL)
		return;

	if (g_ascii_strncasecmp ((*error)->message, "no such table", 13) == 0)
		g_clear_error (error);
}

/* deletes folder/removes it from the folder cache, if it's there */
static void
cs_delete_cached_folder (CamelStore *store,
                         const gchar *folder_name)
{
	CamelFolder *folder;
	CamelVeeFolder *vfolder;

	if (store->folders == NULL)
		return;

	folder = camel_object_bag_get (store->folders, folder_name);
	if (folder == NULL)
		return;

	if (store->flags & CAMEL_STORE_VTRASH) {
		vfolder = camel_object_bag_get (
			store->folders, CAMEL_VTRASH_NAME);
		if (vfolder != NULL) {
			camel_vee_folder_remove_folder (vfolder, folder);
			g_object_unref (vfolder);
		}
	}

	if (store->flags & CAMEL_STORE_VJUNK) {
		vfolder = camel_object_bag_get (
			store->folders, CAMEL_VJUNK_NAME);
		if (vfolder != NULL) {
			camel_vee_folder_remove_folder (vfolder, folder);
			g_object_unref (vfolder);
		}
	}

	camel_folder_delete (folder);

	camel_object_bag_remove (store->folders, folder);
	g_object_unref (folder);
}

static CamelFolder *
store_get_special (CamelStore *store,
                   camel_vtrash_folder_t type)
{
	CamelFolder *folder;
	GPtrArray *folders;
	gint i;

	folder = camel_vtrash_folder_new (store, type);
	folders = camel_object_bag_list (store->folders);
	for (i = 0; i < folders->len; i++) {
		if (!CAMEL_IS_VTRASH_FOLDER (folders->pdata[i]))
			camel_vee_folder_add_folder ((CamelVeeFolder *) folder, (CamelFolder *) folders->pdata[i]);
		g_object_unref (folders->pdata[i]);
	}
	g_ptr_array_free (folders, TRUE);

	return folder;
}

static void
store_finalize (GObject *object)
{
	CamelStore *store = CAMEL_STORE (object);

	if (store->folders != NULL)
		camel_object_bag_destroy (store->folders);

	g_static_rec_mutex_free (&store->priv->folder_lock);

	if (store->cdb_r != NULL) {
		camel_db_close (store->cdb_r);
		store->cdb_r = NULL;
		store->cdb_w = NULL;
	}

	/* Chain up to parent's finalize() method. */
	G_OBJECT_CLASS (camel_store_parent_class)->finalize (object);
}

static void
store_constructed (GObject *object)
{
	CamelStore *store;
	CamelStoreClass *class;

	/* Chain up to parent's constructed() method. */
	G_OBJECT_CLASS (camel_store_parent_class)->constructed (object);

	store = CAMEL_STORE (object);
	class = CAMEL_STORE_GET_CLASS (store);

	g_return_if_fail (class->hash_folder_name != NULL);
	g_return_if_fail (class->compare_folder_name != NULL);

	store->folders = camel_object_bag_new (
		class->hash_folder_name,
		class->compare_folder_name,
		(CamelCopyFunc) g_strdup, g_free);
}

static gboolean
store_can_refresh_folder (CamelStore *store,
                          CamelFolderInfo *info,
                          GError **error)
{
	return ((info->flags & CAMEL_FOLDER_TYPE_MASK) == CAMEL_FOLDER_TYPE_INBOX);
}

static CamelFolder *
store_get_inbox_folder_sync (CamelStore *store,
                             GCancellable *cancellable,
                             GError **error)
{
	CamelStoreClass *class;
	CamelFolder *folder;

	class = CAMEL_STORE_GET_CLASS (store);
	g_return_val_if_fail (class->get_folder_sync != NULL, NULL);

	/* Assume the inbox's name is "inbox" and open with default flags. */
	folder = class->get_folder_sync (store, "inbox", 0, cancellable, error);
	CAMEL_CHECK_GERROR (store, get_folder_sync, folder != NULL, error);

	return folder;
}

static CamelFolder *
store_get_junk_folder_sync (CamelStore *store,
                            GCancellable *cancellable,
                            GError **error)
{'fraction_non_alphanumeric': 0.11286019210245464, 'fraction_numerical': 0.005202774813233725, 'mean_word_length': 4.436185641769399, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 130, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2714080', 'n_tokens_mistral': 5662, 'n_tokens_neox': 5363, 'n_words': 1241}