Newer
Older
char *mailbox, *context;
context = mailbox = ast_strdupa(mbox);
strsep(&context, "@");
if (ast_strlen_zero(context))
context = "default";
if (!(event = ast_event_new(AST_EVENT_MWI,
AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, new,
AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, old,
AST_EVENT_IE_END))) {
return;
}
ast_event_queue_and_cache(event,
AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR,
AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR,
static int notify_new_message(struct ast_channel *chan, struct ast_vm_user *vmu, int msgnum, long duration, char *fmt, char *cidnum, char *cidname)
char todir[PATH_MAX], fn[PATH_MAX], ext_context[PATH_MAX], *stringp;
int newmsgs = 0, oldmsgs = 0;
const char *category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY");
make_dir(todir, sizeof(todir), vmu->context, vmu->mailbox, "INBOX");
make_file(fn, sizeof(fn), todir, msgnum);
snprintf(ext_context, sizeof(ext_context), "%s@%s", vmu->mailbox, vmu->context);
if (!ast_strlen_zero(vmu->attachfmt)) {
fmt = vmu->attachfmt;
ast_log(LOG_WARNING, "Attachment format '%s' is not one of the recorded formats '%s'. Falling back to default format for '%s@%s'.\n", vmu->attachfmt, fmt, vmu->mailbox, vmu->context);
}
/* Attach only the first format */
Russell Bryant
committed
fmt = ast_strdupa(fmt);
stringp = fmt;
strsep(&stringp, "|");
Russell Bryant
committed
if (!ast_strlen_zero(vmu->serveremail))
myserveremail = vmu->serveremail;
Russell Bryant
committed
if (!ast_strlen_zero(vmu->email)) {
int attach_user_voicemail = ast_test_flag(vmu, VM_ATTACH);
if (!attach_user_voicemail)
attach_user_voicemail = ast_test_flag((&globalflags), VM_ATTACH);
if (attach_user_voicemail)
RETRIEVE(todir, msgnum, vmu->mailbox, vmu->context);
/*XXX possible imap issue, should category be NULL XXX*/
sendmail(myserveremail, vmu, msgnum, vmu->context, vmu->mailbox, cidnum, cidname, fn, fmt, duration, attach_user_voicemail, chan, category);
if (attach_user_voicemail)
DISPOSE(todir, msgnum);
Russell Bryant
committed
}
Russell Bryant
committed
Russell Bryant
committed
sendpage(myserveremail, vmu->pager, msgnum, vmu->context, vmu->mailbox, cidnum, cidname, duration, vmu, category);
DELETE(todir, msgnum, fn);
Matt O'Gorman
committed
#ifdef IMAP_STORAGE
DELETE(todir, msgnum, fn);
#endif
/* Leave voicemail for someone */
if (ast_app_has_voicemail(ext_context, NULL))
Tilghman Lesher
committed
ast_app_inboxcount(ext_context, &newmsgs, &oldmsgs);
queue_mwi_event(ext_context, newmsgs, oldmsgs);
manager_event(EVENT_FLAG_CALL, "MessageWaiting", "Mailbox: %s@%s\r\nWaiting: %d\r\nNew: %d\r\nOld: %d\r\n", vmu->mailbox, vmu->context, ast_app_has_voicemail(ext_context, NULL), newmsgs, oldmsgs);
run_externnotify(vmu->context, vmu->mailbox);
return 0;
}
static int forward_message(struct ast_channel *chan, char *context, struct vm_state *vms, struct ast_vm_user *sender, char *fmt, int flag, signed char record_gain)
#ifdef IMAP_STORAGE
BODY *body;
char *header_content;
char *temp;
char todir[256];
int todircount=0;
#endif
char username[70]="";
Martin Pycko
committed
int res = 0, cmd = 0;
struct ast_vm_user *receiver = NULL, *vmtmp;
AST_LIST_HEAD_NOLOCK_STATIC(extensions, ast_vm_user);
Tilghman Lesher
committed
char *stringp;
const char *s;
Martin Pycko
committed
int saved_messages = 0, found = 0;
int valid_extensions = 0;
char *dir;
int curmsg;
if (vms == NULL) return -1;
dir = vms->curdir;
curmsg = vms->curmsg;
Martin Pycko
committed
while (!res && !valid_extensions) {
int use_directory = 0;
if (ast_test_flag((&globalflags), VM_DIRECFORWARD)) {
int done = 0;
int retries = 0;
cmd=0;
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
if (cmd)
retries = 0;
switch (cmd) {
case '1':
use_directory = 0;
done = 1;
break;
case '2':
use_directory = 1;
done=1;
break;
case '*':
cmd = 't';
done = 1;
break;
default:
/* Press 1 to enter an extension press 2 to use the directory */
cmd = ast_play_and_wait(chan,"vm-forward");
if (!cmd)
cmd = ast_waitfordigit(chan,3000);
if (!cmd)
retries++;
if (retries > 3)
{
cmd = 't';
done = 1;
}
break;
}
/* use app_directory */
char old_context[sizeof(chan->context)];
char old_exten[sizeof(chan->exten)];
int old_priority;
struct ast_app* app;
app = pbx_findapp("Directory");
if (app) {
Jason Parker
committed
char vmcontext[256];
/* make backup copies */
memcpy(old_context, chan->context, sizeof(chan->context));
memcpy(old_exten, chan->exten, sizeof(chan->exten));
old_priority = chan->priority;
/* call the the Directory, changes the channel */
Jason Parker
committed
sprintf(vmcontext, "%s||v", context ? context : "default");
res = pbx_exec(chan, app, vmcontext);
ast_copy_string(username, chan->exten, sizeof(username));
/* restore the old context, exten, and priority */
memcpy(chan->context, old_context, sizeof(chan->context));
memcpy(chan->exten, old_exten, sizeof(chan->exten));
chan->priority = old_priority;
} else {
ast_log(LOG_WARNING, "Could not find the Directory application, disabling directory_forward\n");
ast_clear_flag((&globalflags), VM_DIRECFORWARD);
/* Ask for an extension */
res = ast_streamfile(chan, "vm-extension", chan->language); /* "extension" */
if (res)
break;
if ((res = ast_readstring(chan, username, sizeof(username) - 1, 2000, 10000, "#") < 0))
break;
}
Martin Pycko
committed
/* start all over if no username */
if (ast_strlen_zero(username))
Martin Pycko
committed
continue;
stringp = username;
s = strsep(&stringp, "*");
/* start optimistic */
valid_extensions = 1;
while (s) {
/* Don't forward to ourselves. find_user is going to malloc since we have a NULL as first argument */
if (strcmp(s,sender->mailbox) && (receiver = find_user(NULL, context, s))) {
AST_LIST_INSERT_HEAD(&extensions, receiver, list);
Martin Pycko
committed
found++;
} else {
valid_extensions = 0;
Martin Pycko
committed
s = strsep(&stringp, "*");
}
/* break from the loop of reading the extensions */
if (valid_extensions)
break;
/* "I am sorry, that's not a valid extension. Please try again." */
res = ast_play_and_wait(chan, "pbx-invalid");
Martin Pycko
committed
}
/* check if we're clear to proceed */
if (AST_LIST_EMPTY(&extensions) || !valid_extensions)
Martin Pycko
committed
return res;
Kevin P. Fleming
committed
struct leave_vm_options leave_options;
char mailbox[AST_MAX_EXTENSION * 2 + 2];
snprintf(mailbox, sizeof(mailbox), "%s@%s", username, context);
Kevin P. Fleming
committed
Kevin P. Fleming
committed
memset(&leave_options, 0, sizeof(leave_options));
leave_options.record_gain = record_gain;
cmd = leave_voicemail(chan, mailbox, &leave_options);
#ifdef IMAP_STORAGE
char *myserveremail = serveremail;
char buf[1024] = "";
int attach_user_voicemail = ast_test_flag((&globalflags), VM_ATTACH);
Mark Michelson
committed
RETRIEVE(dir, curmsg, sender->mailbox, context);
cmd = vm_forwardoptions(chan, sender, dir, curmsg, vmfmts, S_OR(context, "default"), record_gain, &duration, vms);
if (!cmd) {
AST_LIST_TRAVERSE_SAFE_BEGIN(&extensions, vmtmp, list) {
#ifdef IMAP_STORAGE
/* Need to get message content */
ast_debug(3,"Before mail_fetchheaders, curmsg is: %d, imap messages is %lu\n",vms->curmsg, vms->msgArray[vms->curmsg]);
if (!vms->msgArray[vms->curmsg]) {
ast_log (LOG_WARNING,"Trying to access unknown message\n");
return -1;
}
/* This will only work for new messages... */
header_content = mail_fetchheader (vms->mailstream, vms->msgArray[vms->curmsg]);
/* empty string means no valid header */
Matt O'Gorman
committed
if (ast_strlen_zero(header_content)) {
ast_log (LOG_ERROR,"Could not fetch header for message number %ld\n",vms->msgArray[vms->curmsg]);
return -1;
}
/* Get header info needed by sendmail */
if ((temp = get_header_by_tag(header_content, "X-Asterisk-VM-Duration:", buf, sizeof(buf))))
duration = atoi(temp);
else
duration = 0;
/* Attach only the first format */
if ((fmt = ast_strdupa(fmt))) {
stringp = fmt;
strsep(&stringp, "|");
} else {
ast_log (LOG_ERROR,"audio format not set. Default to WAV\n");
fmt = "WAV";
}
if (!strcasecmp(fmt, "wav49"))
fmt = "WAV";
ast_debug(3,"**** format set to %s, vmfmts set to %s\n",fmt,vmfmts);
/* if (!ast_strlen_zero(fmt)) { */
Matt O'Gorman
committed
snprintf(todir, sizeof(todir), "%s%s/%s/tmp", VM_SPOOL_DIR, vmtmp->context, vmtmp->mailbox);
make_gsm_file(vms->fn, vms->imapuser, todir, vms->curmsg);
ast_debug(3,"Before mail_fetchstructure, message number is %ld, filename is:%s\n",vms->msgArray[vms->curmsg], vms->fn);
/*mail_fetchstructure (mailstream, vmArray[0], &body); */
mail_fetchstructure (vms->mailstream, vms->msgArray[vms->curmsg], &body);
save_body(body,vms,"3","gsm");
/* should not assume "fmt" here! */
/* get destination mailbox */
dstvms = get_vm_state_by_mailbox(vmtmp->mailbox,0);
if (dstvms) {
init_mailstream(dstvms, 0);
if (!dstvms->mailstream) {
ast_log (LOG_ERROR,"IMAP mailstream for %s is NULL\n",vmtmp->mailbox);
} else {
STORE(todir, vmtmp->mailbox, vmtmp->context, dstvms->curmsg, chan, vmtmp, fmt, duration, dstvms);
run_externnotify(vmtmp->context, vmtmp->mailbox);
}
} else {
ast_log (LOG_ERROR,"Could not find state information for mailbox %s\n",vmtmp->mailbox);
}
Matt O'Gorman
committed
if (!ast_strlen_zero(vmtmp->serveremail))
myserveremail = vmtmp->serveremail;
attach_user_voicemail = ast_test_flag(vmtmp, VM_ATTACH);
/* NULL category for IMAP storage */
sendmail(myserveremail, vmtmp, todircount, vmtmp->context, vmtmp->mailbox, S_OR(chan->cid.cid_num, NULL), S_OR(chan->cid.cid_name, NULL), vms->fn, fmt, duration, attach_user_voicemail, chan, NULL);
copy_message(chan, sender, 0, curmsg, duration, vmtmp, fmt, dir);
saved_messages++;
AST_LIST_REMOVE_CURRENT(&extensions, list);
free_user(vmtmp);
if (res)
break;
AST_LIST_TRAVERSE_SAFE_END;
if (saved_messages > 0) {
/* give confirmation that the message was saved */
/* commented out since we can't forward batches yet
if (saved_messages == 1)
res = ast_play_and_wait(chan, "vm-message");
res = ast_play_and_wait(chan, "vm-messages");
if (!res)
res = ast_play_and_wait(chan, "vm-saved"); */
Martin Pycko
committed
}
/* If anything failed above, we still have this list to free */
while ((vmtmp = AST_LIST_REMOVE_HEAD(&extensions, list)))
free_user(vmtmp);
Martin Pycko
committed
return res ? res : cmd;
static int wait_file2(struct ast_channel *chan, struct vm_state *vms, char *file)
int res;
Steve Murphy
committed
if ((res = ast_stream_and_wait(chan, file, AST_DIGIT_ANY)) < 0)
ast_log(LOG_WARNING, "Unable to play message %s\n", file);
return res;
}
static int wait_file(struct ast_channel *chan, struct vm_state *vms, char *file)
{
Mark Michelson
committed
return ast_control_streamfile(chan, file, listen_control_forward_key, listen_control_reverse_key, listen_control_stop_key, listen_control_pause_key, listen_control_restart_key, skipms, NULL);
}
Tilghman Lesher
committed
static int play_message_category(struct ast_channel *chan, const char *category)
{
int res = 0;
if (!ast_strlen_zero(category))
res = ast_play_and_wait(chan, category);
if (res) {
ast_log(LOG_WARNING, "No sound file for category '%s' was found.\n", category);
res = 0;
}
Tilghman Lesher
committed
static int play_message_datetime(struct ast_channel *chan, struct ast_vm_user *vmu, const char *origtime, const char *filename)
{
int res = 0;
struct vm_zone *the_zone = NULL;
time_t t;
Kevin P. Fleming
committed
if (ast_get_time_t(origtime, &t, 0, NULL)) {
ast_log(LOG_WARNING, "Couldn't find origtime in %s\n", filename);
return 0;
}
/* Does this user have a timezone specified? */
if (!ast_strlen_zero(vmu->zonetag)) {
/* Find the zone in the list */
struct vm_zone *z;
Russell Bryant
committed
AST_LIST_LOCK(&zones);
AST_LIST_TRAVERSE(&zones, z, list) {
if (!strcmp(z->name, vmu->zonetag)) {
the_zone = z;
break;
Russell Bryant
committed
AST_LIST_UNLOCK(&zones);
/* No internal variable parsing for now, so we'll comment it out for the time being */
#if 0
/* Set the DIFF_* variables */
ast_localtime(&t, &time_now, NULL);
Kevin P. Fleming
committed
tv_now = ast_tvnow();
Tilghman Lesher
committed
ast_localtime(&tv_now, &time_then, NULL);
/* Day difference */
if (time_now.tm_year == time_then.tm_year)
snprintf(temp,sizeof(temp),"%d",time_now.tm_yday);
else
snprintf(temp,sizeof(temp),"%d",(time_now.tm_year - time_then.tm_year) * 365 + (time_now.tm_yday - time_then.tm_yday));
pbx_builtin_setvar_helper(chan, "DIFF_DAY", temp);
/* Can't think of how other diffs might be helpful, but I'm sure somebody will think of something. */
#endif
if (the_zone)
res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, the_zone->msg_format, the_zone->timezone);
else if (!strcasecmp(chan->language,"pl")) /* POLISH syntax */
Russell Bryant
committed
res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q HM", NULL);
else if (!strcasecmp(chan->language,"se")) /* SWEDISH syntax */
Russell Bryant
committed
res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' dB 'digits/at' k 'and' M", NULL);
else if (!strcasecmp(chan->language,"no")) /* NORWEGIAN syntax */
Russell Bryant
committed
res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q 'digits/at' HM", NULL);
else if (!strcasecmp(chan->language,"de")) /* GERMAN syntax */
Mark Spencer
committed
res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q 'digits/at' HM", NULL);
else if (!strcasecmp(chan->language,"nl")) /* DUTCH syntax */
res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/nl-om' HM", NULL);
else if (!strcasecmp(chan->language,"it")) /* ITALIAN syntax */
res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/at' 'digits/hours' k 'digits/e' M 'digits/minutes'", NULL);
else if (!strcasecmp(chan->language,"gr"))
res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q H 'digits/kai' M ", NULL);
else if (!strcasecmp(chan->language,"pt_BR"))
res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Ad 'digits/pt-de' B 'digits/pt-de' Y 'digits/pt-as' HM ", NULL);
else if (!strcasecmp(chan->language,"tw")) /* CHINESE (Taiwan) syntax */
res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "qR 'vm-received'", NULL);
else
res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/at' IMp", NULL);
#if 0
pbx_builtin_setvar_helper(chan, "DIFF_DAY", NULL);
#endif
return res;
}
Tilghman Lesher
committed
static int play_message_callerid(struct ast_channel *chan, struct vm_state *vms, char *cid, const char *context, int callback)
{
int res = 0;
int i;
char *callerid, *name;
/* If voicemail cid is not enabled, or we didn't get cid or context from the attribute file, leave now. */
/* BB: Still need to change this so that if this function is called by the message envelope (and someone is explicitly requesting to hear the CID), it does not check to see if CID is enabled in the config file */
if ((cid == NULL)||(context == NULL))
return res;
/* Strip off caller ID number from name */
ast_debug(1, "VM-CID: composite caller ID received: %s, context: %s\n", cid, context);
ast_callerid_parse(cid, &name, &callerid);
Tilghman Lesher
committed
if ((!ast_strlen_zero(callerid)) && strcmp(callerid, "Unknown")) {
/* Check for internal contexts and only */
/* say extension when the call didn't come from an internal context in the list */
for (i = 0 ; i < MAX_NUM_CID_CONTEXTS ; i++){
ast_debug(1, "VM-CID: comparing internalcontext: %s\n", cidinternalcontexts[i]);
if ((strcmp(cidinternalcontexts[i], context) == 0))
if (i != MAX_NUM_CID_CONTEXTS){ /* internal context? */
if (!res) {
snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, context, callerid);
if (!ast_strlen_zero(prefile)) {
/* See if we can find a recorded name for this person instead of their extension number */
if (ast_fileexists(prefile, NULL, NULL) > 0) {
ast_verb(3, "Playing envelope info: CID number '%s' matches mailbox number, playing recorded name\n", callerid);
if (!callback)
res = wait_file2(chan, vms, "vm-from");
Steve Murphy
committed
res = ast_stream_and_wait(chan, prefile, "");
ast_verb(3, "Playing envelope info: message from '%s'\n", callerid);
/* BB: Say "from extension" as one saying to sound smoother */
if (!callback)
res = wait_file2(chan, vms, "vm-from-extension");
res = ast_say_digit_str(chan, callerid, "", chan->language);
}
}
}
}
ast_debug(1, "VM-CID: Numeric caller id: (%s)\n", callerid);
/* BB: Since this is all nicely figured out, why not say "from phone number" in this case" */
if (!callback)
res = wait_file2(chan, vms, "vm-from-phonenumber");
res = ast_say_digit_str(chan, callerid, AST_DIGIT_ANY, chan->language);
}
ast_debug(1, "VM-CID: From an unknown number\n");
Tilghman Lesher
committed
/* Say "from an unknown caller" as one phrase - it is already recorded by "the voice" anyhow */
res = wait_file2(chan, vms, "vm-unknown-caller");
Tilghman Lesher
committed
static int play_message_duration(struct ast_channel *chan, struct vm_state *vms, const char *duration, int minduration)
{
int res = 0;
int durationm;
int durations;
/* Verify that we have a duration for the message */
return res;
/* Convert from seconds to minutes */
durations=atoi(duration);
durationm=(durations / 60);
ast_debug(1, "VM-Duration: duration is: %d seconds converted to: %d minutes\n", durations, durationm);
Russell Bryant
committed
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
if ((!res) && (durationm >= minduration)) {
res = wait_file2(chan, vms, "vm-duration");
/* POLISH syntax */
if (!strcasecmp(chan->language, "pl")) {
div_t num = div(durationm, 10);
if (durationm == 1) {
res = ast_play_and_wait(chan, "digits/1z");
res = res ? res : ast_play_and_wait(chan, "vm-minute-ta");
} else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
if (num.rem == 2) {
if (!num.quot) {
res = ast_play_and_wait(chan, "digits/2-ie");
} else {
res = say_and_wait(chan, durationm - 2 , chan->language);
res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
}
} else {
res = say_and_wait(chan, durationm, chan->language);
}
res = res ? res : ast_play_and_wait(chan, "vm-minute-ty");
} else {
res = say_and_wait(chan, durationm, chan->language);
res = res ? res : ast_play_and_wait(chan, "vm-minute-t");
}
/* DEFAULT syntax */
} else {
res = ast_say_number(chan, durationm, AST_DIGIT_ANY, chan->language, NULL);
res = wait_file2(chan, vms, "vm-minutes");
}
}
return res;
}
#ifdef IMAP_STORAGE
static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms)
{
char *header_content;
char cid[256];
char context[256];
char origtime[32];
char duration[16];
char category[32];
vms->starting = 0;
ast_debug(3,"Before mail_fetchheaders, curmsg is: %d, imap messages is %lu\n",vms->curmsg, vms->msgArray[vms->curmsg]);
if (!vms->msgArray[vms->curmsg]) {
ast_log (LOG_WARNING,"Trying to access unknown message\n");
return -1;
}
/* This will only work for new messages... */
header_content = mail_fetchheader (vms->mailstream, vms->msgArray[vms->curmsg]);
/* empty string means no valid header */
Matt O'Gorman
committed
if (ast_strlen_zero(header_content)) {
ast_log (LOG_ERROR,"Could not fetch header for message number %ld\n",vms->msgArray[vms->curmsg]);
return -1;
}
Matt O'Gorman
committed
snprintf(todir, sizeof(todir), "%s%s/%s/tmp", VM_SPOOL_DIR, vmu->context, vmu->mailbox);
make_gsm_file(vms->fn, vms->imapuser, todir, vms->curmsg);
mail_fetchstructure (vms->mailstream,vms->msgArray[vms->curmsg],&body);
/* We have the body, now we extract the file name of the first attachment. */
if (body->nested.part->next && body->nested.part->next->body.parameter->value) {
attachedfilefmt = ast_strdupa(body->nested.part->next->body.parameter->value);
} else {
ast_log(LOG_ERROR, "There is no file attached to this IMAP message.\n");
return -1;
}
Mark Michelson
committed
/* Find the format of the attached file */
strsep(&attachedfilefmt, ".");
if (!attachedfilefmt) {
ast_log(LOG_ERROR, "File format could not be obtained from IMAP message attachment\n");
return -1;
}
save_body(body, vms, "2", attachedfilefmt);
adsi_message(chan, vms);
if (!vms->curmsg)
res = wait_file2(chan, vms, "vm-first"); /* "First" */
else if (vms->curmsg == vms->lastmsg)
res = wait_file2(chan, vms, "vm-last"); /* "last" */
if (!res) {
res = wait_file2(chan, vms, "vm-message"); /* "message" */
if (vms->curmsg && (vms->curmsg != vms->lastmsg)) {
if (!res)
res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, chan->language, (char *) NULL);
}
}
Matt O'Gorman
committed
/* Get info from headers!! */
if ((temp = get_header_by_tag(header_content, "X-Asterisk-VM-Caller-ID-Num:", buf, sizeof(buf))))
Matt O'Gorman
committed
ast_copy_string(cid, temp, sizeof(cid));
if ((temp = get_header_by_tag(header_content, "X-Asterisk-VM-Context:", buf, sizeof(buf))))
Matt O'Gorman
committed
ast_copy_string(context, temp, sizeof(context));
if ((temp = get_header_by_tag(header_content, "X-Asterisk-VM-Orig-time:", buf, sizeof(buf))))
Matt O'Gorman
committed
ast_copy_string(origtime, temp, sizeof(origtime));
if ((temp = get_header_by_tag(header_content, "X-Asterisk-VM-Duration:", buf, sizeof(buf))))
Matt O'Gorman
committed
ast_copy_string(duration,temp, sizeof(duration));
if ((temp = get_header_by_tag(header_content, "X-Asterisk-VM-Category:", buf, sizeof(buf))))
Matt O'Gorman
committed
ast_copy_string(category,temp, sizeof(category));
Matt O'Gorman
committed
/*if (!strncasecmp("macro",context,5)) Macro names in contexts are useless for our needs */
/* context = ast_variable_retrieve(msg_cfg, "message","macrocontext"); */
if (res == '1')
res = 0;
if ((!res) && !ast_strlen_zero(category)) {
res = play_message_category(chan, category);
}
if ((!res) && (ast_test_flag(vmu, VM_ENVELOPE)) && origtime[0] != '\0')
res = play_message_datetime(chan, vmu, origtime, "IMAP_STORAGE");
if ((!res) && (ast_test_flag(vmu, VM_SAYCID)) && cid[0] !='\0' && context[0] !='\0')
res = play_message_callerid(chan, vms, cid, context, 0);
if ((!res) && (ast_test_flag(vmu, VM_SAYDURATION)) && duration[0] != '\0')
res = play_message_duration(chan, vms, duration, vmu->saydurationm);
/* Allow pressing '1' to skip envelope / callerid */
/* if (res == '1')
res = 0;
*/
/*ast_config_destroy(msg_cfg);*/
res = 0;
if (!res) {
vms->heard[vms->curmsg] = 1;
res = wait_file(chan, vms, vms->fn);
}
DISPOSE(vms->curdir, vms->curmsg);
Matt O'Gorman
committed
DELETE(0, 0, vms->fn);
return res;
}
#else
static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms)
{
int res = 0;
Tilghman Lesher
committed
char filename[256], *cid;
const char *origtime, *context, *category, *duration;
struct ast_config *msg_cfg;
vms->starting = 0;
make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
adsi_message(chan, vms);
if (!vms->curmsg)
res = wait_file2(chan, vms, "vm-first"); /* "First" */
else if (vms->curmsg == vms->lastmsg)
res = wait_file2(chan, vms, "vm-last"); /* "last" */
if (!res) {
Russell Bryant
committed
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
/* POLISH syntax */
if (!strcasecmp(chan->language, "pl")) {
if (vms->curmsg && (vms->curmsg != vms->lastmsg)) {
int ten, one;
char nextmsg[256];
ten = (vms->curmsg + 1) / 10;
one = (vms->curmsg + 1) % 10;
if (vms->curmsg < 20) {
snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", vms->curmsg + 1);
res = wait_file2(chan, vms, nextmsg);
} else {
snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", ten * 10);
res = wait_file2(chan, vms, nextmsg);
if (one > 0) {
if (!res) {
snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", one);
res = wait_file2(chan, vms, nextmsg);
}
}
}
}
if (!res)
Russell Bryant
committed
res = wait_file2(chan, vms, "vm-message");
} else {
if (!strcasecmp(chan->language, "se")) /* SWEDISH syntax */
res = wait_file2(chan, vms, "vm-meddelandet"); /* "message" */
else /* DEFAULT syntax */
res = wait_file2(chan, vms, "vm-message");
if (vms->curmsg && (vms->curmsg != vms->lastmsg)) {
if (!res)
res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, chan->language, NULL);
}
}
}
/* Retrieve info from VM attribute file */
make_file(vms->fn2, sizeof(vms->fn2), vms->curdir, vms->curmsg);
Russell Bryant
committed
snprintf(filename, sizeof(filename), "%s.txt", vms->fn2);
Mark Michelson
committed
RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context);
if (!msg_cfg) {
ast_log(LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
return 0;
}
if (!(origtime = ast_variable_retrieve(msg_cfg, "message", "origtime"))) {
ast_log(LOG_WARNING, "No origtime?!\n");
DISPOSE(vms->curdir, vms->curmsg);
ast_config_destroy(msg_cfg);
cid = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "callerid"));
duration = ast_variable_retrieve(msg_cfg, "message", "duration");
category = ast_variable_retrieve(msg_cfg, "message", "category");
context = ast_variable_retrieve(msg_cfg, "message", "context");
if (!strncasecmp("macro",context,5)) /* Macro names in contexts are useless for our needs */
context = ast_variable_retrieve(msg_cfg, "message","macrocontext");
if (!res)
res = play_message_category(chan, category);
if ((!res) && (ast_test_flag(vmu, VM_ENVELOPE)))
res = play_message_datetime(chan, vmu, origtime, filename);
if ((!res) && (ast_test_flag(vmu, VM_SAYCID)))
res = play_message_callerid(chan, vms, cid, context, 0);
if ((!res) && (ast_test_flag(vmu, VM_SAYDURATION)))
res = play_message_duration(chan, vms, duration, vmu->saydurationm);
Mark Spencer
committed
/* Allow pressing '1' to skip envelope / callerid */
if (res == '1')
res = 0;
if (!res) {
make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
vms->heard[vms->curmsg] = 1;
res = wait_file(chan, vms, vms->fn);
}
DISPOSE(vms->curdir, vms->curmsg);
return res;
}
Matt O'Gorman
committed
static void imap_mailbox_name(char *spec, struct vm_state *vms, int box, int use_folder)
char tmp[256], *t = tmp;
size_t left = sizeof(tmp);
Mark Michelson
committed
if (box == OLD_FOLDER) {
ast_copy_string(vms->curbox, mbox(NEW_FOLDER), sizeof(vms->curbox));
sprintf(vms->vmbox, "vm-%s", mbox(OLD_FOLDER));
ast_copy_string(vms->curbox, mbox(box), sizeof(vms->curbox));
snprintf(vms->vmbox, sizeof(vms->vmbox), "vm-%s", vms->curbox);
}
/* Build up server information */
ast_build_string(&t, &left, "{%s:%s/imap", imapserver, imapport);
/* Add authentication user if present */
if (!ast_strlen_zero(authuser))
ast_build_string(&t, &left, "/authuser=%s", authuser);
/* Add flags if present */
if (!ast_strlen_zero(imapflags))
ast_build_string(&t, &left, "/%s", imapflags);
/* End with username */
ast_build_string(&t, &left, "/user=%s}", vms->imapuser);
Mark Michelson
committed
if(box == NEW_FOLDER || box == OLD_FOLDER)
Matt O'Gorman
committed
sprintf(spec, "%s%s", tmp, use_folder? imapfolder: "INBOX");
Mark Michelson
committed
else if (box == GREETINGS_FOLDER)
sprintf(spec, "%s%s", tmp, greetingfolder);
Matt O'Gorman
committed
else
sprintf(spec, "%s%s%c%s", tmp, imapfolder, delimiter, mbox(box));
}
static int init_mailstream(struct vm_state *vms, int box)
{
MAILSTREAM *stream = NIL;
long debug;
char tmp[255];
if (!vms) {
ast_log (LOG_ERROR,"vm_state is NULL!\n");
return -1;
}
ast_debug(3,"vm_state user is:%s\n",vms->imapuser);
Matt O'Gorman
committed
if (vms->mailstream == NIL || !vms->mailstream) {
ast_debug(1,"mailstream not set.\n");
Matt O'Gorman
committed
} else {
stream = vms->mailstream;
}
/* debug = T; user wants protocol telemetry? */
debug = NIL; /* NO protocol telemetry? */
if (delimiter == '\0') { /* did not probe the server yet */
char *cp;
Russell Bryant
committed
#ifdef USE_SYSTEM_IMAP
#include <imap/linkage.c>
#else
Matt O'Gorman
committed
#include "linkage.c"
Russell Bryant
committed
#endif
Matt O'Gorman
committed
/* Connect to INBOX first to get folders delimiter */
Mark Michelson
committed
imap_mailbox_name(tmp, vms, NEW_FOLDER, 0);
stream = mail_open(stream, tmp, debug ? OP_DEBUG : NIL);
Matt O'Gorman
committed
if (stream == NIL) {
ast_log (LOG_ERROR, "Can't connect to imap server %s\n", tmp);
return NIL;
}
get_mailbox_delimiter(stream);
/* update delimiter in imapfolder */
for(cp = imapfolder; *cp; cp++) {
Matt O'Gorman
committed
if(*cp == '/')
*cp = delimiter;
Matt O'Gorman
committed
}
/* Now connect to the target folder */
imap_mailbox_name(tmp, vms, box, 1);
ast_debug(3,"Before mail_open, server: %s, box:%d\n", tmp, box);
vms->mailstream = mail_open(stream, tmp, debug ? OP_DEBUG : NIL);
Matt O'Gorman
committed
if (vms->mailstream == NIL) {
return -1;
} else {
return 0;
}
}
static int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu, int box)
{
SEARCHPGM *pgm;
SEARCHHEADER *hdr;
int ret;
char dbox[256];
ast_copy_string(vms->imapuser,vmu->imapuser, sizeof(vms->imapuser));
ast_debug(3,"Before init_mailstream, user is %s\n",vmu->imapuser);
if ((ret = init_mailstream(vms, box)) || !vms->mailstream) {
ast_log (LOG_ERROR,"Could not initialize mailstream\n");
/* Check Quota (here for now to test) */
mail_parameters(NULL, SET_QUOTA, (void *) mm_parsequota);
Matt O'Gorman
committed
imap_mailbox_name(dbox, vms, box, 1);
imap_getquotaroot(vms->mailstream, dbox);
/* Check IMAP folder for Asterisk messages only... */
hdr = mail_newsearchheader("X-Asterisk-VM-Extension", vmu->mailbox);
pgm->deleted = 0;
pgm->undeleted = 1;
Mark Michelson
committed
/* if box = NEW_FOLDER, check for new, if box = OLD_FOLDER, check for read */
if (box == NEW_FOLDER) {
pgm->unseen = 1;
pgm->seen = 0;
Mark Michelson
committed
} else if (box == OLD_FOLDER) {
pgm->seen = 1;
pgm->unseen = 0;
}
ast_debug(3,"Before mail_search_full, user is %s\n",vmu->imapuser);
vms->vmArrayIndex = 0;
mail_search_full (vms->mailstream, NULL, pgm, NIL);
vms->lastmsg = vms->vmArrayIndex - 1;
Matt O'Gorman
committed
mail_free_searchpgm(&pgm);
Mark Michelson
committed
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
static int imap_remove_file(char *dir, int msgnum)
{
char fn[PATH_MAX];
char full_fn[PATH_MAX];
char msgnums[80];
if (msgnum > -1) {
snprintf(msgnums, sizeof(msgnums), "%d", msgnum);
make_file(fn, sizeof(fn), dir, msgnum);
} else
ast_copy_string(fn, dir, sizeof(fn));
if ((msgnum < 0 && imapgreetings) || msgnum > -1) {
ast_filedelete(fn, NULL);
snprintf(full_fn, sizeof(full_fn), "%s.txt", fn);
unlink(full_fn);
}
return 0;
}
static int imap_retrieve_file (char *dir, int msgnum, char *mailbox, char *context)
{
struct ast_vm_user *vmu;
struct vm_state *vms_p;
char *file, *filename;
char *attachment;
/*char *mb, *cur;*/
int ret = 0, i;
BODY *body;
/* This function is only used for retrieval of IMAP greetings
* regular messages are not retrieved this way, nor are greetings
* if they are stored locally*/
if (msgnum > -1 || !imapgreetings) {
return 0;
} else {
file = strrchr(ast_strdupa(dir), '/');
if (file)
*file++ = '\0';
else {
ast_debug (1, "Failed to procure file name from directory passed.\n");
return -1;
}
}
/* We have to get the user before we can open the stream! */
/* ast_log (LOG_DEBUG,"Before find_user, context is %s and mailbox is %s\n",context,mailbox); */
vmu = find_user(NULL, context, mailbox);
if (!vmu) {
ast_log (LOG_ERROR,"Couldn't find mailbox %s in context %s\n",mailbox,context);
return -1;
} else {
/* No IMAP account available */
if (vmu->imapuser[0] == '\0') {
ast_log (LOG_WARNING,"IMAP user not set for mailbox %s\n",vmu->mailbox);
free_user(vmu);
return -1;
}
}
/* check if someone is accessing this box right now... */
vms_p = get_vm_state_by_mailbox(mailbox,0);
if (!vms_p) {
ast_log(LOG_ERROR, "Voicemail state not found!\n");
return -1;
}
ret = init_mailstream(vms_p, GREETINGS_FOLDER);
if (!vms_p->mailstream) {
ast_log (LOG_ERROR,"IMAP mailstream is NULL\n");
free_user(vmu);
return -1;
}
for (i = 0; i < vms_p->mailstream->nmsgs; i++) {
Mark Michelson
committed
mail_fetchstructure(vms_p->mailstream, i + 1, &body);
/* We have the body, now we extract the file name of the first attachment. */
if (body->nested.part->next && body->nested.part->next->body.parameter->value) {
attachment = ast_strdupa(body->nested.part->next->body.parameter->value);
} else {
ast_log(LOG_ERROR, "There is no file attached to this IMAP message.\n");
return -1;
}
filename = strsep(&attachment, ".");
if (!strcmp(filename, file)) {
Mark Michelson
committed
ast_copy_string(vms_p->fn, dir, sizeof(vms_p->fn));
vms_p->msgArray[vms_p->curmsg] = i + 1;
save_body(body, vms_p, "2", attachment);
free_user(vmu);
return 0;
}
}
free_user(vmu);
return -1;
}
static int imap_delete_old_greeting (char *dir, struct vm_state *vms)