[asterisk-commits] mjordan: branch mjordan/voicemail_refactor_11_10_19 r349725 - in /team/mjorda...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu Jan 5 14:58:14 CST 2012


Author: mjordan
Date: Thu Jan  5 14:58:10 2012
New Revision: 349725

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=349725
Log:
Committing to resolve svn merge issues

Added:
    team/mjordan/voicemail_refactor_11_10_19/main/message_storage.c   (with props)
    team/mjordan/voicemail_refactor_11_10_19/res/res_message_file.c
      - copied, changed from r348361, team/mjordan/voicemail_refactor_11_10_19/res/res_message_storage.c
Removed:
    team/mjordan/voicemail_refactor_11_10_19/res/res_message_storage.c
Modified:
    team/mjordan/voicemail_refactor_11_10_19/include/asterisk/_private.h
    team/mjordan/voicemail_refactor_11_10_19/include/asterisk/message_storage.h
    team/mjordan/voicemail_refactor_11_10_19/main/asterisk.c
    team/mjordan/voicemail_refactor_11_10_19/res/res_message_imap.c

Modified: team/mjordan/voicemail_refactor_11_10_19/include/asterisk/_private.h
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/voicemail_refactor_11_10_19/include/asterisk/_private.h?view=diff&rev=349725&r1=349724&r2=349725
==============================================================================
--- team/mjordan/voicemail_refactor_11_10_19/include/asterisk/_private.h (original)
+++ team/mjordan/voicemail_refactor_11_10_19/include/asterisk/_private.h Thu Jan  5 14:58:10 2012
@@ -48,6 +48,7 @@
 int ast_ssl_init(void);                 /*!< Provided by ssl.c */
 int ast_test_init(void);            /*!< Provided by test.c */
 int ast_msg_init(void);             /*!< Provided by message.c */
+int ast_message_storage_init(void); /*!< Provided by message_storage.c */
 
 /*!
  * \brief Reload asterisk modules.

Modified: team/mjordan/voicemail_refactor_11_10_19/include/asterisk/message_storage.h
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/voicemail_refactor_11_10_19/include/asterisk/message_storage.h?view=diff&rev=349725&r1=349724&r2=349725
==============================================================================
--- team/mjordan/voicemail_refactor_11_10_19/include/asterisk/message_storage.h (original)
+++ team/mjordan/voicemail_refactor_11_10_19/include/asterisk/message_storage.h Thu Jan  5 14:58:10 2012
@@ -8,14 +8,16 @@
 #ifndef MESSAGE_STORAGE_H_
 #define MESSAGE_STORAGE_H_
 
+struct mailbox_pvt;
 
 struct ast_msg_config {
+	char type_name[32];
 	unsigned int max_deleted_messages;
 	unsigned int max_messages;
-	enum vm_passwordlocation password_location;
 	char format[MAX_FORMAT_LENGTH];
 	struct ast_flags global_flags;
 	struct ast_flags password_flags;
+	char default_mailbox_context[AST_MAX_CONTEXT];
 	AST_DECLARE_STRING_FIELDS(
 		AST_STRING_FIELD(zonetag);
 		AST_STRING_FIELD(locale);
@@ -23,23 +25,17 @@
 };
 
 struct ast_msg_mailbox {
+	const struct mailbox_pvt *pvt;
+	char type_name[32];
 	char context[AST_MAX_CONTEXT];		/*!< Mailbox context */
 	char mailbox[AST_MAX_EXTENSION];	/*!< Mailbox id, unique within a context */
 	char language[MAX_LANGUAGE];		/*!< Config: Language setting */
 	int max_messages;					/*!< Maximum number of msgs per folder for this mailbox */
 	int max_deleted_messages;			/*!< Maximum number of deleted msgs saved for this mailbox */
 	int hash_key;
-	enum vm_passwordlocation password_location;           /*!< Storage location of the password */
-	double volgain;						/*!< Volume gain for voicemails sent via email */
-	struct ast_flags flags;				/*!< VM_ flags */
-	AST_DECLARE_STRING_FIELDS(
-		AST_STRING_FIELD(fullname);
-		AST_STRING_FIELD(password);
-		AST_STRING_FIELD(locale);
-		AST_STRING_FIELD(zonetag);
-		AST_STRING_FIELD(timezone);
-	);
+	struct ast_flags flags;				/*!< general flags applicable to the mailbox */
 };
+
 
 
 struct ast_msg_storage_tech {
@@ -60,10 +56,6 @@
 	/* retrieve message */
 };
 
-struct ast_msg_config *ast_get_message_storage_config(void);
-
-struct ast_msg_mailbox *ast_get_message_mailbox(const char * const context, const char * const mailbox);
-
 void ast_unregister_message_storage_tech(const char * const name);
 
 void ast_register_message_storage_tech(struct ast_msg_storage_tech *ms_tech);

Modified: team/mjordan/voicemail_refactor_11_10_19/main/asterisk.c
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/voicemail_refactor_11_10_19/main/asterisk.c?view=diff&rev=349725&r1=349724&r2=349725
==============================================================================
--- team/mjordan/voicemail_refactor_11_10_19/main/asterisk.c (original)
+++ team/mjordan/voicemail_refactor_11_10_19/main/asterisk.c Thu Jan  5 14:58:10 2012
@@ -3782,6 +3782,11 @@
 		exit(1);
 	}
 
+	if (ast_message_storage_init()) {
+		printf("%s", term_quit());
+		exit(1);
+	}
+
 	/* initialize the data retrieval API */
 	if (ast_data_init()) {
 		printf ("%s", term_quit());

Added: team/mjordan/voicemail_refactor_11_10_19/main/message_storage.c
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/voicemail_refactor_11_10_19/main/message_storage.c?view=auto&rev=349725
==============================================================================
--- team/mjordan/voicemail_refactor_11_10_19/main/message_storage.c (added)
+++ team/mjordan/voicemail_refactor_11_10_19/main/message_storage.c Thu Jan  5 14:58:10 2012
@@ -1,0 +1,80 @@
+/*
+ * res_message_storage.c
+ *
+ *  Created on: Oct 30, 2011
+ *      Author: mjordan
+ */
+
+#include "asterisk.h"
+#include "asterisk/message_storage.h"
+
+static struct ao2_container *msg_storage_techs;
+
+#define MSG_STORAGE_TECH_BUCKETS 19
+
+void ast_register_message_storage_tech(struct ast_msg_storage_tech *ms_tech)
+{
+	struct ao2_iterator it_techs;
+	struct ast_msg_storage_tech *it_tech = NULL;
+
+	if (!ms_tech) {
+		return;
+	}
+
+	/* Add the tech if it hasn't already been added */
+	if ((it_tech = ast_get_message_storage_tech(ms_tech->name))) {
+		ast_log(AST_LOG_WARNING, "Message storage technology %s already registered\n", ms_tech->name);
+		ao2_ref(it_tech, -1);
+	} else {
+		ao2_link(msg_storage_techs, ms_tech);
+	}
+	ao2_ref(ms_tech, -1);
+}
+
+void ast_unregister_message_storage_tech(const char * const name)
+{
+	struct ast_msg_storage_tech tech_temp = { .name = name, };
+	struct ast_msg_storage_tech *ms_tech;
+
+	if (ast_strlen_zero(name)) {
+		return;
+	}
+
+	if ((ms_tech = ao2_find(msg_storage_techs, tech_temp, OBJ_POINTER))) {
+		ao2_ref(ms_tech, -1);
+		ao2_unlink(msg_storage_techs, ms_tech);
+	}
+}
+
+struct ast_msg_storage_tech *ast_get_message_storage_tech(const char * const name)
+{
+	struct ast_msg_storage_tech tech_temp = { .name = name, };
+	struct ast_msg_storage_tech *ms_tech;
+
+	ms_tech = ao2_find(msg_storage_techs, tech_temp, OBJ_POINTER);
+
+	return ms_tech;
+}
+
+static int message_storage_hash_fn(const void *obj, const int flags)
+{
+	const struct ast_message_storage_tech *ms_tech = obj;
+	return ast_str_case_hash(ms_tech->name);
+}
+
+static int message_storage_cmp_fn(void *obj, void *arg, int flags)
+{
+	const struct ast_message_storage_tech *ms_tech_left = obj;
+	const struct ast_message_storage_tech *ms_tech_right = arg;
+	return !strcasecmp(ms_tech_left->name, ms_tech_right->name) ? CMP_MATCH | CMP_STOP: 0;
+}
+
+int ast_message_storage_init(void)
+{
+	if (!(msg_storage_techs = ao2_container_alloc(MSG_STORAGE_TECH_BUCKETS, message_storage_hash_fn, message_storage_cmp_fn))) {
+		ast_log(LOG_ERROR, "Unable to allocate message storage technology container\n");
+		return 1;
+	}
+
+	return 0;
+}

Propchange: team/mjordan/voicemail_refactor_11_10_19/main/message_storage.c
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: team/mjordan/voicemail_refactor_11_10_19/main/message_storage.c
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Propchange: team/mjordan/voicemail_refactor_11_10_19/main/message_storage.c
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Copied: team/mjordan/voicemail_refactor_11_10_19/res/res_message_file.c (from r348361, team/mjordan/voicemail_refactor_11_10_19/res/res_message_storage.c)
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/voicemail_refactor_11_10_19/res/res_message_file.c?view=diff&rev=349725&p1=team/mjordan/voicemail_refactor_11_10_19/res/res_message_storage.c&r1=348361&p2=team/mjordan/voicemail_refactor_11_10_19/res/res_message_file.c&r2=349725
==============================================================================
--- team/mjordan/voicemail_refactor_11_10_19/res/res_message_storage.c (original)
+++ team/mjordan/voicemail_refactor_11_10_19/res/res_message_file.c Thu Jan  5 14:58:10 2012
@@ -9,74 +9,230 @@
 #include "asterisk/module.h"
 #include "asterisk/message_storage.h"
 
-static struct ao2_container *msg_storage_techs;
-
-#define MSG_STORAGE_TECH_BUCKETS 19
-
-void ast_register_message_storage_tech(struct ast_msg_storage_tech *ms_tech)
-{
-	struct ao2_iterator it_techs;
-	struct ast_msg_storage_tech *tech_current = NULL;
-
-	if (!ms_tech) {
+/*! \internal \brief The default format for sound files to be saved as */
+static const char *default_format_string = "wav";
+
+/*! \internal \brief The default context to find mailboxes in users.conf */
+static const char *default_mailbox_context = "default";
+
+/*! \internal \brief The default limit to the maximum number of messages that can be stored per folder */
+static const unsigned int default_max_messages_limit = 9999;
+
+/*! \internal \brief The default maximum number of messages that can be stored per folder */
+static const unsigned int default_max_messages = 100;
+
+/*! \internal \brief The base directory for voicemail user's files */
+static char voicemail_spool_directory[PATH_MAX];
+
+/* \internal \brief The message storage configuration object
+ * \note Methods should *not* reference this object directly, but instead should
+ * get a reference from it through file_get_message_storage_config
+ */
+static struct ast_msg_config *config;
+
+/*! \internal \brief The mutex that protects access to the imap config object */
+AST_MUTEX_DEFINE_STATIC(config_lock);
+
+/* \internal \brief The mailboxes */
+static struct ao2_container *mailboxes;
+
+static struct ast_msg_storage_tech file_message_storage_tech = {
+		.name = "file",
+		.load_config = file_load_config,
+		.load_mailboxes = file_load_mailboxes,
+		.get_config = file_get_message_storage_config,
+		.get_mailbox = file_get_message_mailbox,
+};
+
+/*! \internal \brief Create a new mailbox
+ * \param context, the context the mailbox resides in
+ * \param mailbox, the mailbox name
+ */
+static struct ast_msg_mailbox *mailbox_new(const char *context, const char *mailbox)
+{
+	struct ast_msg_mailbox *mbox = NULL;
+	char mailbox_unique_name[AST_MAX_CONTEXT + AST_MAX_EXTENSION + 1];
+
+	if ((mbox = ao2_alloc(sizeof(*mbox), mailbox_destroy))) {
+		if (ast_string_field_init(mbox, 256)) {
+			ao2_ref(mbox, -1);
+			mbox = NULL;
+		} else {
+			/* A mailbox is uniquely defined by the context / mailbox pair.  Set these
+			 * values on creation and create the hash key for the mailbox
+			 */
+			ast_string_field_set(mbox, context, context);
+			ast_string_field_set(mbox, mailbox, mailbox);
+			strcpy(mailbox_unique_name, context);
+			strcat(mailbox_unique_name, mailbox);
+			mbox->hash_key = ast_str_case_hash(mailbox_unique_name);
+		}
+	}
+
+	return mbox;
+}
+
+/*! \internal \brief Dispose of a mailbox */
+static void mailbox_destroy(void *obj)
+{
+	struct ast_msg_mailbox *mbox = obj;
+
+	if (!mbox) {
 		return;
 	}
-
-	/* Add the tech if it hasn't already been added */
-	ao2_lock(msg_storage_techs);
-	it_techs = ao2_iterator_init(msg_storage_techs, 0);
-	while ((tech_current = ao2_iterator_next(&it_techs))) {
-		if (!strncmp(ms_tech->name, tech_current->name, sizeof(ms_tech->name))) {
-			ast_log(AST_LOG_WARNING, "Message storage technology %s already registered\n", ms_tech->name)
-			ao2_ref(tech_current, -1);
-			ao2_iterator_destroy(&it_techs);
-			ao2_unlock(msg_storage_techs);
-			return;
+	ast_string_field_free_memory(mbox);
+}
+
+/*! \internal \brief Hash function used for mailboxes */
+static int mailbox_hash_fn(const void *obj, const int flags)
+{
+	const struct ast_msg_mailbox *mbox = obj;
+	return mbox->hash_key;
+}
+
+/*! \internal \brief Comparison function used for mailboxes */
+static int mailbox_cmp_fn(void *obj, void *arg, int flags)
+{
+	const struct ast_msg_mailbox *mbox_left = obj;
+	const struct ast_msg_mailbox *mbox_right = arg;
+
+	if (mbox_left->hash_key == mbox_right->hash_key) {
+		return CMP_MATCH | CMP_STOP;
+	} else {
+		return 0;
+	}
+}
+
+/*! \internal \brief Create a new file configuration object */
+static struct ast_msg_config *config_new(void)
+{
+	struct ast_msg_config *fconfig = NULL;
+
+	if ((fconfig = ao2_alloc(sizeof(*fconfig), config_destroy))) {
+		if (ast_string_field_init(fconfig, 256)) {
+			ao2_ref(fconfig, -1);
+			fconfig = NULL;
 		}
-		ao2_ref(tech_current, -1);
-	}
-	ao2_iterator_destroy(&it_techs);
-	ao2_unlock(msg_storage_techs);
-
-	ao2_link(msg_storage_techs, ms_tech);
-}
-
-void ast_unregister_message_storage_tech(const char * const name)
-{
-	struct ast_msg_storage_tech tech_temp = { .name = name, };
-	struct ast_msg_storage_tech *ms_tech;
-
-	if (ast_strlen_zero(name)) {
+	}
+
+	return fconfig;
+}
+
+/*! \internal \brief Dispose of an IMAP configuration object */
+static void config_destroy(void *obj)
+{
+	struct ast_msg_config *fconfig = obj;
+
+	if (!fconfig) {
 		return;
 	}
-
-	if ((ms_tech = ao2_find(msg_storage_techs, tech_temp, OBJ_POINTER))) {
-		ao2_ref(ms_tech, -1);
-		ao2_unlink(msg_storage_techs, ms_tech);
-	}
-}
-
-struct ast_msg_storage_tech *ast_get_message_storage_tech(const char * const name)
-{
-	struct ast_msg_storage_tech tech_temp = { .name = name, };
-	struct ast_msg_storage_tech *ms_tech;
-
-	ms_tech = ao2_find(msg_storage_techs, tech_temp, OBJ_POINTER);
-
-	return ms_tech;
-}
-
-static int message_storage_hash_fn(const void *obj, const int flags)
-{
-	const struct ast_message_storage_tech *ms_tech = obj;
-	return ast_str_case_hash(ms_tech->name);
-}
-
-static int message_storage_cmp_fn(void *obj, void *arg, int flags)
-{
-	const struct ast_message_storage_tech *ms_tech_left = obj;
-	const struct ast_message_storage_tech *ms_tech_right = arg;
-	return !strcasecmp(ms_tech_left->name, ms_tech_right->name) ? CMP_MATCH | CMP_STOP: 0;
+	ast_string_field_free_memory(fconfig);
+}
+
+/*! \internal \brief Obtain the message storage configuration object
+ * \note Methods should use this function to get the configuration.  This method will
+ * increment the reference count on the config object before returning it
+ */
+struct ast_msg_config *file_get_message_storage_config(void)
+{
+	ao2_lock(&config_lock);
+	ao2_ref(config, +1);
+	ao2_unlock(&config_lock);
+	return config;
+}
+
+struct ast_msg_mailbox *file_get_message_mailbox(const char * const context, const char * const mailbox)
+{
+	struct ast_msg_mailbox tmp_mbox;
+	struct ast_msg_mailbox *mbox;
+	char mailbox_unique_name[AST_MAX_CONTEXT + AST_MAX_EXTENSION + 1];
+
+	ast_copy_string(tmp_mbox.context, context, sizeof(tmp_mbox.context));
+	ast_copy_string(tmp_mbox.mailbox, mailbox, sizeof(tmp_mbox.mailbox));
+	ast_copy_string(mailbox_unique_name, context, AST_MAX_CONTEXT);
+	strncat(mailbox_unique_name, mailbox, AST_MAX_EXTENSION);
+	tmp_mbox.hash_key = ast_str_case_hash(mailbox_unique_name);
+
+	mbox = ao2_find(mailboxes, &tmp_mbox, OBJ_POINTER);
+
+	return mbox;
+}
+
+void populate_default_options(struct ast_msg_config *fconfig)
+{
+	strcpy(fconfig->default_mailbox_context, default_mailbox_context);
+	strcpy(fconfig->format, default_format_string);
+	fconfig->max_messages = default_max_messages;
+}
+
+void validate_config(struct ast_msg_config *fconfig)
+{
+	if (fconfig->max_deleted_messages > default_max_messages_limit) {
+		ast_log(AST_LOG_WARNING, "Maximum number of deleted messages saved per mailbox is %d. Cannot accept value backupdeleted=%d\n", default_max_messages_limit, fconfig->max_deleted_messages);
+		fconfig->max_deleted_messages = default_max_messages_limit;
+	}
+	if (fconfig->max_messages > default_max_messages_limit) {
+		ast_log(AST_LOG_WARNING, "Maximum number of messages per folder is %d. Cannot accept value maxmsg=%d\n", default_max_messages_limit, fconfig->max_messages);
+		fconfig->max_messages = default_max_messages_limit;
+	}
+}
+
+int file_load_config(struct ast_config *cfg, int reload)
+{
+	struct ast_variable *var;
+	struct ast_category *cat = ast_category_get(cfg, default_settings_context);
+	struct ast_msg_config *fconfig;
+
+	if (!cat) {
+		ast_log(AST_LOG_ERROR, "No %s category defined in configuration\n", default_settings_context);
+		return 1;
+	}
+
+	if (!(fconfig = config_new())) {
+		ast_log(AST_LOG_ERROR, "Unable to allocate sufficient memory for ast_msg_config object\n");
+		return 1;
+	}
+
+	populate_default_options(fconfig);
+
+	for (var = ast_category_first(cat); var; var = var->next) {
+		if (!strcasecmp(var->name, "userscontext")) {
+			ast_copy_string(fconfig->default_mailbox_context, var->value, sizeof(fconfig->default_mailbox_context));
+		} else if (!strcasecmp(var->name, "maxmsg")) {
+			if (sscanf(var->value, "%30ud", &(fconfig->max_messages)) < 1) {
+				ast_log(AST_LOG_WARNING, "Failed to parse %s with value %s into parameter max_messages\n", var->name, var->value);
+			}
+		} else if (!strcasecmp(var->name, "backupdeleted")) {
+			/* Field can be either an absolute number of messages to delete, or a 'yes' / 'no' value */
+			if (sscanf(var->value, "%30ud", &(fconfig->max_deleted_messages)) < 1) {
+				if (ast_true(var->value)) {
+					fconfig->max_deleted_messages = default_max_messages;
+				} else {
+					fconfig->max_deleted_messages = 0;
+				}
+			}
+		} else if (!strcasecmp(var->name, "searchcontexts")) {
+			ast_set2_flag(&(fconfig->global_flags), ast_true(var->value), VM_SEARCH);
+		} else if (!strcasecmp(var->name, "format")) {
+			ast_copy_string(vmcfg->format, var->value, sizeof(vmcfg->format));
+		}
+	}
+
+	validate_config(fconfig);
+
+	ast_mutex_lock(&config_lock);
+	if (!config) {
+		ao2_ref(config, -1);
+	}
+	config = fconfig;
+	ast_mutex_unlock(&config_lock);
+
+	return 0;
+}
+
+int file_load_mailboxes(struct ast_config *mcfg, int reload, int by_variable)
+{
+	return 0;
 }
 
 static int reload(void)
@@ -88,20 +244,26 @@
 /* If I were to allow unloading it would look something like this */
 static int unload_module(void)
 {
-	ao2_ref(msg_storage_techs, -1);
+	ast_unregister_message_storage_tech(&file_message_storage_tech);
+
+	if (config) {
+		ao2_ref(config, -1);
+	}
+	ao2_ref(mailboxes, -1);
 	return 0;
 }
 
 static int load_module(void)
 {
-	if (!(msg_storage_techs = ao2_container_alloc(MSG_STORAGE_TECH_BUCKETS, message_storage_hash_fn, message_storage_cmp_fn))) {
-		ast_log(LOG_ERROR, "Unable to allocate message storage technology container\n");
+	if (!(mailboxes = ao2_container_alloc(mailbox_hash_fn, mailbox_cmp_fn))) {
+		ast_log(AST_LOG_ERROR, "Unable to allocate mailbox container\n");
 		return AST_MODULE_LOAD_FAILURE;
 	}
 
-	/* Since other modules depend on this, disable unloading */
-	/* TODO: not sure about this either, since it is sort of a memory leak */
-	ast_module_ref(ast_module_info->self);
+	/* TODO: make this part of the config? */
+	snprintf(voicemail_spool_directory, sizeof(voicemail_spool_directory), "%s/voicemail/", ast_config_AST_SPOOL_DIR);
+
+	ast_register_message_storage_tech(&file_message_storage_tech);
 
 	return AST_MODULE_LOAD_SUCCESS;
 }

Modified: team/mjordan/voicemail_refactor_11_10_19/res/res_message_imap.c
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/voicemail_refactor_11_10_19/res/res_message_imap.c?view=diff&rev=349725&r1=349724&r2=349725
==============================================================================
--- team/mjordan/voicemail_refactor_11_10_19/res/res_message_imap.c (original)
+++ team/mjordan/voicemail_refactor_11_10_19/res/res_message_imap.c Thu Jan  5 14:58:10 2012
@@ -19,7 +19,7 @@
 	AST_DECLARE_STRING_FIELDS(
 		AST_STRING_FIELD(server);
 		AST_STRING_FIELD(port);
-		AST_STRING_FIELD(flags);
+		AST_STRING_FIELD(server_flags);
 		AST_STRING_FIELD(folder);
 		AST_STRING_FIELD(parent_folder);
 		AST_STRING_FIELD(greeting_folder);
@@ -31,14 +31,18 @@
 /*! \internal \brief The IMAP mailbox definition */
 struct imap_mailbox {
 	struct ast_msg_mailbox *msg_mailbox;		/*!< The inherited message mailbox information */
+	unsigned int expunge_on_hangup;
+	unsigned int imap_greetings;
 	AST_DECLARE_STRING_FIELDS(
 		AST_STRING_FIELD(user);					/*!< IMAP server login */
 		AST_STRING_FIELD(password);				/*!< IMAP server password if auth_password not defined */
 		AST_STRING_FIELD(default_folder);		/*!< IMAP message folder */
+		AST_STRING_FIELD(parent_folder);
+		AST_STRING_FIELD(greeting_folder);
 		AST_STRING_FIELD(shared_id);			/*!< Shared mailbox ID to use rather than the dialed one */
 		AST_STRING_FIELD(server);
 		AST_STRING_FIELD(port);
-		AST_STRING_FIELD(flags);
+		AST_STRING_FIELD(server_flags);
 	);
 };
 
@@ -63,6 +67,11 @@
 
 /*! \internal \brief Context that contains timezone information; skipped for mailboxes */
 static const char *default_timezone_context = "zonemessages";
+
+/*! \internal \brief Default context that users defined from their own context are placed under,
+ * if no default context is defined in the base message layer
+ */
+static const char *default_mailbox_context = "default"
 
 /* \internal \brief The IMAP storage layer configuration object
  * \note Methods should *not* reference this object directly, but instead should
@@ -83,8 +92,8 @@
 		.name = "IMAP",
 		.load_config = imap_load_config,
 		.load_mailboxes = imap_load_mailboxes,
-		.get_config = ast_get_message_storage_config,
-		.get_mailbox = ast_get_message_mailbox,
+		.get_config = base_tech->get_config,
+		.get_mailbox = base_tech->get_mailbox,
 };
 
 /*! \internal \brief Create a new IMAP mailbox
@@ -134,6 +143,26 @@
 	ast_string_field_free_memory(imbox);
 }
 
+/*! \internal \brief Hash function used for IMAP mailboxes */
+static int imap_mailbox_hash_fn(const void *obj, const int flags)
+{
+	const struct imap_mailbox *imbox = obj;
+	return imbox->msg_mailbox->hash_key;
+}
+
+/*! \internal \brief Comparison function used for IMAP mailboxes */
+static int imap_mailbox_cmp_fn(void *obj, void *arg, int flags)
+{
+	const struct imap_mailbox *imbox_left = obj;
+	const struct imap_mailbox *imbox_right = arg;
+
+	if (imbox_left->msg_mailbox->hash_key == imbox_right->msg_mailbox->hash_key) {
+		return CMP_MATCH | CMP_STOP;
+	} else {
+		return 0;
+	}
+}
+
 /*! \internal \brief Create a new IMAP configuration object
  * \note The base message storage technology must first have loaded its configuration
  * before calling this method.
@@ -231,7 +260,7 @@
 		} else if (!strcasecmp(var->name, "imapport")) {
 			ast_string_field_set(iconfig, port, var->value);
 		} else if (!strcasecmp(var->name, "imapflags")) {
-			ast_string_field_set(iconfig, flags, var->value);
+			ast_string_field_set(iconfig, server_flags, var->value);
 		} else if (!strcasecmp(var->name, "authuser")) {
 			ast_string_field_set(iconfig, auth_user, var->value);
 		} else if (!strcasecmp(var->name, "authpassword")) {
@@ -298,16 +327,60 @@
 	return (struct ast_msg_config *)config;
 }
 
-static int valid_user(struct imap_user *imu)
-{
-	return 0;
-}
-
 static void populate_default_mailbox_options(const struct imap_config *iconfig, struct imap_mailbox *imbox)
 {
-
-}
-
+	/* Apply the general settings to the mailbox */
+	ast_string_field_set(imbox, password, iconfig->auth_password);
+	ast_string_field_set(imbox, user, iconfig->auth_user);
+	imbox->expunge_on_hangup = iconfig->expunge_on_hangup;
+	ast_string_field_set(imbox, default_folder, iconfig->folder);
+	ast_string_field_set(imbox, greeting_folder, iconfig->greeting_folder);
+	imbox->imap_greetings = iconfig->imap_greetings;
+	ast_string_field_set(imbox, parent_folder, iconfig->parent_folder);
+	ast_string_field_set(imbox, port, iconfig->port);
+	ast_string_field_set(imbox, server, iconfig->server);
+	ast_string_field_set(imbox, server_flags, iconfig->server_flags);
+}
+
+static void apply_mailbox_option(struct imap_mailbox *imbox, const char *key, const char *value)
+{
+	if (!strcasecmp(key, "imapserver")) {
+		ast_string_field_set(imbox, server, value);
+	} else if (!strcasecmp(key, "imapport")) {
+		ast_string_field_set(imbox, port, value);
+	} else if (!strcasecmp(key, "imapflags")) {
+		ast_string_field_set(imbox, server_flags, value);
+	} else if (!strcasecmp(key, "authuser")) {
+		ast_string_field_set(imbox, auth_user, value);
+	} else if (!strcasecmp(key, "authpassword")) {
+		ast_string_field_set(imbox, password, value);
+	} else if (!strcasecmp(key, "expungeonhangup")) {
+		if (ast_false(value)) {
+			imbox->expunge_on_hangup = 0;
+		} else {
+			imbox->expunge_on_hangup = 1;
+		}
+	} else if (!strcasecmp(key, "imapfolder")) {
+		ast_string_field_set(imbox, default_folder, value);
+	} else if (!strcasecmp(key, "imapparentfolder")) {
+		ast_string_field_set(imbox, parent_folder, value);
+	} else if (!strcasecmp(key, "greetingfolder") || !strcasecmp(key, "greetingsfolder")) {
+		ast_string_field_set(imbox, greeting_folder, value);
+	} else if (!strcasecmp(key, "imapgreetings")) {
+		if (ast_true(value)) {
+			imbox->imap_greetings = 1;
+		} else {
+			imbox->imap_greetings = 0;
+		}
+	}
+}
+
+/*! \internal \brief Create a mailbox from a single Asterisk configuration variable
+ * \param iconfig, the global configuration object
+ * \param cat_name, the category name (interpeted as the context)
+ * \param var, the Asterisk variable containing the mailbox info
+ * \returns A configured IMAP mailbox, or NULL on error
+ */
 static struct imap_mailbox *create_mailbox_from_variable(const struct imap_config *iconfig, const char *cat_name, struct ast_variable *var)
 {
 	char *values;
@@ -321,44 +394,74 @@
 		ast_log(AST_LOG_ERROR, "Failed to create IMAP mailbox for %s/%s\n", cat_name, var->name);
 		return NULL;
 	}
-
-	ast_copy_string(vmu->mailbox, var->name, sizeof(vmu->mailbox));
-	ast_copy_string(vmu->context, context, sizeof(vmu->context));
-
+	populate_default_mailbox_options(iconfig, imbox);
+
+	/* Set the basic values - note that this will override what was set
+	 * for the existing mailbox, but in most cases would be identical.  If
+	 * we don't want to repeat ourselves, we could simply skip the first four
+	 * values
+	 */
 	values = ast_strdup(var->value);
-
 	if ((value = strsep(&values, ","))) {
-		ast_string_field_set(vmu, password, value);
+		ast_string_field_set(imbox->msg_mailbox, password, value);
 	}
 	if (values && (value = strsep(&values, ","))) {
-		ast_string_field_set(vmu, fullname, value);
+		ast_string_field_set(imbox->msg_mailbox, fullname, value);
 	}
 	if (values && (value = strsep(&values, ","))) {
-		ast_string_field_set(vmu, email_address, value);
+		ast_string_field_set(imbox->msg_mailbox, email_address, value);
 	}
 	if (values && (value = strsep(&values, ","))) {
-		ast_string_field_set(vmu, pager_address, value);
+		ast_string_field_set(imbox->msg_mailbox, pager_address, value);
 	}
 	if (values && (value = strsep(&values, ","))) {
 		options = ast_strdup(value);
 		while ((option_value = strsep(&options, "|"))) {
 			if ((option_key = strsep(&option_value, "=")) && option_value) {
-				apply_user_option(vmcfg, vmu, option_key, option_value);
-			}
-		}
-		if (options) {
-			ast_free(options);
-		}
-	}
-
-	if (values) {
-		ast_free(values);
-	}
-}
-
-static void create_mailbox_from_category(const struct imap_config *iconfig, struct imap_user *imu, struct ast_config *ucfg, const char *cat_name)
-{
-
+				apply_mailbox_option(imbox, option_key, option_value);
+			}
+		}
+	}
+
+	return imbox;
+}
+
+static struct imap_mailbox *create_mailbox_from_category(const struct imap_config *iconfig, struct ast_config *mcfg, const char *cat_name)
+{
+	struct ast_variable *var;
+	struct imap_mailbox *imbox;
+	const char *context;
+
+	/* If the mailbox config specifies a context, use that.  Otherwise, use the default one
+	 * in the base message tech, or lastly, the one defined here
+	 */
+	context = ast_variable_retrieve(mcfg, cat, "context");
+	if ((!imbox = imap_mailbox_new(S_OR(context, S_OR(iconfig->msg_config->default_mailbox_context, default_mailbox_context)), cat_name))) {
+		ast_log(AST_LOG_ERROR, "Failed to create IMAP mailbox for %s/%s\n", S_OR(context, S_OR(iconfig->msg_config->default_mailbox_context, default_mailbox_context)), cat_name);
+		return NULL;
+	}
+	populate_default_mailbox_options(iconfig, imbox);
+
+	for (var = ast_variable_browse(mcfg, cat); var; var = var->next) {
+		if (!strcasecmp(var->name, "vmsecret")) {
+			ast_string_field_set(imbox->msg_mailbox, password, var->value);
+		} else if (!strcasecmp(var->name, "secret") || !strcasecmp(var->name, "password")) {
+			/* don't overwrite vmsecret if it was already applied */
+			if (ast_strlen_zero(imbox->msg_mailbox->password)) {
+				ast_string_field_set(imbox->msg_mailbox, password, var->value);
+			}
+		} else if (!strcasecmp(var->name, "pager")) {
+			ast_string_field_set(imbox->msg_mailbox, pager_address, var->value);
+		} else if (!strcasecmp(var->name, "email")) {
+			ast_string_field_set(imbox->msg_mailbox, email_address, var->value);
+		} else if (!strcasecmp(var->name, "fullname")) {
+			ast_string_field_set(imbox->msg_mailbox, fullname, var->value);
+		} else {
+			apply_mailbox_option(imbox, var->name, var->value);
+		}
+	}
+
+	return imbox;
 }
 
 /*! \internal \brief Remove all of the mailboxes from a container
@@ -421,9 +524,7 @@
 			}
 		}
 
-		if (!validate_user(imbox)) {
-			ao2_link(temp_container, imbox);
-		}
+		ao2_link(temp_container, imbox);
 		ao2_ref(imbox, -1);
 		imbox = NULL;
 	}
@@ -448,7 +549,9 @@
 {
 	ast_unregister_message_storage_tech(imap_message_storage_tech.name);
 
-	ao2_ref(config, -1);
+	if (config) {
+		ao2_ref(config, -1);
+	}
 	/* TODO: This may not be necessary */
 	ao2_lock(imap_mailboxes);
 	imap_remove_mailboxes(imap_mailboxes);
@@ -460,21 +563,13 @@
 
 static int load_module(void)
 {
-	/* TODO: base? */
-	if (!(base_tech = ast_get_message_storage_tech("base"))) {
+	if (!(base_tech = ast_get_message_storage_tech("file"))) {
 		ast_log(AST_LOG_ERROR, "Unable to obtain base message technology\n");
 		return AST_MODULE_LOAD_FAILURE;
 	}
 
-	if (!(imap_mailboxes = ao2_container_alloc())) {
-		ast_log(AST_LOG_ERROR, "Unable to allocate IMAP users container\n");
-		return AST_MODULE_LOAD_FAILURE;
-	}
-
-	/* Since we have good config objects, attempt to create a new IMAP config from them */
-	if (!(config = imap_config_new())) {
-		ast_log(AST_LOG_ERROR, "Failed to allocate memory for new IMAP config object\n");
-		ao2_ref(imap_users, -1);
+	if (!(imap_mailboxes = ao2_container_alloc(imap_mailbox_hash_fn, imap_mailbox_cmp_fn))) {
+		ast_log(AST_LOG_ERROR, "Unable to allocate IMAP mailbox container\n");
 		return AST_MODULE_LOAD_FAILURE;
 	}
 




More information about the asterisk-commits mailing list