summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/app_directory.c82
-rw-r--r--configs/voicemail.conf.sample4
-rw-r--r--contrib/realtime/mysql/voicemail.sql2
-rw-r--r--res/res_xmpp.c51
4 files changed, 113 insertions, 26 deletions
diff --git a/apps/app_directory.c b/apps/app_directory.c
index ce01bc83b..b26a09cd9 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 a92e7a1c5..b776fd60d 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 bd924f426..62c7fbb6a 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 77369c487..1e130e771 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;
}