diff --git a/apps/app_directory.c b/apps/app_directory.c
index ce01bc83b80ef93bcc317e5cd93a0804805da57b..b26a09cd9777709ec837d8c4056a2fc6413f3681 100644
--- a/apps/app_directory.c
+++ b/apps/app_directory.c
@@ -87,6 +87,12 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 						argument will be used for the number of characters the user should enter.</para>
 						<argument name="n" required="true" />
 					</option>
+					<option name="a">
+						<para>Allow the caller to additionally enter an alias for a user in the
+						directory.  This option must be specified in addition to the
+						<literal>f</literal>, <literal>l</literal>, or <literal>b</literal>
+						option.</para>
+					</option>
 					<option name="m">
 						<para>Instead of reading each name sequentially and asking for
 						confirmation, create a menu of up to 8 names.</para>
@@ -135,6 +141,7 @@ enum {
 	OPT_LISTBYEITHER =    OPT_LISTBYFIRSTNAME | OPT_LISTBYLASTNAME,
 	OPT_PAUSE =           (1 << 5),
 	OPT_NOANSWER =        (1 << 6),
+	OPT_ALIAS =           (1 << 7),
 };
 
 enum {
@@ -164,6 +171,7 @@ AST_APP_OPTIONS(directory_app_options, {
 	AST_APP_OPTION('v', OPT_FROMVOICEMAIL),
 	AST_APP_OPTION('m', OPT_SELECTFROMMENU),
 	AST_APP_OPTION('n', OPT_NOANSWER),
+	AST_APP_OPTION('a', OPT_ALIAS),
 });
 
 static int compare(const char *text, const char *template)
@@ -427,6 +435,8 @@ static int select_item_menu(struct ast_channel *chan, struct directory_item **it
 	return 0;
 }
 
+AST_THREADSTORAGE(commonbuf);
+
 static struct ast_config *realtime_directory(char *context)
 {
 	struct ast_config *cfg;
@@ -436,8 +446,12 @@ static struct ast_config *realtime_directory(char *context)
 	char *mailbox;
 	const char *fullname;
 	const char *hidefromdir, *searchcontexts = NULL;
-	char tmp[100];
 	struct ast_flags config_flags = { 0 };
+	struct ast_str *tmp = ast_str_thread_get(&commonbuf, 100);
+
+	if (!tmp) {
+		return NULL;
+	}
 
 	/* Load flat file config. */
 	cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags);
@@ -472,6 +486,7 @@ static struct ast_config *realtime_directory(char *context)
 
 	mailbox = NULL;
 	while ( (mailbox = ast_category_browse(rtdata, mailbox)) ) {
+		struct ast_variable *alias;
 		const char *ctx = ast_variable_retrieve(rtdata, mailbox, "context");
 
 		fullname = ast_variable_retrieve(rtdata, mailbox, "fullname");
@@ -480,7 +495,14 @@ static struct ast_config *realtime_directory(char *context)
 			/* Skip hidden */
 			continue;
 		}
-		snprintf(tmp, sizeof(tmp), "no-password,%s", S_OR(fullname, ""));
+		ast_str_set(&tmp, 0, "no-password,%s", S_OR(fullname, ""));
+		if (ast_variable_retrieve(rtdata, mailbox, "alias")) {
+			for (alias = ast_variable_browse(rtdata, mailbox); alias; alias = alias->next) {
+				if (!strcasecmp(alias->name, "alias")) {
+					ast_str_append(&tmp, 0, "|alias=%s", alias->value);
+				}
+			}
+		}
 
 		/* Does the context exist within the config file? If not, make one */
 		if (!(cat = ast_category_get(cfg, ctx))) {
@@ -495,7 +517,7 @@ static struct ast_config *realtime_directory(char *context)
 			ast_category_append(cfg, cat);
 		}
 
-		if ((var = ast_variable_new(mailbox, tmp, ""))) {
+		if ((var = ast_variable_new(mailbox, ast_str_buffer(tmp), ""))) {
 			ast_variable_append(cat, var);
 		} else {
 			ast_log(LOG_WARNING, "Out of memory adding mailbox '%s'\n", mailbox);
@@ -556,20 +578,26 @@ typedef AST_LIST_HEAD_NOLOCK(, directory_item) itemlist;
 static int search_directory_sub(const char *context, struct ast_config *vmcfg, struct ast_config *ucfg, const char *ext, struct ast_flags flags, itemlist *alist)
 {
 	struct ast_variable *v;
-	char buf[AST_MAX_EXTENSION + 1], *pos, *bufptr, *cat;
+	struct ast_str *buf = ast_str_thread_get(&commonbuf, 100);
+	char *pos, *bufptr, *cat, *alias;
 	struct directory_item *item;
 	int res;
 
+	if (!buf) {
+		return -1;
+	}
+
 	ast_debug(2, "Pattern: %s\n", ext);
 
 	for (v = ast_variable_browse(vmcfg, context); v; v = v->next) {
 
 		/* Ignore hidden */
-		if (strcasestr(v->value, "hidefromdir=yes"))
+		if (strcasestr(v->value, "hidefromdir=yes")) {
 			continue;
+		}
 
-		ast_copy_string(buf, v->value, sizeof(buf));
-		bufptr = buf;
+		ast_str_set(&buf, 0, "%s", v->value);
+		bufptr = ast_str_buffer(buf);
 
 		/* password,Full Name,email,pager,options */
 		strsep(&bufptr, ",");
@@ -587,11 +615,23 @@ static int search_directory_sub(const char *context, struct ast_config *vmcfg, s
 		if (!res && ast_test_flag(&flags, OPT_LISTBYFIRSTNAME)) {
 			res = check_match(&item, context, pos, v->name, ext, 1 /* use_first_name */);
 		}
+		if (!res && ast_test_flag(&flags, OPT_ALIAS) && (alias = strcasestr(bufptr, "alias="))) {
+			char *a;
+			ast_debug(1, "Found alias: %s\n", alias);
+			while ((a = strsep(&alias, "|"))) {
+				if (!strncasecmp(a, "alias=", 6)) {
+					if ((res = check_match(&item, context, a + 6, v->name, ext, 1))) {
+						break;
+					}
+				}
+			}
+		}
 
-		if (!res)
+		if (!res) {
 			continue;
-		else if (res < 0)
+		} else if (res < 0) {
 			return -1;
+		}
 
 		AST_LIST_INSERT_TAIL(alist, item, entry);
 	}
@@ -599,15 +639,18 @@ static int search_directory_sub(const char *context, struct ast_config *vmcfg, s
 	if (ucfg) {
 		for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
 			const char *position;
-			if (!strcasecmp(cat, "general"))
+
+			if (!strcasecmp(cat, "general")) {
 				continue;
-			if (!ast_true(ast_config_option(ucfg, cat, "hasdirectory")))
+			}
+			if (!ast_true(ast_config_option(ucfg, cat, "hasdirectory"))) {
 				continue;
+			}
 
 			/* Find all candidate extensions */
-			position = ast_variable_retrieve(ucfg, cat, "fullname");
-			if (!position)
+			if (!(position = ast_variable_retrieve(ucfg, cat, "fullname"))) {
 				continue;
+			}
 
 			res = 0;
 			if (ast_test_flag(&flags, OPT_LISTBYLASTNAME)) {
@@ -616,11 +659,20 @@ static int search_directory_sub(const char *context, struct ast_config *vmcfg, s
 			if (!res && ast_test_flag(&flags, OPT_LISTBYFIRSTNAME)) {
 				res = check_match(&item, context, position, cat, ext, 1 /* use_first_name */);
 			}
+			if (!res && ast_test_flag(&flags, OPT_ALIAS)) {
+				struct ast_variable *alias;
+				for (alias = ast_variable_browse(ucfg, cat); alias; alias = alias->next) {
+					if (!strcasecmp(v->name, "alias") && (res = check_match(&item, context, v->value, cat, ext, 1))) {
+						break;
+					}
+				}
+			}
 
-			if (!res)
+			if (!res) {
 				continue;
-			else if (res < 0)
+			} else if (res < 0) {
 				return -1;
+			}
 
 			AST_LIST_INSERT_TAIL(alist, item, entry);
 		}
diff --git a/configs/voicemail.conf.sample b/configs/voicemail.conf.sample
index a92e7a1c5b88f78617bb980e01df1d566a4d861e..b776fd60d9ae4f474e244b824ee8ebaeb8da74a5 100644
--- a/configs/voicemail.conf.sample
+++ b/configs/voicemail.conf.sample
@@ -282,6 +282,10 @@ sendvoicemail=yes ; Allow the user to compose and send a voicemail while inside
 			;     This is intended for use with users who wish to receive their
 			;     voicemail ONLY by email. Note:  "deletevoicemail" is provided as an
 			;     equivalent option for Realtime configuration.
+; alias=Bongo       ; Use this additional string for comparison while looking
+                    ; for a match in the Directory application.  This option
+                    ; may be specified multiple times to specify additional
+                    ; strings [per-mailbox only]
 ; volgain=0.0		; Emails bearing the voicemail may arrive in a volume too
 			;     quiet to be heard.  This parameter allows you to specify how
 			;     much gain to add to the message when sending a voicemail.
diff --git a/contrib/realtime/mysql/voicemail.sql b/contrib/realtime/mysql/voicemail.sql
index bd924f4265f9680fd96077f7e72c164a80651e25..62c7fbb6ae24d1aa648a9e3dc00a15b7e0545b9b 100644
--- a/contrib/realtime/mysql/voicemail.sql
+++ b/contrib/realtime/mysql/voicemail.sql
@@ -10,6 +10,8 @@ CREATE TABLE voicemail (
 	password CHAR(80) NOT NULL,
 	-- Used in email and for Directory app
 	fullname CHAR(80),
+    -- Used for Directory app
+	alias CHAR(80),
 	-- Email address (will get sound file if attach=yes)
 	email CHAR(80),
 	-- Email address (won't get sound file)
diff --git a/res/res_xmpp.c b/res/res_xmpp.c
index 77369c487a6495e5071ad2b19f513b4820ff4207..1e130e77152574d2b10f4c5676491ed3fbf027a4 100644
--- a/res/res_xmpp.c
+++ b/res/res_xmpp.c
@@ -928,7 +928,7 @@ static iks* xmpp_pubsub_iq_create(struct ast_xmpp_client *client, const char *ty
  * \return iks *
  */
 static iks* xmpp_pubsub_build_publish_skeleton(struct ast_xmpp_client *client, const char *node,
-					       const char *event_type)
+					       const char *event_type, unsigned int cachable)
 {
 	RAII_VAR(struct xmpp_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup);
 	iks *request, *pubsub, *publish, *item;
@@ -944,6 +944,22 @@ static iks* xmpp_pubsub_build_publish_skeleton(struct ast_xmpp_client *client, c
 	item = iks_insert(publish, "item");
 	iks_insert_attrib(item, "id", node);
 
+	if (cachable == AST_DEVSTATE_NOT_CACHABLE) {
+		iks *options, *x, *field_form_type, *field_persist;
+
+		options = iks_insert(pubsub, "publish-options");
+		x = iks_insert(options, "x");
+		iks_insert_attrib(x, "xmlns", "jabber:x:data");
+		iks_insert_attrib(x, "type", "submit");
+		field_form_type = iks_insert(x, "field");
+		iks_insert_attrib(field_form_type, "var", "FORM_TYPE");
+		iks_insert_attrib(field_form_type, "type", "hidden");
+		iks_insert_cdata(iks_insert(field_form_type, "value"), "http://jabber.org/protocol/pubsub#publish-options", 0);
+		field_persist = iks_insert(x, "field");
+		iks_insert_attrib(field_persist, "var", "pubsub#persist_items");
+		iks_insert_cdata(iks_insert(field_persist, "value"), "0", 1);
+	}
+
 	return item;
 
 }
@@ -1120,7 +1136,7 @@ static void xmpp_pubsub_publish_mwi(struct ast_xmpp_client *client, const char *
 
 	snprintf(full_mailbox, sizeof(full_mailbox), "%s@%s", mailbox, context);
 
-	if (!(request = xmpp_pubsub_build_publish_skeleton(client, full_mailbox, "message_waiting"))) {
+	if (!(request = xmpp_pubsub_build_publish_skeleton(client, full_mailbox, "message_waiting", AST_DEVSTATE_CACHABLE))) {
 		return;
 	}
 
@@ -1144,13 +1160,13 @@ static void xmpp_pubsub_publish_mwi(struct ast_xmpp_client *client, const char *
  * \return void
  */
 static void xmpp_pubsub_publish_device_state(struct ast_xmpp_client *client, const char *device,
-					     const char *device_state)
+					     const char *device_state, unsigned int cachable)
 {
 	RAII_VAR(struct xmpp_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup);
 	iks *request, *state;
-	char eid_str[20];
+	char eid_str[20], cachable_str[2];
 
-	if (!cfg || !cfg->global || !(request = xmpp_pubsub_build_publish_skeleton(client, device, "device_state"))) {
+	if (!cfg || !cfg->global || !(request = xmpp_pubsub_build_publish_skeleton(client, device, "device_state", cachable))) {
 		return;
 	}
 
@@ -1166,6 +1182,8 @@ static void xmpp_pubsub_publish_device_state(struct ast_xmpp_client *client, con
 	state = iks_insert(request, "state");
 	iks_insert_attrib(state, "xmlns", "http://asterisk.org");
 	iks_insert_attrib(state, "eid", eid_str);
+	snprintf(cachable_str, sizeof(cachable_str), "%u", cachable);
+	iks_insert_attrib(state, "cachable", cachable_str);
 	iks_insert_cdata(state, device_state, strlen(device_state));
 	ast_xmpp_client_send(client, iks_root(request));
 	iks_delete(request);
@@ -1208,6 +1226,7 @@ static void xmpp_pubsub_devstate_cb(const struct ast_event *ast_event, void *dat
 {
 	struct ast_xmpp_client *client = data;
 	const char *device, *device_state;
+	unsigned int cachable;
 
 	if (ast_eid_cmp(&ast_eid_default, ast_event_get_ie_raw(ast_event, AST_EVENT_IE_EID))) {
 		/* If the event didn't originate from this server, don't send it back out. */
@@ -1217,7 +1236,8 @@ static void xmpp_pubsub_devstate_cb(const struct ast_event *ast_event, void *dat
 
 	device = ast_event_get_ie_str(ast_event, AST_EVENT_IE_DEVICE);
 	device_state = ast_devstate_str(ast_event_get_ie_uint(ast_event, AST_EVENT_IE_STATE));
-	xmpp_pubsub_publish_device_state(client, device, device_state);
+	cachable = ast_event_get_ie_uint(ast_event, AST_EVENT_IE_CACHABLE);
+	xmpp_pubsub_publish_device_state(client, device, device_state, cachable);
 }
 
 /*!
@@ -1301,11 +1321,12 @@ static void xmpp_pubsub_subscribe(struct ast_xmpp_client *client, const char *no
  */
 static int xmpp_pubsub_handle_event(void *data, ikspak *pak)
 {
-	char *item_id, *device_state, *context;
+	char *item_id, *device_state, *context, *cachable_str;
 	int oldmsgs, newmsgs;
 	iks *item, *item_content;
 	struct ast_eid pubsub_eid;
 	struct ast_event *event;
+	unsigned int cachable = AST_DEVSTATE_CACHABLE;
 	item = iks_find(iks_find(iks_find(pak->x, "event"), "items"), "item");
 	if (!item) {
 		ast_log(LOG_ERROR, "Could not parse incoming PubSub event\n");
@@ -1320,6 +1341,9 @@ static int xmpp_pubsub_handle_event(void *data, ikspak *pak)
 	}
 	if (!strcasecmp(iks_name(item_content), "state")) {
 		device_state = iks_find_cdata(item, "state");
+		if ((cachable_str = iks_find_cdata(item, "cachable"))) {
+			sscanf(cachable_str, "%30d", &cachable);
+		}
 		if (!(event = ast_event_new(AST_EVENT_DEVICE_STATE_CHANGE,
 					    AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, item_id, AST_EVENT_IE_STATE,
 					    AST_EVENT_IE_PLTYPE_UINT, ast_devstate_val(device_state), AST_EVENT_IE_EID,
@@ -1344,7 +1368,13 @@ static int xmpp_pubsub_handle_event(void *data, ikspak *pak)
 			  iks_name(item_content));
 		return IKS_FILTER_EAT;
 	}
-	ast_event_queue_and_cache(event);
+
+	if (cachable == AST_DEVSTATE_CACHABLE) {
+		ast_event_queue_and_cache(event);
+	} else {
+		ast_event_queue(event);
+	}
+
 	return IKS_FILTER_EAT;
 }
 
@@ -1846,7 +1876,7 @@ static int acf_jabberreceive_read(struct ast_channel *chan, const char *name, ch
 {
 	RAII_VAR(struct xmpp_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup);
 	RAII_VAR(struct ast_xmpp_client_config *, clientcfg, NULL, ao2_cleanup);
-	char *aux = NULL, *parse = NULL;
+	char *parse = NULL;
 	int timeout, jidlen, resourcelen, found = 0;
 	struct timeval start;
 	long diff = 0;
@@ -1960,7 +1990,7 @@ static int acf_jabberreceive_read(struct ast_channel *chan, const char *name, ch
 				continue;
 			}
 			found = 1;
-			aux = ast_strdupa(message->message);
+			ast_copy_string(buf, message->message, buflen);
 			AST_LIST_REMOVE_CURRENT(list);
 			xmpp_message_destroy(message);
 			break;
@@ -1984,7 +2014,6 @@ static int acf_jabberreceive_read(struct ast_channel *chan, const char *name, ch
 		ast_log(LOG_NOTICE, "Timed out : no message received from %s\n", args.jid);
 		return -1;
 	}
-	ast_copy_string(buf, aux, buflen);
 
 	return 0;
 }