52 #ifdef USE_SYSTEM_IMAP
53 #include <imap/c-client.h>
54 #include <imap/imap4r1.h>
55 #include <imap/linkage.h>
56 #elif defined (USE_SYSTEM_CCLIENT)
57 #include <c-client/c-client.h>
58 #include <c-client/imap4r1.h>
59 #include <c-client/linkage.h>
69 #include "asterisk/paths.h"
75 #if defined(__FreeBSD__) || defined(__OpenBSD__)
348 static char imapserver[48];
349 static char imapport[8];
350 static char imapflags[128];
351 static char imapfolder[64];
352 static char imapparentfolder[64] =
"\0";
353 static char greetingfolder[64];
354 static char authuser[32];
355 static char authpassword[42];
356 static int imapversion = 1;
358 static int expungeonhangup = 1;
359 static int imapgreetings = 0;
360 static char delimiter =
'\0';
368 static int init_mailstream(
struct vm_state *vms,
int box);
369 static void write_file(
char *filename,
char *buffer,
unsigned long len);
370 static char *get_header_by_tag(
char *header,
char *tag,
char *buf,
size_t len);
371 static void vm_imap_delete(
char *file,
int msgnum,
struct ast_vm_user *vmu);
372 static char *get_user_by_mailbox(
char *
mailbox,
char *buf,
size_t len);
373 static struct vm_state *get_vm_state_by_imapuser(
const char *
user,
int interactive);
374 static struct vm_state *get_vm_state_by_mailbox(
const char *
mailbox,
const char *
context,
int interactive);
376 static void vmstate_insert(
struct vm_state *vms);
377 static void vmstate_delete(
struct vm_state *vms);
378 static void set_update(MAILSTREAM * stream);
379 static void init_vm_state(
struct vm_state *vms);
380 static int save_body(BODY *body,
struct vm_state *vms,
char *section,
char *
format,
int is_intro);
381 static void get_mailbox_delimiter(MAILSTREAM *stream);
382 static void mm_parsequota (MAILSTREAM *stream,
unsigned char *msg, QUOTALIST *pquota);
383 static void imap_mailbox_name(
char *spec,
size_t len,
struct vm_state *vms,
int box,
int target);
384 static int imap_store_file(
const char *dir,
const char *mailboxuser,
const char *mailboxcontext,
int msgnum,
struct ast_channel *chan,
struct ast_vm_user *vmu,
char *fmt,
int duration,
struct vm_state *vms,
const char *flag);
385 static void update_messages_by_imapuser(
const char *
user,
unsigned long number);
388 static int imap_remove_file (
char *dir,
int msgnum);
389 static int imap_retrieve_file (
const char *dir,
const int msgnum,
const char *
mailbox,
const char *
context);
390 static int imap_delete_old_greeting (
char *dir,
struct vm_state *vms);
402 #define SMDI_MWI_WAIT_TIMEOUT 1000
404 #define COMMAND_TIMEOUT 5000
406 #define VOICEMAIL_DIR_MODE 0777
407 #define VOICEMAIL_FILE_MODE 0666
408 #define CHUNKSIZE 65536
410 #define VOICEMAIL_CONFIG "voicemail.conf"
411 #define ASTERISK_USERNAME "asterisk"
416 #define DEFAULT_LISTEN_CONTROL_FORWARD_KEY "#"
417 #define DEFAULT_LISTEN_CONTROL_REVERSE_KEY "*"
418 #define DEFAULT_LISTEN_CONTROL_PAUSE_KEY "0"
419 #define DEFAULT_LISTEN_CONTROL_RESTART_KEY "2"
420 #define DEFAULT_LISTEN_CONTROL_STOP_KEY "13456789"
421 #define VALID_DTMF "1234567890*#"
425 #define SENDMAIL "/usr/sbin/sendmail -t"
427 #define INTRO "vm-intro"
430 #define MAXMSGLIMIT 9999
432 #define MINPASSWORD 0
434 #define BASELINELEN 72
435 #define BASEMAXINLINE 256
442 #define MAX_DATETIME_FORMAT 512
443 #define MAX_NUM_CID_CONTEXTS 10
445 #define VM_REVIEW (1 << 0)
446 #define VM_OPERATOR (1 << 1)
447 #define VM_SAYCID (1 << 2)
448 #define VM_SVMAIL (1 << 3)
449 #define VM_ENVELOPE (1 << 4)
450 #define VM_SAYDURATION (1 << 5)
451 #define VM_SKIPAFTERCMD (1 << 6)
452 #define VM_FORCENAME (1 << 7)
453 #define VM_FORCEGREET (1 << 8)
454 #define VM_PBXSKIP (1 << 9)
455 #define VM_DIRECFORWARD (1 << 10)
456 #define VM_ATTACH (1 << 11)
457 #define VM_DELETE (1 << 12)
458 #define VM_ALLOCED (1 << 13)
459 #define VM_SEARCH (1 << 14)
460 #define VM_TEMPGREETWARN (1 << 15)
461 #define VM_MOVEHEARD (1 << 16)
462 #define VM_MESSAGEWRAP (1 << 17)
463 #define VM_FWDURGAUTO (1 << 18)
464 #define ERROR_LOCK_PATH -100
465 #define OPERATOR_EXIT 300
516 #ifdef TEST_FRAMEWORK
641 char imappassword[80];
643 char imapvmshareid[80];
655 char msg_format[512];
658 #define VMSTATE_MAX_MSG_ARRAY 256
665 char curdir[PATH_MAX];
666 char vmbox[PATH_MAX];
668 char intro[PATH_MAX];
683 unsigned msg_array_max;
684 MAILSTREAM *mailstream;
690 char introfn[PATH_MAX];
691 unsigned int quota_limit;
692 unsigned int quota_usage;
698 static char odbc_database[80];
699 static char odbc_table[80];
700 #define RETRIEVE(a,b,c,d) retrieve_file(a,b)
701 #define DISPOSE(a,b) remove_file(a,b)
702 #define STORE(a,b,c,d,e,f,g,h,i,j) store_file(a,b,c,d)
703 #define EXISTS(a,b,c,d) (message_exists(a,b))
704 #define RENAME(a,b,c,d,e,f,g,h) (rename_file(a,b,c,d,e,f))
705 #define COPY(a,b,c,d,e,f,g,h) (copy_file(a,b,c,d,e,f))
706 #define DELETE(a,b,c,d) (delete_file(a,b))
709 #define DISPOSE(a,b) (imap_remove_file(a,b))
710 #define STORE(a,b,c,d,e,f,g,h,i,j) (imap_store_file(a,b,c,d,e,f,g,h,i,j))
711 #define RETRIEVE(a,b,c,d) imap_retrieve_file(a,b,c,d)
712 #define EXISTS(a,b,c,d) (ast_fileexists(c,NULL,d) > 0)
713 #define RENAME(a,b,c,d,e,f,g,h) (rename_file(g,h));
714 #define COPY(a,b,c,d,e,f,g,h) (copy_file(g,h));
715 #define DELETE(a,b,c,d) (vm_imap_delete(a,b,d))
717 #define RETRIEVE(a,b,c,d)
719 #define STORE(a,b,c,d,e,f,g,h,i,j)
720 #define EXISTS(a,b,c,d) (ast_fileexists(c,NULL,d) > 0)
721 #define RENAME(a,b,c,d,e,f,g,h) (rename_file(g,h));
722 #define COPY(a,b,c,d,e,f,g,h) (copy_plain_file(g,h));
723 #define DELETE(a,b,c,d) (vm_delete(c))
734 #define PWDCHANGE_INTERNAL (1 << 1)
735 #define PWDCHANGE_EXTERNAL (1 << 2)
739 #define tdesc "Comedian Mail (Voicemail System) with ODBC Storage"
742 # define tdesc "Comedian Mail (Voicemail System) with IMAP Storage"
744 # define tdesc "Comedian Mail (Voicemail System)"
753 static char *
app =
"VoiceMail";
756 static char *
app2 =
"VoiceMailMain";
758 static char *
app3 =
"MailboxExists";
759 static char *
app4 =
"VMAuthenticate";
792 #define DEFAULT_POLL_FREQ 30
877 static unsigned char adsifdn[4] =
"\x00\x00\x00\x0F";
878 static unsigned char adsisec[4] =
"\x9B\xDB\xF7\xAC";
888 char *fmt,
int outsidecaller,
struct ast_vm_user *vmu,
int *duration,
int *sound_duration,
const char *unlockdir,
889 signed char record_gain,
struct vm_state *vms,
char *flag);
893 static void make_email_file(FILE *p,
char *srcemail,
struct ast_vm_user *vmu,
int msgnum,
char *
context,
char *
mailbox,
const char *fromfolder,
char *cidnum,
char *cidname,
char *attach,
char *attach2,
char *
format,
int duration,
int attach_user_voicemail,
struct ast_channel *chan,
const char *category,
int imap,
const char *flag);
919 if (strcmp(i->
mailbox, j->mailbox)) {
927 struct inprocess *i, *arg =
ast_alloca(
sizeof(*arg) + strlen(context) + strlen(mailbox) + 2);
932 if ((i =
ao2_find(inprocess_container, arg, 0))) {
941 if (!(i =
ao2_alloc(
sizeof(*i) + strlen(context) + strlen(mailbox) + 2, NULL))) {
955 #if !(defined(ODBC_STORAGE) || defined(IMAP_STORAGE))
968 for (; *
input; input++) {
973 if (bufptr == buf + buflen - 1) {
999 if (saydurationminfo) {
1016 if (maxdeletedmsg) {
1025 ast_copy_string(vmu->imapfolder, imapfolder,
sizeof(vmu->imapfolder));
1040 if (!strcasecmp(var,
"attach")) {
1042 }
else if (!strcasecmp(var,
"attachfmt")) {
1044 }
else if (!strcasecmp(var,
"serveremail")) {
1046 }
else if (!strcasecmp(var,
"emailbody")) {
1048 }
else if (!strcasecmp(var,
"emailsubject")) {
1050 }
else if (!strcasecmp(var,
"language")) {
1052 }
else if (!strcasecmp(var,
"tz")) {
1054 }
else if (!strcasecmp(var,
"locale")) {
1057 }
else if (!strcasecmp(var,
"imapuser")) {
1059 vmu->imapversion = imapversion;
1060 }
else if (!strcasecmp(var,
"imappassword") || !strcasecmp(var,
"imapsecret")) {
1062 vmu->imapversion = imapversion;
1063 }
else if (!strcasecmp(var,
"imapfolder")) {
1065 }
else if (!strcasecmp(var,
"imapvmshareid")) {
1066 ast_copy_string(vmu->imapvmshareid, value,
sizeof(vmu->imapvmshareid));
1067 vmu->imapversion = imapversion;
1069 }
else if (!strcasecmp(var,
"delete") || !strcasecmp(var,
"deletevoicemail")) {
1071 }
else if (!strcasecmp(var,
"saycid")){
1073 }
else if (!strcasecmp(var,
"sendvoicemail")){
1075 }
else if (!strcasecmp(var,
"review")){
1077 }
else if (!strcasecmp(var,
"tempgreetwarn")){
1079 }
else if (!strcasecmp(var,
"messagewrap")){
1081 }
else if (!strcasecmp(var,
"operator")) {
1083 }
else if (!strcasecmp(var,
"envelope")){
1085 }
else if (!strcasecmp(var,
"moveheard")){
1087 }
else if (!strcasecmp(var,
"sayduration")){
1089 }
else if (!strcasecmp(var,
"saydurationm")){
1090 if (sscanf(value,
"%30d", &x) == 1) {
1095 }
else if (!strcasecmp(var,
"forcename")){
1097 }
else if (!strcasecmp(var,
"forcegreetings")){
1099 }
else if (!strcasecmp(var,
"callback")) {
1101 }
else if (!strcasecmp(var,
"dialout")) {
1103 }
else if (!strcasecmp(var,
"exitcontext")) {
1105 }
else if (!strcasecmp(var,
"minsecs")) {
1106 if (sscanf(value,
"%30d", &x) == 1 && x >= 0) {
1109 ast_log(
LOG_WARNING,
"Invalid min message length of %s. Using global value %d\n", value, vmminsecs);
1112 }
else if (!strcasecmp(var,
"maxmessage") || !strcasecmp(var,
"maxsecs")) {
1120 if (!strcasecmp(var,
"maxmessage"))
1121 ast_log(
AST_LOG_WARNING,
"Option 'maxmessage' has been deprecated in favor of 'maxsecs'. Please make that change in your voicemail config.\n");
1122 }
else if (!strcasecmp(var,
"maxmsg")) {
1123 vmu->
maxmsg = atoi(value);
1132 }
else if (!strcasecmp(var,
"nextaftercmd")) {
1134 }
else if (!strcasecmp(var,
"backupdeleted")) {
1135 if (sscanf(value,
"%30d", &x) == 1)
1143 ast_log(
AST_LOG_WARNING,
"Invalid number of deleted messages saved per mailbox backupdeleted=%s. Using default value %d\n", value,
MAXMSG);
1149 }
else if (!strcasecmp(var,
"volgain")) {
1150 sscanf(value,
"%30lf", &vmu->
volgain);
1151 }
else if (!strcasecmp(var,
"passwordlocation")) {
1152 if (!strcasecmp(value,
"spooldir")) {
1157 }
else if (!strcasecmp(var,
"options")) {
1164 int fds[2], pid = 0;
1166 memset(buf, 0, len);
1169 snprintf(buf, len,
"FAILURE: Pipe failed: %s", strerror(
errno));
1178 snprintf(buf, len,
"FAILURE: Fork failed");
1182 if (read(fds[0], buf, len) < 0) {
1194 dup2(fds[1], STDOUT_FILENO);
1200 execv(arg.v[0], arg.v);
1201 printf(
"FAILURE: %s", strerror(
errno));
1218 if (strlen(password) < minpassword)
1224 char cmd[255], buf[255];
1228 snprintf(cmd,
sizeof(cmd),
"%s %s %s %s %s", ext_pass_check_cmd, vmu->
mailbox, vmu->
context, vmu->
password, password);
1231 if (!strncasecmp(buf,
"VALID", 5)) {
1232 ast_debug(3,
"Passed password check: '%s'\n", buf);
1234 }
else if (!strncasecmp(buf,
"FAILURE", 7)) {
1259 if (!strcmp(vmu->
password, password)) {
1264 if (strlen(password) > 10) {
1284 while ((s =
strsep(&stringp,
"|"))) {
1286 if ((var =
strsep(&value,
"=")) && value) {
1299 for (;
var; var = var->
next) {
1300 if (!strcasecmp(var->
name,
"vmsecret")) {
1302 }
else if (!strcasecmp(var->
name,
"secret") || !strcasecmp(var->
name,
"password")) {
1306 "\n\tmust be reset in voicemail.conf.\n", retval->
mailbox);
1311 }
else if (!strcasecmp(var->
name,
"uniqueid")) {
1313 }
else if (!strcasecmp(var->
name,
"pager")) {
1315 }
else if (!strcasecmp(var->
name,
"email")) {
1317 }
else if (!strcasecmp(var->
name,
"fullname")) {
1319 }
else if (!strcasecmp(var->
name,
"context")) {
1321 }
else if (!strcasecmp(var->
name,
"emailsubject")) {
1324 }
else if (!strcasecmp(var->
name,
"emailbody")) {
1328 }
else if (!strcasecmp(var->
name,
"imapuser")) {
1330 retval->imapversion = imapversion;
1331 }
else if (!strcasecmp(var->
name,
"imappassword") || !strcasecmp(var->
name,
"imapsecret")) {
1333 retval->imapversion = imapversion;
1334 }
else if (!strcasecmp(var->
name,
"imapfolder")) {
1336 }
else if (!strcasecmp(var->
name,
"imapvmshareid")) {
1338 retval->imapversion = imapversion;
1357 for (i = 0; i < strlen(key); ++i) {
1382 if ((retval = (ivm ? ivm :
ast_calloc(1,
sizeof(*retval))))) {
1384 memset(retval, 0,
sizeof(*retval));
1425 context =
"default";
1429 if (cur->imapversion != imapversion) {
1435 if (context && (!strcasecmp(context, cur->context)) && (!strcasecmp(mailbox, cur->mailbox)))
1440 if ((vmu = (ivm ? ivm :
ast_malloc(
sizeof(*vmu))))) {
1472 if ((!context || !strcasecmp(context, cur->
context)) &&
1473 (!strcasecmp(mailbox, cur->
mailbox)))
1504 char *category = NULL, *
value = NULL, *
new = NULL;
1505 const char *tmp = NULL;
1507 char secretfn[PATH_MAX] =
"";
1516 snprintf(secretfn,
sizeof(secretfn),
"%s%s/%s/secret.conf", VM_SPOOL_DIR, vmu->
context, vmu->
mailbox);
1519 ast_verb(4,
"Writing voicemail password to file %s succeeded\n", secretfn);
1524 ast_verb(4,
"Writing voicemail password to file %s failed, falling back to config file\n", secretfn);
1530 if (!strcasecmp(category, vmu->
context)) {
1535 value = strstr(tmp,
",");
1538 sprintf(
new,
"%s", newpassword);
1540 new =
ast_alloca((strlen(value) + strlen(newpassword) + 1));
1541 sprintf(
new,
"%s%s", newpassword, value);
1553 ast_test_suite_event_notify(
"PASSWORDCHANGED",
"Message: voicemail.conf updated with new password\r\nPasswordSource: voicemail.conf");
1570 ast_debug(4,
"users.conf: %s\n", category);
1571 if (!strcasecmp(category, vmu->
mailbox)) {
1573 ast_debug(3,
"looks like we need to make vmsecret!\n");
1579 sprintf(
new,
"%s", newpassword);
1581 ast_debug(4,
"failed to get category!\n");
1610 snprintf(buf,
sizeof(buf),
"%s %s %s %s", ext_pass_cmd, vmu->
context, vmu->
mailbox, newpassword);
1611 ast_debug(1,
"External password: %s\n",buf);
1635 return snprintf(dest, len,
"%s%s/%s/%s", VM_SPOOL_DIR, context, ext, folder);
1650 static int make_file(
char *dest,
const int len,
const char *dir,
const int num)
1652 return snprintf(dest, len,
"%s/msg%04d", dir, num);
1659 int pfd = mkstemp(
template);
1662 p = fdopen(pfd,
"w+");
1684 make_dir(dest, len, context, ext, folder);
1714 if (vmu &&
id == 0) {
1715 return vmu->imapfolder;
1718 return (
id >= 0 &&
id <
ARRAY_LEN(mailbox_folders)) ? mailbox_folders[
id] :
"Unknown";
1725 for (i = 0; i <
ARRAY_LEN(mailbox_folders); i++) {
1726 if (strcasecmp(name, mailbox_folders[i]) == 0) {
1750 int arraysize = (vmu->
maxmsg > count_msg ? vmu->
maxmsg : count_msg);
1763 if (arraysize > 0) {
1781 static void vm_imap_delete(
char *file,
int msgnum,
struct ast_vm_user *vmu)
1785 unsigned long messageNum;
1788 if (msgnum < 0 && !imapgreetings) {
1793 if (!(vms = get_vm_state_by_mailbox(vmu->
mailbox, vmu->
context, 1)) && !(vms = get_vm_state_by_mailbox(vmu->
mailbox, vmu->
context, 0))) {
1794 ast_log(
LOG_WARNING,
"Couldn't find a vm_state for mailbox %s. Unable to set \\DELETED flag for message %d\n", vmu->
mailbox, msgnum);
1799 imap_delete_old_greeting(file, vms);
1805 messageNum = vms->msgArray[msgnum];
1806 if (messageNum == 0) {
1807 ast_log(
LOG_WARNING,
"msgnum %d, mailbox message %lu is zero.\n", msgnum, messageNum);
1811 ast_log(
LOG_DEBUG,
"deleting msgnum %d, which is mailbox message %lu\n", msgnum, messageNum);
1813 snprintf (arg,
sizeof(arg),
"%lu", messageNum);
1815 mail_setflag (vms->mailstream, arg,
"\\DELETED");
1816 mail_expunge(vms->mailstream);
1820 static int imap_retrieve_greeting(
const char *dir,
const int msgnum,
struct ast_vm_user *vmu)
1823 char *file, *filename;
1831 if (msgnum > -1 || !imapgreetings) {
1838 ast_debug (1,
"Failed to procure file name from directory passed.\n");
1844 if (!(vms_p = get_vm_state_by_mailbox(vmu->
mailbox, vmu->
context, 1)) &&
1845 !(vms_p = get_vm_state_by_mailbox(vmu->
mailbox, vmu->
context, 0))) {
1850 if (!(vms_p = create_vm_state_from_user(vmu))) {
1857 *vms_p->introfn =
'\0';
1861 if (!vms_p->mailstream) {
1868 for (i = 0; i < vms_p->mailstream->nmsgs; i++) {
1869 mail_fetchstructure(vms_p->mailstream, i + 1, &body);
1871 if (body->nested.part && body->nested.part->next && body->nested.part->next->body.parameter->value) {
1872 attachment =
ast_strdupa(body->nested.part->next->body.parameter->value);
1878 filename =
strsep(&attachment,
".");
1879 if (!strcmp(filename, file)) {
1881 vms_p->msgArray[vms_p->
curmsg] = i + 1;
1882 save_body(body, vms_p,
"2", attachment, 0);
1892 static int imap_retrieve_file(
const char *dir,
const int msgnum,
const char *
mailbox,
const char *
context)
1895 char *header_content;
1896 char *attachedfilefmt;
1899 char text_file[PATH_MAX];
1900 FILE *text_file_ptr;
1904 if (!(vmu =
find_user(NULL, context, mailbox))) {
1910 if (imapgreetings) {
1911 res = imap_retrieve_greeting(dir, msgnum, vmu);
1922 if (!(vms = get_vm_state_by_mailbox(vmu->
mailbox, vmu->
context, 1)) && !(vms = get_vm_state_by_mailbox(vmu->
mailbox, vmu->
context, 0))) {
1936 snprintf(vms->introfn,
sizeof(vms->introfn),
"%sintro", vms->
fn);
1945 ast_log(
LOG_DEBUG,
"Before mail_fetchheaders, curmsg is: %d, imap messages is %lu\n", msgnum, vms->msgArray[msgnum]);
1946 if (vms->msgArray[msgnum] == 0) {
1954 header_content = mail_fetchheader (vms->mailstream, vms->msgArray[msgnum]);
1958 ast_log(
LOG_ERROR,
"Could not fetch header for message number %ld\n", vms->msgArray[msgnum]);
1964 mail_fetchstructure(vms->mailstream, vms->msgArray[msgnum], &body);
1968 if (body->nested.part && body->nested.part->next && body->nested.part->next->body.parameter->value) {
1969 attachedfilefmt =
ast_strdupa(body->nested.part->next->body.parameter->value);
1978 strsep(&attachedfilefmt,
".");
1979 if (!attachedfilefmt) {
1980 ast_log(
LOG_ERROR,
"File format could not be obtained from IMAP message attachment\n");
1985 save_body(body, vms,
"2", attachedfilefmt, 0);
1986 if (save_body(body, vms,
"3", attachedfilefmt, 1)) {
1987 *vms->introfn =
'\0';
1991 snprintf(text_file,
sizeof(text_file),
"%s.%s", vms->
fn,
"txt");
1993 if (!(text_file_ptr = fopen(text_file,
"w"))) {
1997 fprintf(text_file_ptr,
"%s\n",
"[message]");
1999 get_header_by_tag(header_content,
"X-Asterisk-VM-Caller-ID-Name:", buf,
sizeof(buf));
2000 fprintf(text_file_ptr,
"callerid=\"%s\" ",
S_OR(buf,
""));
2001 get_header_by_tag(header_content,
"X-Asterisk-VM-Caller-ID-Num:", buf,
sizeof(buf));
2002 fprintf(text_file_ptr,
"<%s>\n",
S_OR(buf,
""));
2003 get_header_by_tag(header_content,
"X-Asterisk-VM-Context:", buf,
sizeof(buf));
2004 fprintf(text_file_ptr,
"context=%s\n",
S_OR(buf,
""));
2005 get_header_by_tag(header_content,
"X-Asterisk-VM-Orig-time:", buf,
sizeof(buf));
2006 fprintf(text_file_ptr,
"origtime=%s\n",
S_OR(buf,
""));
2007 get_header_by_tag(header_content,
"X-Asterisk-VM-Duration:", buf,
sizeof(buf));
2008 fprintf(text_file_ptr,
"duration=%s\n",
S_OR(buf,
""));
2009 get_header_by_tag(header_content,
"X-Asterisk-VM-Category:", buf,
sizeof(buf));
2010 fprintf(text_file_ptr,
"category=%s\n",
S_OR(buf,
""));
2011 get_header_by_tag(header_content,
"X-Asterisk-VM-Flag:", buf,
sizeof(buf));
2012 fprintf(text_file_ptr,
"flag=%s\n",
S_OR(buf,
""));
2013 fclose(text_file_ptr);
2020 static int folder_int(
const char *folder)
2026 if (!strcasecmp(folder, imapfolder)) {
2028 }
else if (!strcasecmp(folder,
"Old")) {
2030 }
else if (!strcasecmp(folder,
"Work")) {
2032 }
else if (!strcasecmp(folder,
"Family")) {
2034 }
else if (!strcasecmp(folder,
"Friends")) {
2036 }
else if (!strcasecmp(folder,
"Cust1")) {
2038 }
else if (!strcasecmp(folder,
"Cust2")) {
2040 }
else if (!strcasecmp(folder,
"Cust3")) {
2042 }
else if (!strcasecmp(folder,
"Cust4")) {
2044 }
else if (!strcasecmp(folder,
"Cust5")) {
2046 }
else if (!strcasecmp(folder,
"Urgent")) {
2053 static int __messagecount(
const char *context,
const char *mailbox,
const char *folder)
2061 int fold = folder_int(folder);
2074 vmu =
find_user(&vmus, context, mailbox);
2080 if (vmu->imapuser[0] ==
'\0') {
2087 if (vmu->imapuser[0] ==
'\0') {
2095 vms_p = get_vm_state_by_imapuser(vmu->imapuser, 1);
2097 vms_p = get_vm_state_by_mailbox(mailbox, context, 1);
2100 ast_debug(3,
"Returning before search - user is logged in\n");
2110 vms_p = get_vm_state_by_imapuser(vmu->imapuser, 0);
2112 vms_p = get_vm_state_by_mailbox(mailbox, context, 0);
2116 vms_p = create_vm_state_from_user(vmu);
2118 ret = init_mailstream(vms_p, fold);
2119 if (!vms_p->mailstream) {
2125 pgm = mail_newsearchpgm ();
2126 hdr = mail_newsearchheader (
"X-Asterisk-VM-Extension", (
char *)(!
ast_strlen_zero(vmu->imapvmshareid) ? vmu->imapvmshareid : mailbox));
2127 hdr->next = mail_newsearchheader(
"X-Asterisk-VM-Context", (
char *)
S_OR(context,
"default"));
2153 vms_p->vmArrayIndex = 0;
2154 mail_search_full (vms_p->mailstream, NULL, pgm, NIL);
2155 if (fold == 0 && urgent == 0)
2159 if (fold == 0 && urgent == 1)
2162 mail_free_searchpgm(&pgm);
2165 return vms_p->vmArrayIndex;
2168 mail_ping(vms_p->mailstream);
2177 check_quota(vms, vmu->imapfolder);
2178 if (vms->quota_limit && vms->quota_usage >= vms->quota_limit) {
2179 ast_debug(1,
"*** QUOTA EXCEEDED!! %u >= %u\n", vms->quota_usage, vms->quota_limit);
2187 ast_log(
LOG_WARNING,
"Unable to leave message since we will exceed the maximum number of messages allowed (%u >= %u)\n", msgnum, vmu->
maxmsg);
2205 static int messagecount(
const char *context,
const char *mailbox,
const char *folder)
2208 return __messagecount(context, mailbox,
"INBOX") + __messagecount(context, mailbox,
"Urgent");
2210 return __messagecount(context, mailbox, folder);
2214 static int imap_store_file(
const char *dir,
const char *mailboxuser,
const char *mailboxcontext,
int msgnum,
struct ast_channel *chan,
struct ast_vm_user *vmu,
char *fmt,
int duration,
struct vm_state *vms,
const char *flag)
2218 char introfn[PATH_MAX];
2222 char tmp[80] =
"/tmp/astmail-XXXXXX";
2228 char *imap_flags = NIL;
2234 if(!imapgreetings) {
2241 if (imap_check_limits(chan, vms, vmu, msgcount)) {
2247 ast_debug(3,
"Setting message flag \\\\FLAGGED.\n");
2248 imap_flags =
"\\FLAGGED";
2264 snprintf(introfn,
sizeof(introfn),
"%sintro", fn);
2279 if (!strcmp(fmt,
"wav49"))
2281 ast_debug(3,
"Storing file '%s', format '%s'\n", fn, fmt);
2288 *(vmu->
email) =
'\0';
2292 if (msgnum < 0 && imapgreetings) {
2297 imap_delete_old_greeting(fn, vms);
2303 fn, introfn, fmt, duration, 1, chan, NULL, 1, flag);
2311 *(vmu->
email) =
'\0';
2314 if (fread(buf, len, 1, p) <
len) {
2320 ((
char *) buf)[
len] =
'\0';
2321 INIT(&str, mail_string, buf, len);
2322 ret = init_mailstream(vms, box);
2324 imap_mailbox_name(mailbox,
sizeof(mailbox), vms, box, 1);
2326 if(!mail_append_full(vms->mailstream, mailbox, imap_flags, NIL, &str))
2342 *(vmu->
email) =
'\0';
2361 static int inboxcount2(
const char *mailbox_context,
int *urgentmsgs,
int *newmsgs,
int *oldmsgs)
2363 char tmp[PATH_MAX] =
"";
2375 ast_debug(3,
"Mailbox is set to %s\n", mailbox_context);
2381 context = strchr(tmp,
'@');
2382 if (strchr(mailbox_context,
',')) {
2383 int tmpnew, tmpold, tmpurgent;
2386 while ((cur =
strsep(&mb,
", "))) {
2388 if (
inboxcount2(cur, urgentmsgs ? &tmpurgent : NULL, newmsgs ? &tmpnew : NULL, oldmsgs ? &tmpold : NULL))
2396 *urgentmsgs += tmpurgent;
2407 context =
"default";
2408 mailboxnc = (
char *) mailbox_context;
2417 if ((*newmsgs = __messagecount(context, mailboxnc, vmu->imapfolder)) < 0) {
2424 if ((*oldmsgs = __messagecount(context, mailboxnc,
"Old")) < 0) {
2429 if ((*urgentmsgs = __messagecount(context, mailboxnc,
"Urgent")) < 0) {
2446 static int has_voicemail(
const char *mailbox,
const char *folder)
2448 char tmp[256], *tmp2, *box, *
context;
2451 if (strchr(tmp2,
',') || strchr(tmp2,
'&')) {
2452 while ((box =
strsep(&tmp2,
",&"))) {
2460 if ((context = strchr(tmp,
'@'))) {
2463 context =
"default";
2465 return __messagecount(context, tmp, folder) ? 1 : 0;
2485 struct vm_state *sendvms = NULL, *destvms = NULL;
2486 char messagestring[10];
2487 if (msgnum >= recip->
maxmsg) {
2491 if (!(sendvms = get_vm_state_by_imapuser(vmu->imapuser, 0))) {
2495 if (!(destvms = get_vm_state_by_imapuser(recip->imapuser, 0))) {
2499 snprintf(messagestring,
sizeof(messagestring),
"%ld", sendvms->msgArray[msgnum]);
2501 if ((mail_copy(sendvms->mailstream, messagestring, (
char *)
mbox(vmu, imbox)) == T)) {
2510 static void imap_mailbox_name(
char *spec,
size_t len,
struct vm_state *vms,
int box,
int use_folder)
2512 char tmp[256], *t = tmp;
2513 size_t left =
sizeof(tmp);
2524 snprintf(vms->
vmbox,
sizeof(vms->
vmbox),
"vm-%s",
mbox(NULL, box));
2545 snprintf(spec, len,
"%s%s", tmp, use_folder? vms->imapfolder:
"INBOX");
2547 snprintf(spec, len,
"%s%s", tmp, greetingfolder);
2551 snprintf(spec, len,
"%s%s%c%s", tmp, imapparentfolder, delimiter,
mbox(NULL, box));
2553 snprintf(spec, len,
"%s%s", tmp,
mbox(NULL, box));
2558 static int init_mailstream(
struct vm_state *vms,
int box)
2560 MAILSTREAM *stream = NIL;
2570 if (vms->mailstream == NIL || !vms->mailstream) {
2574 stream = vms->mailstream;
2579 if (delimiter ==
'\0') {
2581 #ifdef USE_SYSTEM_IMAP
2582 #include <imap/linkage.c>
2583 #elif defined(USE_SYSTEM_CCLIENT)
2584 #include <c-client/linkage.c>
2586 #include "linkage.c"
2589 imap_mailbox_name(tmp,
sizeof(tmp), vms, 0, 1);
2591 stream = mail_open (stream, tmp, debug ? OP_DEBUG : NIL);
2593 if (stream == NIL) {
2597 get_mailbox_delimiter(stream);
2599 for (cp = vms->imapfolder; *cp; cp++)
2604 imap_mailbox_name(tmp,
sizeof(tmp), vms, box, 1);
2608 vms->mailstream = mail_open (stream, tmp, debug ? OP_DEBUG : NIL);
2610 if (vms->mailstream == NIL) {
2621 int ret, urgent = 0;
2630 ast_copy_string(vms->imapfolder, vmu->imapfolder,
sizeof(vms->imapfolder));
2631 vms->imapversion = vmu->imapversion;
2632 ast_debug(3,
"Before init_mailstream, user is %s\n", vmu->imapuser);
2634 if ((ret = init_mailstream(vms, box)) || !vms->mailstream) {
2643 ast_debug(3,
"Mailbox name set to: %s, about to check quotas\n",
mbox(vmu, box));
2644 check_quota(vms, (
char *)
mbox(vmu, box));
2648 pgm = mail_newsearchpgm();
2651 hdr = mail_newsearchheader(
"X-Asterisk-VM-Extension", (!
ast_strlen_zero(vmu->imapvmshareid) ? vmu->imapvmshareid : vmu->
mailbox));
2652 hdr->next = mail_newsearchheader(
"X-Asterisk-VM-Context", vmu->
context);
2663 }
else if (box ==
NEW_FOLDER && urgent == 0) {
2673 ast_debug(3,
"Before mail_search_full, user is %s\n", vmu->imapuser);
2675 vms->vmArrayIndex = 0;
2676 mail_search_full (vms->mailstream, NULL, pgm, NIL);
2677 vms->
lastmsg = vms->vmArrayIndex - 1;
2678 mail_free_searchpgm(&pgm);
2684 ast_log(
LOG_WARNING,
"The code expects the old messages to be checked first, fix the code.\n");
2695 static void write_file(
char *filename,
char *buffer,
unsigned long len)
2699 output = fopen (filename,
"w");
2700 if (fwrite(buffer, len, 1, output) != 1) {
2701 if (ferror(output)) {
2708 static void update_messages_by_imapuser(
const char *
user,
unsigned long number)
2710 struct vm_state *vms = get_vm_state_by_imapuser(user, 1);
2712 if (!vms && !(vms = get_vm_state_by_imapuser(user, 0))) {
2716 ast_debug(3,
"saving mailbox message number %lu as message %d. Interactive set to %d\n", number, vms->vmArrayIndex, vms->interactive);
2719 if (vms->vmArrayIndex >= vms->msg_array_max) {
2720 long *new_mem =
ast_realloc(vms->msgArray, 2 * vms->msg_array_max *
sizeof(
long));
2724 vms->msgArray = new_mem;
2725 vms->msg_array_max *= 2;
2728 vms->msgArray[vms->vmArrayIndex++] = number;
2731 void mm_searched(MAILSTREAM *stream,
unsigned long number)
2733 char *mailbox = stream->mailbox, buf[1024] =
"", *
user;
2735 if (!(user = get_user_by_mailbox(mailbox, buf,
sizeof(buf))))
2738 update_messages_by_imapuser(user, number);
2741 static struct ast_vm_user *find_user_realtime_imapuser(
const char *imapuser)
2766 void mm_exists(MAILSTREAM * stream,
unsigned long number)
2769 ast_debug(4,
"Entering EXISTS callback for message %ld\n", number);
2770 if (number == 0)
return;
2775 void mm_expunged(MAILSTREAM * stream,
unsigned long number)
2778 ast_debug(4,
"Entering EXPUNGE callback for message %ld\n", number);
2779 if (number == 0)
return;
2784 void mm_flags(MAILSTREAM * stream,
unsigned long number)
2787 ast_debug(4,
"Entering FLAGS callback for message %ld\n", number);
2788 if (number == 0)
return;
2793 void mm_notify(MAILSTREAM * stream,
char *
string,
long errflg)
2795 ast_debug(5,
"Entering NOTIFY callback, errflag is %ld, string is %s\n", errflg,
string);
2796 mm_log (
string, errflg);
2800 void mm_list(MAILSTREAM * stream,
int delim,
char *mailbox,
long attributes)
2802 if (delimiter ==
'\0') {
2806 ast_debug(5,
"Delimiter set to %c and mailbox %s\n", delim, mailbox);
2807 if (attributes & LATT_NOINFERIORS)
2809 if (attributes & LATT_NOSELECT)
2811 if (attributes & LATT_MARKED)
2813 if (attributes & LATT_UNMARKED)
2818 void mm_lsub(MAILSTREAM * stream,
int delim,
char *mailbox,
long attributes)
2820 ast_debug(5,
"Delimiter set to %c and mailbox %s\n", delim, mailbox);
2821 if (attributes & LATT_NOINFERIORS)
2823 if (attributes & LATT_NOSELECT)
2825 if (attributes & LATT_MARKED)
2827 if (attributes & LATT_UNMARKED)
2832 void mm_status(MAILSTREAM * stream,
char *mailbox, MAILSTATUS *
status)
2835 if (status->flags & SA_MESSAGES)
2837 if (status->flags & SA_RECENT)
2839 if (status->flags & SA_UNSEEN)
2841 if (status->flags & SA_UIDVALIDITY)
2843 if (status->flags & SA_UIDNEXT)
2849 void mm_log(
char *
string,
long errflg)
2851 switch ((
short) errflg) {
2853 ast_debug(1,
"IMAP Info: %s\n",
string);
2866 void mm_dlog(
char *
string)
2872 void mm_login(NETMBX * mb,
char *user,
char *pwd,
long trial)
2876 ast_debug(4,
"Entering callback mm_login\n");
2885 if (!strcasecmp(mb->user, vmu->imapuser)) {
2891 if ((vmu = find_user_realtime_imapuser(mb->user))) {
2900 void mm_critical(MAILSTREAM * stream)
2905 void mm_nocritical(MAILSTREAM * stream)
2910 long mm_diskerror(MAILSTREAM * stream,
long errcode,
long serious)
2912 kill (getpid (), SIGSTOP);
2917 void mm_fatal(
char *
string)
2923 static void mm_parsequota(MAILSTREAM *stream,
unsigned char *msg, QUOTALIST *pquota)
2926 char *mailbox = stream->mailbox, *
user;
2927 char buf[1024] =
"";
2928 unsigned long usage = 0, limit = 0;
2931 usage = pquota->usage;
2932 limit = pquota->limit;
2933 pquota = pquota->next;
2936 if (!(user = get_user_by_mailbox(mailbox, buf,
sizeof(buf))) || (!(vms = get_vm_state_by_imapuser(user, 2)) && !(vms = get_vm_state_by_imapuser(user, 0)))) {
2941 ast_debug(3,
"User %s usage is %lu, limit is %lu\n", user, usage, limit);
2943 vms->quota_usage = usage;
2944 vms->quota_limit = limit;
2947 static char *get_header_by_tag(
char *header,
char *tag,
char *buf,
size_t len)
2949 char *start, *eol_pnt;
2955 taglen = strlen(tag) + 1;
2959 if (!(start = strstr(header, tag)))
2963 memset(buf, 0, len);
2966 if ((eol_pnt = strchr(buf,
'\r')) || (eol_pnt = strchr(buf,
'\n')))
2971 static char *get_user_by_mailbox(
char *mailbox,
char *buf,
size_t len)
2973 char *start, *
quote, *eol_pnt;
2978 if (!(start = strstr(mailbox,
"/user=")))
2983 if (!(quote = strchr(buf,
'\"'))) {
2984 if (!(eol_pnt = strchr(buf,
'/')))
2985 eol_pnt = strchr(buf,
'}');
2989 eol_pnt = strchr(buf+1,
'\"');
2999 pthread_once(&ts_vmstate.once, ts_vmstate.key_init);
3000 if ((vms_p = pthread_getspecific(ts_vmstate.key)) && !strcmp(vms_p->imapuser, vmu->imapuser) && !strcmp(vms_p->
username, vmu->
mailbox)) {
3006 if (!(vms_p =
ast_calloc(1,
sizeof(*vms_p))))
3008 ast_copy_string(vms_p->imapuser, vmu->imapuser,
sizeof(vms_p->imapuser));
3009 ast_copy_string(vms_p->imapfolder, vmu->imapfolder,
sizeof(vms_p->imapfolder));
3012 vms_p->mailstream = NIL;
3013 vms_p->imapversion = vmu->imapversion;
3019 init_vm_state(vms_p);
3020 vmstate_insert(vms_p);
3024 static struct vm_state *get_vm_state_by_imapuser(
const char *user,
int interactive)
3026 struct vmstate *vlist = NULL;
3030 pthread_once(&ts_vmstate.once, ts_vmstate.key_init);
3031 vms = pthread_getspecific(ts_vmstate.key);
3038 ast_debug(3,
"error: vms is NULL for %s\n", user);
3041 if (vlist->vms->imapversion != imapversion) {
3044 if (!vlist->vms->imapuser) {
3045 ast_debug(3,
"error: imapuser is NULL for %s\n", user);
3049 if (!strcmp(vlist->vms->imapuser, user) && (interactive == 2 || vlist->vms->interactive == interactive)) {
3056 ast_debug(3,
"%s not found in vmstates\n", user);
3061 static struct vm_state *get_vm_state_by_mailbox(
const char *mailbox,
const char *context,
int interactive)
3064 struct vmstate *vlist = NULL;
3065 const char *local_context =
S_OR(context,
"default");
3069 pthread_once(&ts_vmstate.once, ts_vmstate.key_init);
3070 vms = pthread_getspecific(ts_vmstate.key);
3077 ast_debug(3,
"error: vms is NULL for %s\n", mailbox);
3080 if (vlist->vms->imapversion != imapversion) {
3083 if (!vlist->vms->username || !vlist->vms->context) {
3084 ast_debug(3,
"error: username is NULL for %s\n", mailbox);
3088 ast_debug(3,
"comparing mailbox %s@%s (i=%d) to vmstate mailbox %s@%s (i=%d)\n", mailbox, local_context, interactive, vlist->vms->username, vlist->vms->context, vlist->vms->interactive);
3090 if (!strcmp(vlist->vms->username, mailbox) && !strcmp(vlist->vms->context, local_context) && vlist->vms->interactive == interactive) {
3098 ast_debug(3,
"%s not found in vmstates\n", mailbox);
3103 static void vmstate_insert(
struct vm_state *vms)
3111 if (vms->interactive == 1) {
3117 vms->vmArrayIndex = altvms->vmArrayIndex;
3122 vms->persist_vms = altvms;
3124 #ifdef REALLY_FAST_EVEN_IF_IT_MEANS_RESOURCE_LEAKS
3125 vms->mailstream = altvms->mailstream;
3127 vms->mailstream = NIL;
3138 ast_debug(3,
"Inserting vm_state for user:%s, mailbox %s\n", vms->imapuser, vms->
username);
3145 static void vmstate_delete(
struct vm_state *vms)
3147 struct vmstate *vc = NULL;
3152 if (vms->interactive == 1 && (altvms = vms->persist_vms)) {
3156 altvms->updated = 1;
3157 vms->mailstream = mail_close(vms->mailstream);
3163 ast_debug(3,
"Removing vm_state for user:%s, mailbox %s\n", vms->imapuser, vms->
username);
3167 if (vc->vms == vms) {
3178 vc->vms->msgArray = NULL;
3179 vc->vms->msg_array_max = 0;
3187 static void set_update(MAILSTREAM * stream)
3190 char *mailbox = stream->mailbox, *
user;
3191 char buf[1024] =
"";
3193 if (!(user = get_user_by_mailbox(mailbox, buf,
sizeof(buf))) || !(vms = get_vm_state_by_imapuser(user, 0))) {
3199 ast_debug(3,
"User %s mailbox set for update.\n", user);
3204 static void init_vm_state(
struct vm_state *vms)
3207 vms->msgArray =
ast_calloc(vms->msg_array_max,
sizeof(
long));
3208 if (!vms->msgArray) {
3210 vms->msg_array_max = 0;
3212 vms->vmArrayIndex = 0;
3216 static int save_body(BODY *body,
struct vm_state *vms,
char *section,
char *
format,
int is_intro)
3220 char *fn = is_intro ? vms->introfn : vms->
fn;
3222 unsigned long newlen;
3225 if (!body || body == NIL)
3229 body_content = mail_fetchbody(vms->mailstream, vms->msgArray[vms->
curmsg], section, &len);
3231 if (body_content != NIL) {
3232 snprintf(filename,
sizeof(filename),
"%s.%s", fn, format);
3234 body_decoded = rfc822_base64((
unsigned char *) body_content, len, &newlen);
3239 write_file(filename, (
char *) body_decoded, newlen);
3241 ast_debug(5,
"Body of message is NULL.\n");
3254 static void get_mailbox_delimiter(MAILSTREAM *stream) {
3256 snprintf(tmp,
sizeof(tmp),
"{%s}", imapserver);
3257 mail_list(stream, tmp,
"*");
3267 static void check_quota(
struct vm_state *vms,
char *mailbox) {
3269 mail_parameters(NULL, SET_QUOTA, (
void *) mm_parsequota);
3270 ast_debug(3,
"Mailbox name set to: %s, about to check quotas\n", mailbox);
3271 if (vms && vms->mailstream != NULL) {
3272 imap_getquotaroot(vms->mailstream, mailbox);
3297 struct generic_prepare_struct {
3305 struct generic_prepare_struct *gps = data;
3309 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->
con, &stmt);
3310 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
3314 res = SQLPrepare(stmt, (
unsigned char *) gps->sql, SQL_NTS);
3315 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
3317 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
3320 for (i = 0; i < gps->argc; i++)
3321 SQLBindParameter(stmt, i + 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(gps->argv[i]), 0, gps->argv[i], 0, NULL);
3340 static int retrieve_file(
char *dir,
int msgnum)
3346 void *fdm = MAP_FAILED;
3347 SQLSMALLINT colcount = 0;
3354 SQLSMALLINT datatype;
3355 SQLSMALLINT decimaldigits;
3356 SQLSMALLINT nullable;
3362 char full_fn[PATH_MAX];
3364 char *argv[] = { dir, msgnums };
3365 struct generic_prepare_struct gps = { .sql = sql, .argc = 2, .argv = argv };
3371 c = strchr(fmt,
'|');
3374 if (!strcasecmp(fmt,
"wav49"))
3376 snprintf(msgnums,
sizeof(msgnums),
"%d", msgnum);
3383 snprintf(full_fn,
sizeof(full_fn),
"%s.txt", fn);
3385 if (!(f = fopen(full_fn,
"w+"))) {
3390 snprintf(full_fn,
sizeof(full_fn),
"%s.%s", fn, fmt);
3391 snprintf(sql,
sizeof(sql),
"SELECT * FROM %s WHERE dir=? AND msgnum=?", odbc_table);
3398 res = SQLFetch(stmt);
3399 if (res == SQL_NO_DATA) {
3400 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
3403 }
else if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
3405 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
3412 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
3416 res = SQLNumResultCols(stmt, &colcount);
3417 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
3419 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
3424 fprintf(f,
"[message]\n");
3425 for (x = 0; x < colcount; x++) {
3428 collen =
sizeof(coltitle);
3429 res = SQLDescribeCol(stmt, x + 1, (
unsigned char *) coltitle,
sizeof(coltitle), &collen,
3430 &datatype, &colsize, &decimaldigits, &nullable);
3431 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
3433 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
3437 if (!strcasecmp(coltitle,
"recording")) {
3439 res = SQLGetData(stmt, x + 1, SQL_BINARY, rowdata, 0, &colsize2);
3443 lseek(fd, fdlen - 1, SEEK_SET);
3444 if (write(fd, tmp, 1) != 1) {
3450 for (offset = 0; offset < colsize2; offset +=
CHUNKSIZE) {
3451 if ((fdm = mmap(NULL,
CHUNKSIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset)) == MAP_FAILED) {
3453 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
3457 res = SQLGetData(stmt, x + 1, SQL_BINARY, fdm,
CHUNKSIZE, NULL);
3459 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
3462 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
3468 if (truncate(full_fn, fdlen) < 0) {
3473 res = SQLGetData(stmt, x + 1, SQL_CHAR, rowdata,
sizeof(rowdata), NULL);
3474 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
3476 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
3480 if (strcasecmp(coltitle,
"msgnum") && strcasecmp(coltitle,
"dir") && f)
3481 fprintf(f,
"%s=%s\n", coltitle, rowdata);
3484 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
3514 char *argv[] = { dir };
3515 struct generic_prepare_struct gps = { .sql = sql, .argc = 1, .argv = argv };
3520 snprintf(sql,
sizeof(sql),
"SELECT msgnum FROM %s WHERE dir=? order by msgnum desc", odbc_table);
3528 res = SQLFetch(stmt);
3529 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
3530 if (res == SQL_NO_DATA) {
3531 ast_log(
AST_LOG_DEBUG,
"Directory '%s' has no messages and therefore no index was retrieved.\n", dir);
3536 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
3540 res = SQLGetData(stmt, 1, SQL_CHAR, rowdata,
sizeof(rowdata), NULL);
3541 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
3543 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
3547 if (sscanf(rowdata,
"%30d", &x) != 1)
3549 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
3567 static int message_exists(
char *dir,
int msgnum)
3575 char *argv[] = { dir, msgnums };
3576 struct generic_prepare_struct gps = { .sql = sql, .argc = 2, .argv = argv };
3581 snprintf(msgnums,
sizeof(msgnums),
"%d", msgnum);
3582 snprintf(sql,
sizeof(sql),
"SELECT COUNT(*) FROM %s WHERE dir=? AND msgnum=?", odbc_table);
3589 res = SQLFetch(stmt);
3590 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
3592 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
3596 res = SQLGetData(stmt, 1, SQL_CHAR, rowdata,
sizeof(rowdata), NULL);
3597 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
3599 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
3603 if (sscanf(rowdata,
"%30d", &x) != 1)
3605 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
3629 char *argv[] = { dir };
3630 struct generic_prepare_struct gps = { .sql = sql, .argc = 1, .argv = argv };
3635 snprintf(sql,
sizeof(sql),
"SELECT COUNT(*) FROM %s WHERE dir=?", odbc_table);
3642 res = SQLFetch(stmt);
3643 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
3645 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
3649 res = SQLGetData(stmt, 1, SQL_CHAR, rowdata,
sizeof(rowdata), NULL);
3650 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
3652 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
3656 if (sscanf(rowdata,
"%30d", &x) != 1)
3658 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
3678 static void delete_file(
const char *sdir,
int smsg)
3683 char *argv[] = { NULL, msgnums };
3684 struct generic_prepare_struct gps = { .sql = sql, .argc = 2, .argv = argv };
3691 snprintf(msgnums,
sizeof(msgnums),
"%d", smsg);
3692 snprintf(sql,
sizeof(sql),
"DELETE FROM %s WHERE dir=? AND msgnum=?", odbc_table);
3697 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
3715 static void copy_file(
char *sdir,
int smsg,
char *ddir,
int dmsg,
char *dmailboxuser,
char *dmailboxcontext)
3722 char *argv[] = { ddir, msgnumd, dmailboxuser, dmailboxcontext, sdir, msgnums };
3723 struct generic_prepare_struct gps = { .sql = sql, .argc = 6, .argv = argv };
3728 snprintf(msgnums,
sizeof(msgnums),
"%d", smsg);
3729 snprintf(msgnumd,
sizeof(msgnumd),
"%d", dmsg);
3730 snprintf(sql,
sizeof(sql),
"INSERT INTO %s (dir, msgnum, context, macrocontext, callerid, origtime, duration, recording, flag, mailboxuser, mailboxcontext) SELECT ?,?,context,macrocontext,callerid,origtime,duration,recording,flag,?,? FROM %s WHERE dir=? AND msgnum=?", odbc_table, odbc_table);
3733 ast_log(
AST_LOG_WARNING,
"SQL Execute error!\n[%s] (You probably don't have MySQL 4.1 or later installed)\n\n", sql);
3735 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
3742 struct insert_data {
3745 const char *msgnums;
3750 const char *macrocontext;
3751 const char *callerid;
3752 const char *origtime;
3753 const char *duration;
3754 const char *mailboxuser;
3755 const char *mailboxcontext;
3756 const char *category;
3760 static SQLHSTMT insert_data_cb(
struct odbc_obj *obj,
void *vdata)
3762 struct insert_data *data = vdata;
3766 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->
con, &stmt);
3767 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
3769 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
3773 SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->dir), 0, (
void *) data->dir, 0, NULL);
3774 SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->msgnums), 0, (
void *) data->msgnums, 0, NULL);
3775 SQLBindParameter(stmt, 3, SQL_PARAM_INPUT, SQL_C_BINARY, SQL_LONGVARBINARY, data->datalen, 0, (
void *) data->data, data->datalen, &data->indlen);
3776 SQLBindParameter(stmt, 4, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->context), 0, (
void *) data->context, 0, NULL);
3777 SQLBindParameter(stmt, 5, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->macrocontext), 0, (
void *) data->macrocontext, 0, NULL);
3778 SQLBindParameter(stmt, 6, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->callerid), 0, (
void *) data->callerid, 0, NULL);
3779 SQLBindParameter(stmt, 7, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->origtime), 0, (
void *) data->origtime, 0, NULL);
3780 SQLBindParameter(stmt, 8, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->duration), 0, (
void *) data->duration, 0, NULL);
3781 SQLBindParameter(stmt, 9, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->mailboxuser), 0, (
void *) data->mailboxuser, 0, NULL);
3782 SQLBindParameter(stmt, 10, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->mailboxcontext), 0, (
void *) data->mailboxcontext, 0, NULL);
3783 SQLBindParameter(stmt, 11, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->flag), 0, (
void *) data->flag, 0, NULL);
3785 SQLBindParameter(stmt, 12, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->category), 0, (
void *) data->category, 0, NULL);
3787 res = SQLExecDirect(stmt, (
unsigned char *) data->sql, SQL_NTS);
3788 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
3790 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
3810 static int store_file(
const char *dir,
const char *mailboxuser,
const char *mailboxcontext,
int msgnum)
3814 void *fdm = MAP_FAILED;
3820 char full_fn[PATH_MAX];
3825 struct insert_data idata = { .sql = sql, .msgnums = msgnums, .dir = dir, .mailboxuser = mailboxuser, .mailboxcontext = mailboxcontext,
3826 .context =
"", .macrocontext =
"", .callerid =
"", .origtime =
"", .duration =
"", .category =
"", .flag =
"" };
3837 c = strchr(fmt,
'|');
3840 if (!strcasecmp(fmt,
"wav49"))
3842 snprintf(msgnums,
sizeof(msgnums),
"%d", msgnum);
3847 snprintf(full_fn,
sizeof(full_fn),
"%s.txt", fn);
3849 snprintf(full_fn,
sizeof(full_fn),
"%s.%s", fn, fmt);
3850 fd = open(full_fn, O_RDWR);
3861 idata.macrocontext =
"";
3864 idata.callerid =
"";
3867 idata.origtime =
"";
3870 idata.duration =
"";
3873 idata.category =
"";
3879 fdlen = lseek(fd, 0, SEEK_END);
3880 if (fdlen < 0 || lseek(fd, 0, SEEK_SET) < 0) {
3885 fdm = mmap(NULL, fdlen, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
3886 if (fdm == MAP_FAILED) {
3892 idata.datalen = idata.indlen = fdlen;
3895 snprintf(sql,
sizeof(sql),
"INSERT INTO %s (dir,msgnum,recording,context,macrocontext,callerid,origtime,duration,mailboxuser,mailboxcontext,flag,category) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)", odbc_table);
3897 snprintf(sql,
sizeof(sql),
"INSERT INTO %s (dir,msgnum,recording,context,macrocontext,callerid,origtime,duration,mailboxuser,mailboxcontext,flag) VALUES (?,?,?,?,?,?,?,?,?,?,?)", odbc_table);
3900 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
3911 if (fdm != MAP_FAILED)
3931 static void rename_file(
char *sdir,
int smsg,
char *mailboxuser,
char *mailboxcontext,
char *ddir,
int dmsg)
3938 char *argv[] = { ddir, msgnumd, mailboxuser, mailboxcontext, sdir, msgnums };
3939 struct generic_prepare_struct gps = { .sql = sql, .argc = 6, .argv = argv };
3944 snprintf(msgnums,
sizeof(msgnums),
"%d", smsg);
3945 snprintf(msgnumd,
sizeof(msgnumd),
"%d", dmsg);
3946 snprintf(sql,
sizeof(sql),
"UPDATE %s SET dir=?, msgnum=?, mailboxuser=?, mailboxcontext=? WHERE dir=? AND msgnum=?", odbc_table);
3951 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
3969 static int remove_file(
char *dir,
int msgnum)
3972 char full_fn[PATH_MAX];
3976 snprintf(msgnums,
sizeof(msgnums),
"%d", msgnum);
3981 snprintf(full_fn,
sizeof(full_fn),
"%s.txt", fn);
3986 #ifndef IMAP_STORAGE
4001 struct dirent *vment = NULL;
4006 if ((vmdir = opendir(dir))) {
4007 while ((vment = readdir(vmdir))) {
4008 if (strlen(vment->d_name) > 7 && !strncmp(vment->d_name + 7,
".txt", 4)) {
4028 char stxt[PATH_MAX];
4029 char dtxt[PATH_MAX];
4031 snprintf(stxt,
sizeof(stxt),
"%s.txt", sfn);
4032 snprintf(dtxt,
sizeof(dtxt),
"%s.txt", dfn);
4055 struct dirent *msgdirent;
4064 if (!(msgdir = opendir(dir))) {
4068 while ((msgdirent = readdir(msgdir))) {
4069 if (sscanf(msgdirent->d_name,
"msg%30d.%3s", &msgdirint, extension) == 2 && !strcmp(extension,
"txt") && msgdirint <
MAXMSGLIMIT) {
4072 ast_debug(4,
"%s map[%d] = %d, count = %d\n", dir, msgdirint, map[msgdirint], stopcount);
4077 for (x = 0; x < vmu->
maxmsg; x++) {
4080 }
else if (map[x] == 0 && !stopcount) {
4090 #ifndef IMAP_STORAGE
4101 static int copy(
char *infile,
char *outfile)
4109 #ifdef HARDLINK_WHEN_POSSIBLE
4111 if (link(infile, outfile)) {
4113 if ((ifd = open(infile, O_RDONLY)) < 0) {
4123 len = read(ifd, buf,
sizeof(buf));
4130 res = write(ofd, buf, len);
4131 if (
errno == ENOMEM ||
errno == ENOSPC || res != len) {
4142 #ifdef HARDLINK_WHEN_POSSIBLE
4161 char frompath2[PATH_MAX], topath2[PATH_MAX];
4163 const char *origmailbox = NULL, *context = NULL, *macrocontext = NULL, *
exten = NULL, *priority = NULL, *callerchan = NULL, *callerid = NULL, *origdate = NULL, *origtime = NULL, *category = NULL, *duration = NULL;
4165 snprintf(frompath2,
sizeof(frompath2),
"%s.txt", frompath);
4166 snprintf(topath2,
sizeof(topath2),
"%s.txt", topath);
4170 for (tmp = var; tmp; tmp = tmp->
next) {
4171 if (!strcasecmp(tmp->
name,
"origmailbox")) {
4172 origmailbox = tmp->
value;
4173 }
else if (!strcasecmp(tmp->
name,
"context")) {
4174 context = tmp->
value;
4175 }
else if (!strcasecmp(tmp->
name,
"macrocontext")) {
4176 macrocontext = tmp->
value;
4177 }
else if (!strcasecmp(tmp->
name,
"exten")) {
4179 }
else if (!strcasecmp(tmp->
name,
"priority")) {
4180 priority = tmp->
value;
4181 }
else if (!strcasecmp(tmp->
name,
"callerchan")) {
4182 callerchan = tmp->
value;
4183 }
else if (!strcasecmp(tmp->
name,
"callerid")) {
4184 callerid = tmp->
value;
4185 }
else if (!strcasecmp(tmp->
name,
"origdate")) {
4186 origdate = tmp->
value;
4187 }
else if (!strcasecmp(tmp->
name,
"origtime")) {
4188 origtime = tmp->
value;
4189 }
else if (!strcasecmp(tmp->
name,
"category")) {
4190 category = tmp->
value;
4191 }
else if (!strcasecmp(tmp->
name,
"duration")) {
4192 duration = tmp->
value;
4195 ast_store_realtime(
"voicemail_data",
"filename", topath,
"origmailbox", origmailbox,
"context", context,
"macrocontext", macrocontext,
"exten", exten,
"priority", priority,
"callerchan", callerchan,
"callerid", callerid,
"origdate", origdate,
"origtime", origtime,
"category", category,
"duration", duration,
SENTINEL);
4197 copy(frompath2, topath2);
4215 txtsize = (strlen(file) + 5)*
sizeof(
char);
4223 snprintf(txt, txtsize,
"%s.txt", file);
4258 if (!
inbuf(bio, fi))
4271 if (fputs(
ENDL, so) == EOF) {
4278 if (putc(((
unsigned char) c), so) == EOF) {
4298 static const unsigned char dtable[] = {
'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
'I',
'J',
'K',
4299 'L',
'M',
'N',
'O',
'P',
'Q',
'R',
'S',
'T',
'U',
'V',
'W',
'X',
'Y',
'Z',
'a',
'b',
'c',
'd',
'e',
'f',
4300 'g',
'h',
'i',
'j',
'k',
'l',
'm',
'n',
'o',
'p',
'q',
'r',
's',
't',
'u',
'v',
'w',
'x',
'y',
'z',
'0',
4301 '1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'+',
'/'};
4306 memset(&bio, 0,
sizeof(bio));
4309 if (!(fi = fopen(filename,
"rb"))) {
4315 unsigned char igroup[3], ogroup[4];
4318 memset(igroup, 0,
sizeof(igroup));
4320 for (n = 0; n < 3; n++) {
4321 if ((c =
inchar(&bio, fi)) == EOF) {
4326 igroup[n] = (
unsigned char) c;
4330 ogroup[0]= dtable[igroup[0] >> 2];
4331 ogroup[1]= dtable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)];
4332 ogroup[2]= dtable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)];
4333 ogroup[3]= dtable[igroup[2] & 0x3F];
4342 for (i = 0; i < 4; i++)
4343 ochar(&bio, ogroup[i], so);
4349 if (fputs(
ENDL, so) == EOF) {
4356 static void prep_email_sub_vars(
struct ast_channel *ast,
struct ast_vm_user *vmu,
int msgnum,
char *context,
char *mailbox,
const char *fromfolder,
char *cidnum,
char *cidname,
char *dur,
char *date,
const char *category,
const char *flag)
4360 char fromdir[256], fromfile[256];
4362 const char *origcallerid, *origtime;
4363 char origcidname[80], origcidnum[80], origdate[80];
4370 snprintf(num,
sizeof(num),
"%d", msgnum);
4375 ast_callerid_merge(callerid,
sizeof(callerid), cidname, cidnum, NULL) :
"an unknown caller");
4384 make_file(fromfile,
sizeof(fromfile), fromdir, msgnum - 1);
4385 if (strlen(fromfile) <
sizeof(fromfile) - 5) {
4386 strcat(fromfile,
".txt");
4390 ast_log(
LOG_DEBUG,
"Config load for message text file '%s' failed\n", fromfile);
4397 ast_callerid_split(origcallerid, origcidname,
sizeof(origcidname), origcidnum,
sizeof(origcidnum));
4402 if ((origtime =
ast_variable_retrieve(msg_cfg,
"message",
"origtime")) && sscanf(origtime,
"%30d", &inttime) == 1) {
4403 struct timeval tv = { inttime, };
4426 for (ptr = from; *ptr; ptr++) {
4427 if (*ptr ==
'"' || *ptr ==
'\\') {
4444 const struct vm_zone *z = NULL;
4467 for (; *
str; str++) {
4468 if (*str > 126 || *str < 32 || strchr(
"()<>@,:;/\"[]?.=", *str)) {
4495 int first_section = 1;
4499 for (; *start; start++) {
4500 int need_encoding = 0;
4501 if (*start < 33 || *start > 126 || strchr(
"()<>@,:;/\"[]?.=_", *start)) {
4504 if ((first_section && need_encoding && preamble +
ast_str_strlen(tmp) > 70) ||
4505 (first_section && !need_encoding && preamble +
ast_str_strlen(tmp) > 72) ||
4507 (!first_section && !need_encoding &&
ast_str_strlen(tmp) > 72)) {
4513 if (need_encoding && *start ==
' ') {
4515 }
else if (need_encoding) {
4548 static void make_email_file(FILE *p,
char *srcemail,
struct ast_vm_user *vmu,
int msgnum,
char *context,
char *mailbox,
const char *fromfolder,
char *cidnum,
char *cidname,
char *attach,
char *attach2,
char *format,
int duration,
int attach_user_voicemail,
struct ast_channel *chan,
const char *category,
int imap,
const char *flag)
4556 char enc_cidnum[256] =
"", enc_cidname[256] =
"";
4558 char *greeting_attachment;
4561 if (!str1 || !str2) {
4573 gethostname(host,
sizeof(host) - 1);
4575 if (strchr(srcemail,
'@')) {
4578 snprintf(who,
sizeof(who),
"%s@%s", srcemail, host);
4581 greeting_attachment = strrchr(
ast_strdupa(attach),
'/');
4582 if (greeting_attachment) {
4583 *greeting_attachment++ =
'\0';
4586 snprintf(dur,
sizeof(dur),
"%d:%02d", duration / 60, duration % 60);
4588 fprintf(p,
"Date: %s" ENDL, date);
4597 prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, enc_cidnum, enc_cidname, dur, date, category, flag);
4619 fprintf(p,
"From: Asterisk PBX <%s>" ENDL, who);
4642 prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
4665 fprintf(p,
"Subject: New message %d in mailbox %s" ENDL, msgnum + 1, mailbox);
4667 fprintf(p,
"Subject: New %s message %d in mailbox %s" ENDL, flag, msgnum + 1, mailbox);
4671 fprintf(p,
"Subject: [PBX]: New message %d in mailbox %s" ENDL, msgnum + 1, mailbox);
4673 fprintf(p,
"Subject: [PBX]: New %s message %d in mailbox %s" ENDL, flag, msgnum + 1, mailbox);
4677 fprintf(p,
"Message-ID: <Asterisk-%d-%u-%s-%d@%s>" ENDL, msgnum + 1,
4678 (
unsigned int)
ast_random(), mailbox, (
int) getpid(), host);
4681 fprintf(p,
"X-Asterisk-VM-Message-Num: %d" ENDL, msgnum + 1);
4683 fprintf(p,
"X-Asterisk-VM-Server-Name: %s" ENDL, fromstring);
4684 fprintf(p,
"X-Asterisk-VM-Context: %s" ENDL, context);
4686 fprintf(p,
"X-Asterisk-VM-Extension: %s" ENDL, (!
ast_strlen_zero(vmu->imapvmshareid) ? vmu->imapvmshareid : mailbox));
4688 fprintf(p,
"X-Asterisk-VM-Extension: %s" ENDL, mailbox);
4691 fprintf(p,
"X-Asterisk-VM-Flag: %s" ENDL, flag);
4692 fprintf(p,
"X-Asterisk-VM-Priority: %d" ENDL, chan->
priority);
4693 fprintf(p,
"X-Asterisk-VM-Caller-channel: %s" ENDL, chan->
name);
4694 fprintf(p,
"X-Asterisk-VM-Caller-ID-Num: %s" ENDL, enc_cidnum);
4695 fprintf(p,
"X-Asterisk-VM-Caller-ID-Name: %s" ENDL, enc_cidname);
4696 fprintf(p,
"X-Asterisk-VM-Duration: %d" ENDL, duration);
4698 fprintf(p,
"X-Asterisk-VM-Category: %s" ENDL, category);
4700 fprintf(p,
"X-Asterisk-VM-Category: " ENDL);
4702 fprintf(p,
"X-Asterisk-VM-Message-Type: %s" ENDL, msgnum > -1 ?
"Message" : greeting_attachment);
4703 fprintf(p,
"X-Asterisk-VM-Orig-date: %s" ENDL, date);
4704 fprintf(p,
"X-Asterisk-VM-Orig-time: %ld" ENDL, (
long) time(NULL));
4707 fprintf(p,
"X-Asterisk-CallerID: %s" ENDL, enc_cidnum);
4710 fprintf(p,
"X-Asterisk-CallerIDName: %s" ENDL, enc_cidname);
4712 fprintf(p,
"MIME-Version: 1.0" ENDL);
4713 if (attach_user_voicemail) {
4715 snprintf(bound,
sizeof(bound),
"----voicemail_%d%s%d%u", msgnum + 1, mailbox,
4716 (
int) getpid(), (
unsigned int)
ast_random());
4718 fprintf(p,
"Content-Type: multipart/mixed; boundary=\"%s\"" ENDL, bound);
4719 fprintf(p,
ENDL ENDL "This is a multi-part message in MIME format." ENDL ENDL);
4720 fprintf(p,
"--%s" ENDL, bound);
4722 fprintf(p,
"Content-Type: text/plain; charset=%s" ENDL "Content-Transfer-Encoding: 8bit" ENDL ENDL, charset);
4727 prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
4735 if ((next = strchr(line,
'\n'))) {
4738 fprintf(p,
"%s" ENDL, line);
4749 }
else if (msgnum > -1) {
4750 if (strcmp(vmu->
mailbox, mailbox)) {
4755 char fromdir[256], fromfile[256], origdate[80] =
"", origcallerid[80] =
"";
4759 make_file(fromfile,
sizeof(fromfile), fromdir, msgnum);
4760 if (strlen(fromfile) <
sizeof(fromfile) - 5) {
4761 strcat(fromfile,
".txt");
4770 if ((v =
ast_variable_retrieve(msg_cfg,
"message",
"origtime")) && sscanf(v,
"%30d", &inttime) == 1) {
4771 struct timeval tv = { inttime, };
4776 fprintf(p,
"Dear %s:" ENDL ENDL
"\tJust wanted to let you know you were just forwarded"
4777 " a %s long message (number %d)" ENDL
"in mailbox %s from %s, on %s" ENDL
4778 "(originally sent by %s on %s)" ENDL
"so you might want to check it when you get a"
4779 " chance. Thanks!" ENDL ENDL
"\t\t\t\t--Asterisk" ENDL ENDL, vmu->
fullname, dur,
4780 msgnum + 1, mailbox, (cidname ? cidname : (cidnum ? cidnum :
"an unknown caller")),
4781 date, origcallerid, origdate);
4788 fprintf(p,
"Dear %s:" ENDL ENDL
"\tJust wanted to let you know you were just left a "
4789 "%s long message (number %d)" ENDL
"in mailbox %s from %s, on %s so you might" ENDL
4790 "want to check it when you get a chance. Thanks!" ENDL ENDL
"\t\t\t\t--Asterisk"
4791 ENDL ENDL, vmu->
fullname, dur, msgnum + 1, mailbox,
4792 (cidname ? cidname : (cidnum ? cidnum :
"an unknown caller")), date);
4795 fprintf(p,
"This message is to let you know that your greeting was changed on %s." ENDL
4796 "Please do not delete this message, lest your greeting vanish with it." ENDL ENDL, date);
4799 if (imap || attach_user_voicemail) {
4801 snprintf(filename,
sizeof(filename),
"msg%04d.%s", msgnum, format);
4802 ast_debug(5,
"creating second attachment filename %s\n", filename);
4803 add_email_attachment(p, vmu, format, attach, greeting_attachment, mailbox, bound, filename, 0, msgnum);
4804 snprintf(filename,
sizeof(filename),
"msgintro%04d.%s", msgnum, format);
4805 ast_debug(5,
"creating attachment filename %s\n", filename);
4806 add_email_attachment(p, vmu, format, attach2, greeting_attachment, mailbox, bound, filename, 1, msgnum);
4808 snprintf(filename,
sizeof(filename),
"msg%04d.%s", msgnum, format);
4809 ast_debug(5,
"creating attachment filename %s, no second attachment.\n", filename);
4810 add_email_attachment(p, vmu, format, attach, greeting_attachment, mailbox, bound, filename, 1, msgnum);
4819 char tmpdir[256], newtmp[256];
4826 char *ctype = (!strcasecmp(format,
"ogg")) ?
"application/" :
"audio/x-";
4830 snprintf(newtmp,
sizeof(newtmp),
"%s/XXXXXX", tmpdir);
4831 tmpfd = mkstemp(newtmp);
4835 snprintf(tmpcmd,
sizeof(tmpcmd),
"sox -v %.4f %s.%s %s.%s", vmu->
volgain, attach, format, newtmp, format);
4838 ast_debug(3,
"VOLGAIN: Stored at: %s.%s - Level: %.4f - Mailbox: %s\n", attach, format, vmu->
volgain, mailbox);
4840 ast_log(
LOG_WARNING,
"Sox failed to re-encode %s.%s: %s (have you installed support for all sox file formats?)\n", attach, format,
4841 soxstatus == 1 ?
"Problem with command line options" :
"An error occurred during file processing");
4846 fprintf(p,
"--%s" ENDL, bound);
4848 fprintf(p,
"Content-Type: %s%s; name=\"%s\"" ENDL, ctype, format, filename);
4850 fprintf(p,
"Content-Type: %s%s; name=\"%s.%s\"" ENDL, ctype, format, greeting_attachment, format);
4851 fprintf(p,
"Content-Transfer-Encoding: base64" ENDL);
4852 fprintf(p,
"Content-Description: Voicemail sound attachment." ENDL);
4854 fprintf(p,
"Content-Disposition: attachment; filename=\"%s\"" ENDL ENDL, filename);
4856 fprintf(p,
"Content-Disposition: attachment; filename=\"%s.%s\"" ENDL ENDL, greeting_attachment, format);
4857 snprintf(fname,
sizeof(fname),
"%s.%s", attach, format);
4860 fprintf(p, ENDL ENDL
"--%s--" ENDL
"." ENDL, bound);
4862 if (soxstatus == 0) {
4871 static int sendmail(
char *srcemail,
struct ast_vm_user *vmu,
int msgnum,
char *context,
char *mailbox,
const char *fromfolder,
char *cidnum,
char *cidname,
char *attach,
char *attach2,
char *format,
int duration,
int attach_user_voicemail,
struct ast_channel *chan,
const char *category,
const char *flag)
4874 char tmp[80] =
"/tmp/astmail-XXXXXX";
4888 if (!strcmp(format,
"wav49"))
4890 ast_debug(3,
"Attaching file '%s', format '%s', uservm is '%d', global is %u\n", attach, format, attach_user_voicemail,
ast_test_flag((&globalflags),
VM_ATTACH));
4897 make_email_file(p, srcemail, vmu, msgnum, context, mailbox, fromfolder, cidnum, cidname, attach, attach2, format, duration, attach_user_voicemail, chan, category, 0, flag);
4899 snprintf(tmp2,
sizeof(tmp2),
"( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
4901 ast_debug(1,
"Sent mail to %s with command '%s'\n", vmu->
email, mailcmd);
4906 static int sendpage(
char *srcemail,
char *pager,
int msgnum,
char *context,
char *mailbox,
const char *fromfolder,
char *cidnum,
char *cidname,
int duration,
struct ast_vm_user *vmu,
const char *category,
const char *flag)
4908 char enc_cidnum[256], enc_cidname[256];
4913 char tmp[80] =
"/tmp/astmail-XXXXXX";
4914 char tmp2[PATH_MAX];
4919 if (!str1 || !str2) {
4938 gethostname(host,
sizeof(host)-1);
4939 if (strchr(srcemail,
'@')) {
4942 snprintf(who,
sizeof(who),
"%s@%s", srcemail, host);
4944 snprintf(dur,
sizeof(dur),
"%d:%02d", duration / 60, duration % 60);
4946 fprintf(p,
"Date: %s\n", date);
4955 prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, enc_cidnum, enc_cidname, dur, date, category, flag);
4977 fprintf(p,
"From: Asterisk PBX <%s>" ENDL, who);
4999 prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
5022 fprintf(p,
"Subject: New VM\n\n");
5024 fprintf(p,
"Subject: New %s VM\n\n", flag);
5031 prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
5039 fprintf(p,
"New %s long %s msg in box %s\n"
5040 "from %s, on %s", dur, flag, mailbox, (cidname ? cidname : (cidnum ? cidnum :
"unknown")), date);
5044 snprintf(tmp2,
sizeof(tmp2),
"( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
5046 ast_debug(1,
"Sent page to %s with command '%s'\n", pager, mailcmd);
5068 return ast_strftime(s, len,
"%a %b %e %r UTC %Y", &tm);
5075 char dest[PATH_MAX];
5077 snprintf(fn,
sizeof(fn),
"%s%s/%s/greet", VM_SPOOL_DIR, context, ext);
5079 if ((res =
create_dirpath(dest,
sizeof(dest), context, ext,
""))) {
5111 static int inboxcount2(
const char *mailbox,
int *urgentmsgs,
int *newmsgs,
int *oldmsgs)
5115 SQLHSTMT stmt = NULL;
5118 char tmp[PATH_MAX] =
"";
5121 struct generic_prepare_struct gps = { .sql = sql, .argc = 0 };
5136 if (strchr(mailbox,
' ') || strchr(mailbox,
',')) {
5138 char *next, *remaining = tmp;
5139 while ((next =
strsep(&remaining,
" ,"))) {
5140 if (
inboxcount2(next, urgentmsgs ? &u : NULL, &n, &o)) {
5156 context = strchr(tmp,
'@');
5161 context =
"default";
5166 snprintf(sql,
sizeof(sql),
"SELECT COUNT(*) FROM %s WHERE dir = '%s%s/%s/%s'", odbc_table, VM_SPOOL_DIR, context, tmp,
"INBOX");
5171 res = SQLFetch(stmt);
5172 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
5176 res = SQLGetData(stmt, 1, SQL_CHAR, rowdata,
sizeof(rowdata), NULL);
5177 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
5181 *newmsgs = atoi(rowdata);
5182 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
5186 snprintf(sql,
sizeof(sql),
"SELECT COUNT(*) FROM %s WHERE dir = '%s%s/%s/%s'", odbc_table, VM_SPOOL_DIR, context, tmp,
"Old");
5191 res = SQLFetch(stmt);
5192 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
5196 res = SQLGetData(stmt, 1, SQL_CHAR, rowdata,
sizeof(rowdata), NULL);
5197 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
5201 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
5202 *oldmsgs = atoi(rowdata);
5206 snprintf(sql,
sizeof(sql),
"SELECT COUNT(*) FROM %s WHERE dir = '%s%s/%s/%s'", odbc_table, VM_SPOOL_DIR, context, tmp,
"Urgent");
5211 res = SQLFetch(stmt);
5212 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
5216 res = SQLGetData(stmt, 1, SQL_CHAR, rowdata,
sizeof(rowdata), NULL);
5217 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
5221 *urgentmsgs = atoi(rowdata);
5231 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
5248 static int messagecount(
const char *context,
const char *mailbox,
const char *folder)
5253 SQLHSTMT stmt = NULL;
5256 struct generic_prepare_struct gps = { .sql = sql, .argc = 0 };
5265 if (!strcmp(folder,
"INBOX")) {
5266 snprintf(sql,
sizeof(sql),
"SELECT COUNT(*) FROM %s WHERE dir = '%s%s/%s/INBOX' OR dir = '%s%s/%s/Urgent'", odbc_table, VM_SPOOL_DIR, context, mailbox, VM_SPOOL_DIR, context, mailbox);
5268 snprintf(sql,
sizeof(sql),
"SELECT COUNT(*) FROM %s WHERE dir = '%s%s/%s/%s'", odbc_table, VM_SPOOL_DIR, context, mailbox, folder);
5275 res = SQLFetch(stmt);
5276 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
5278 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
5281 res = SQLGetData(stmt, 1, SQL_CHAR, rowdata,
sizeof(rowdata), NULL);
5282 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
5284 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
5287 nummsgs = atoi(rowdata);
5288 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
5306 static int has_voicemail(
const char *mailbox,
const char *folder)
5308 char tmp[256], *tmp2 = tmp, *box, *
context;
5310 while ((context = box =
strsep(&tmp2,
",&"))) {
5313 context =
"default";
5320 #ifndef IMAP_STORAGE
5339 char fromdir[PATH_MAX], todir[PATH_MAX], frompath[PATH_MAX], topath[PATH_MAX];
5340 const char *frombox =
mbox(vmu, imbox);
5341 const char *userfolder;
5348 userfolder =
"Urgent";
5350 userfolder =
"INBOX";
5360 make_file(frompath,
sizeof(frompath), fromdir, msgnum);
5368 make_file(topath,
sizeof(topath), todir, recipmsgnum);
5369 #ifndef ODBC_STORAGE
5371 COPY(fromdir, msgnum, todir, recipmsgnum, recip->
mailbox, recip->
context, frompath, topath);
5378 STORE(todir, recip->
mailbox, recip->
context, recipmsgnum, chan, recip, fmt, duration, NULL, NULL);
5380 #ifndef ODBC_STORAGE
5396 #if !(defined(IMAP_STORAGE) || defined(ODBC_STORAGE))
5398 static int messagecount(
const char *context,
const char *mailbox,
const char *folder)
5403 static int __has_voicemail(
const char *context,
const char *mailbox,
const char *folder,
int shortcircuit)
5417 context =
"default";
5419 snprintf(fn,
sizeof(fn),
"%s%s/%s/%s", VM_SPOOL_DIR, context, mailbox, folder);
5421 if (!(dir = opendir(fn)))
5424 while ((de = readdir(dir))) {
5425 if (!strncasecmp(de->d_name,
"msg", 3)) {
5429 }
else if (!strncasecmp(de->d_name + 8,
"txt", 3)) {
5451 char tmp[256], *tmp2 = tmp, *box, *
context;
5456 while ((box =
strsep(&tmp2,
",&"))) {
5457 if ((context = strchr(box,
'@')))
5460 context =
"default";
5464 if (!strcmp(folder,
"INBOX") &&
__has_voicemail(context, box,
"Urgent", 1)) {
5472 static int inboxcount2(
const char *mailbox,
int *urgentmsgs,
int *newmsgs,
int *oldmsgs)
5488 if (strchr(mailbox,
',')) {
5489 int tmpnew, tmpold, tmpurgent;
5494 while ((cur =
strsep(&mb,
", "))) {
5496 if (
inboxcount2(cur, urgentmsgs ? &tmpurgent : NULL, newmsgs ? &tmpnew : NULL, oldmsgs ? &tmpold : NULL))
5504 *urgentmsgs += tmpurgent;
5513 if ((context = strchr(tmp,
'@')))
5516 context =
"default";
5531 static int inboxcount(
const char *mailbox,
int *newmsgs,
int *oldmsgs)
5534 int res =
inboxcount2(mailbox, &urgentmsgs, newmsgs, oldmsgs);
5536 *newmsgs += urgentmsgs;
5543 char arguments[255];
5544 char ext_context[256] =
"";
5545 int newvoicemails = 0, oldvoicemails = 0, urgentvoicemails = 0;
5549 snprintf(ext_context,
sizeof(ext_context),
"%s@%s", extension, context);
5561 if (!strncmp(mwi_msg->
cause,
"INV", 3))
5563 else if (!strncmp(mwi_msg->
cause,
"BLK", 3))
5568 ast_debug(1,
"Successfully executed SMDI MWI change for %s\n", extension);
5573 if (
inboxcount2(ext_context, &urgentvoicemails, &newvoicemails, &oldvoicemails)) {
5574 ast_log(
AST_LOG_ERROR,
"Problem in calculating number of voicemail messages available for extension %s\n", extension);
5576 snprintf(arguments,
sizeof(arguments),
"%s %s %s %d %d %d &",
5577 externnotify,
S_OR(context,
"\"\""),
5578 extension, newvoicemails,
5579 oldvoicemails, urgentvoicemails);
5580 ast_debug(1,
"Executing %s\n", arguments);
5593 signed char record_gain;
5610 int newmsgs, oldmsgs;
5612 char urgdir[PATH_MAX];
5614 char txtfile[PATH_MAX];
5615 char tmptxtfile[PATH_MAX];
5624 int sound_duration = 0;
5632 char tmpdir[PATH_MAX];
5634 char prefile[PATH_MAX] =
"";
5635 char tempfile[PATH_MAX] =
"";
5636 char ext_context[256] =
"";
5639 char ecodes[17] =
"#";
5644 const char *category = NULL;
5646 const char *alldtmf =
"0123456789ABCD*#";
5655 if ((context = strchr(ext,
'@'))) {
5657 tmpptr = strchr(context,
'&');
5659 tmpptr = strchr(ext,
'&');
5680 if (!(vmu =
find_user(&svm, context, ext))) {
5687 if (strcmp(vmu->
context,
"default"))
5688 snprintf(ext_context,
sizeof(ext_context),
"%s@%s", ext, vmu->
context);
5698 snprintf(prefile,
sizeof(prefile),
"%s%s/%s/busy", VM_SPOOL_DIR, vmu->
context, ext);
5700 snprintf(prefile,
sizeof(prefile),
"%s%s/%s/unavail", VM_SPOOL_DIR, vmu->
context, ext);
5706 snprintf(tempfile,
sizeof(tempfile),
"%s%s/%s/temp", VM_SPOOL_DIR, vmu->
context, ext);
5718 #ifndef IMAP_STORAGE
5721 snprintf(dir,
sizeof(dir),
"%simap", VM_SPOOL_DIR);
5732 strncat(ecodes,
"0",
sizeof(ecodes) - strlen(ecodes) - 1);
5737 strncat(ecodes,
"0",
sizeof(ecodes) - strlen(ecodes) - 1);
5742 strncat(ecodes,
"0",
sizeof(ecodes) - strlen(ecodes) - 1);
5750 strncat(ecodes,
"*",
sizeof(ecodes) - strlen(ecodes) - 1);
5754 strncat(ecodes,
"*",
sizeof(ecodes) - strlen(ecodes) - 1);
5758 strncat(ecodes,
"*",
sizeof(ecodes) - strlen(ecodes) - 1);
5763 for (code = alldtmf; *code; code++) {
5766 if (strchr(ecodes, e[0]) == NULL
5770 strncat(ecodes, e,
sizeof(ecodes) - strlen(ecodes) - 1);
5780 RETRIEVE(prefile, -1, ext, context);
5785 if (success == -1) {
5787 ast_debug(1,
"Greeting not retrieved from database, but found in file storage. Inserting into database\n");
5792 ast_debug(1,
"%s doesn't exist, doing what we can\n", prefile);
5797 ast_debug(1,
"Hang up during prefile playback\n");
5812 ast_log(
LOG_DEBUG,
"Greetings only VM (maxmsg=0), Skipping voicemail recording\n");
5828 chan->
exten[0] =
'a';
5829 chan->
exten[1] =
'\0';
5845 if (ouseexten || ousemacro) {
5846 chan->
exten[0] =
'o';
5847 chan->
exten[1] =
'\0';
5887 res =
inboxcount(ext_context, &newmsgs, &oldmsgs);
5893 if (!(vms = get_vm_state_by_mailbox(ext, context, 0))) {
5898 if (!(vms = create_vm_state_from_user(vmu))) {
5907 msgnum = newmsgs + oldmsgs;
5908 ast_debug(3,
"Messagecount set to %d\n", msgnum);
5909 snprintf(fn,
sizeof(fn),
"%simap/msg%s%04d", VM_SPOOL_DIR, vmu->
mailbox, msgnum);
5913 if ((res = imap_check_limits(chan, vms, vmu, msgnum))) {
5928 snprintf(tmptxtfile,
sizeof(tmptxtfile),
"%s/XXXXXX", tmpdir);
5929 txtdes = mkstemp(tmptxtfile);
5949 snprintf(priority,
sizeof(priority),
"%d", chan->
priority);
5950 snprintf(origtime,
sizeof(origtime),
"%ld", (
long) time(NULL));
5960 "exten", chan->
exten,
5961 "priority", priority,
5962 "callerchan", chan->
name,
5963 "callerid", callerid,
5965 "origtime", origtime,
5966 "category",
S_OR(category,
""),
5967 "filename", tmptxtfile,
5972 txt = fdopen(txtdes,
"w+");
5981 "; Message Information file\n"
6004 date, (
long) time(NULL),
6005 category ? category :
"");
6015 res =
play_record_review(chan, NULL, tmptxtfile, vmu->
maxsecs, fmt, 1, vmu, &duration, &sound_duration, NULL, options->
record_gain, vms, flag);
6018 fprintf(txt,
"flag=%s\n", flag);
6019 if (sound_duration < vmu->
minsecs) {
6021 ast_verb(3,
"Recording was %d seconds long but needs to be at least %d - abandoning\n", sound_duration, vmu->
minsecs);
6029 fprintf(txt,
"duration=%d\n", duration);
6038 ast_debug(1,
"The recorded media file is gone, so we should remove the .txt file too!\n");
6046 #ifndef IMAP_STORAGE
6052 #ifndef IMAP_STORAGE
6058 snprintf(txtfile,
sizeof(txtfile),
"%s.txt", fn);
6060 rename(tmptxtfile, txtfile);
6070 snprintf(tmpdur,
sizeof(tmpdur),
"%d", duration);
6085 exten =
strsep(&tmpptr,
"&");
6086 cntx = strchr(exten,
'@');
6091 if ((recip =
find_user(&recipu, cntx, exten))) {
6092 copy_message(chan, vmu, 0, msgnum, duration, recip, fmt, dir, flag);
6096 #ifndef IMAP_STORAGE
6105 make_file(sfn,
sizeof(sfn), dir, msgnum);
6107 ast_debug(5,
"Created an Urgent message, moving file from %s to %s.\n", sfn, dfn);
6140 }
else if (res > 0 && res !=
't')
6143 if (sound_duration < vmu->
minsecs)
6155 ast_debug(3,
"*** Checking if we can expunge, expungeonhangup set to %d\n", expungeonhangup);
6156 if (expungeonhangup == 1) {
6158 #ifdef HAVE_IMAP_TK2006
6159 if (LEVELUIDPLUS (vms->mailstream)) {
6160 mail_expunge_full(vms->mailstream, NIL, EX_UID);
6163 mail_expunge(vms->mailstream);
6172 #if !defined(IMAP_STORAGE)
6185 for (x = 0, dest = 0; dest != stopcount && x < vmu->
maxmsg + 10; x++) {
6187 if (
EXISTS(dir, x, sfn, NULL)) {
6220 snprintf(sequence,
sizeof(sequence),
"%ld", vms->msgArray[msg]);
6222 ast_debug(3,
"Copying sequence %s to mailbox %s\n", sequence,
mbox(vmu, box));
6226 mail_setflag(vms->mailstream, sequence,
"\\Seen");
6227 mail_clearflag(vms->mailstream, sequence,
"\\Unseen");
6229 mail_setflag(vms->mailstream, sequence,
"\\Unseen");
6230 mail_clearflag(vms->mailstream, sequence,
"\\Seen");
6237 imap_mailbox_name(mailbox,
sizeof(mailbox), vms, box, 1);
6238 ast_debug(5,
"Checking if folder exists: %s\n", mailbox);
6239 if (mail_create(vms->mailstream, mailbox) == NIL)
6243 res = !mail_copy(vms->mailstream, sequence, (
char *)
mbox(vmu, box));
6252 char ddir[PATH_MAX];
6253 const char *dbox =
mbox(vmu, box);
6264 for (i = 1; i <= x; i++) {
6267 make_file(dfn,
sizeof(dfn), ddir, i - 1);
6268 if (
EXISTS(ddir, i, sfn, NULL)) {
6281 if (strcmp(sfn, dfn)) {
6282 COPY(dir, msg, ddir, x, username, context, sfn, dfn);
6299 unsigned char buf[256];
6331 bytes += ast_adsi_logo(buf);
6375 for (x = 0; x < 5; x++) {
6376 snprintf(num,
sizeof(num),
"%d", x);
6404 ast_debug(1,
"Done downloading scripts...\n");
6412 ast_debug(1,
"Restarting session...\n");
6445 unsigned char buf[256];
6447 unsigned char keys[8];
6452 for (x = 0; x < 8; x++)
6471 unsigned char buf[256];
6473 unsigned char keys[8];
6478 for (x = 0; x < 8; x++)
6493 unsigned char buf[256];
6495 unsigned char keys[8];
6501 for (x = 0; x < 5; x++) {
6523 unsigned char buf[256];
6530 char datetime[21] =
"";
6533 unsigned char keys[8];
6541 snprintf(fn2,
sizeof(fn2),
"%s.txt", vms->
fn);
6542 f = fopen(fn2,
"r");
6545 if (!fgets((
char *) buf,
sizeof(buf), f)) {
6549 char *stringp = NULL;
6550 stringp = (
char *) buf;
6552 val =
strsep(&stringp,
"=");
6554 if (!strcmp((
char *) buf,
"callerid"))
6556 if (!strcmp((
char *) buf,
"origdate"))
6564 for (x = 0; x < 5; x++)
6591 name =
"Unknown Caller";
6606 snprintf(buf1,
sizeof(buf1),
"%s%s", vms->
curbox,
6607 strcasecmp(vms->
curbox,
"INBOX") ?
" Messages" :
"");
6608 snprintf(buf2,
sizeof(buf2),
"Message %d of %d", vms->
curmsg + 1, vms->
lastmsg + 1);
6624 unsigned char buf[256];
6625 unsigned char keys[8];
6633 for (x = 0; x < 5; x++)
6675 unsigned char buf[256] =
"";
6676 char buf1[256] =
"",
buf2[256] =
"";
6678 unsigned char keys[8];
6681 char *newm = (vms->
newmessages == 1) ?
"message" :
"messages";
6682 char *oldm = (vms->
oldmessages == 1) ?
"message" :
"messages";
6686 snprintf(buf1,
sizeof(buf1),
"You have %d new", vms->
newmessages);
6688 strncat(buf1,
" and",
sizeof(buf1) - strlen(buf1) - 1);
6691 snprintf(
buf2,
sizeof(
buf2),
"%s.", newm);
6694 snprintf(buf1,
sizeof(buf1),
"You have %d old", vms->
oldmessages);
6695 snprintf(
buf2,
sizeof(
buf2),
"%s.", oldm);
6697 strcpy(buf1,
"You have no messages.");
6705 for (x = 0; x < 6; x++)
6722 unsigned char buf[256] =
"";
6723 char buf1[256] =
"",
buf2[256] =
"";
6725 unsigned char keys[8];
6728 char *mess = (vms->
lastmsg == 0) ?
"message" :
"messages";
6734 for (x = 0; x < 6; x++)
6743 snprintf(buf1,
sizeof(buf1),
"%s%s has", vms->
curbox,
6744 strcasecmp(vms->
curbox,
"INBOX") ?
" folder" :
"");
6749 strcpy(
buf2,
"no messages.");
6778 unsigned char buf[256];
6804 for (x = start; x < 5; x++) {
6810 snprintf(fn,
sizeof(fn),
"vm-%s",
mbox(NULL, x));
6819 ast_verb(1,
"failed to find %s\n", fn);
6859 while (((res <
'0') || (res >
'9')) &&
6860 (res !=
'#') && (res >= 0) &&
6892 char *context,
signed char record_gain,
long *duration,
struct vm_state *vms,
char *flag)
6895 int retries = 0, prepend_duration = 0, already_recorded = 0;
6896 char msgfile[PATH_MAX], backup[PATH_MAX], backup_textfile[PATH_MAX];
6897 char textfile[PATH_MAX];
6900 #ifndef IMAP_STORAGE
6901 signed char zero_gain = 0;
6903 const char *duration_str;
6906 make_file(msgfile,
sizeof(msgfile), curdir, curmsg);
6907 strcpy(textfile, msgfile);
6908 strcpy(backup, msgfile);
6909 strcpy(backup_textfile, msgfile);
6910 strncat(textfile,
".txt",
sizeof(textfile) - strlen(textfile) - 1);
6911 strncat(backup,
"-bak",
sizeof(backup) - strlen(backup) - 1);
6912 strncat(backup_textfile,
"-bak.txt",
sizeof(backup_textfile) - strlen(backup_textfile) - 1);
6915 *duration = atoi(duration_str);
6920 while ((cmd >= 0) && (cmd !=
't') && (cmd !=
'*')) {
6928 make_file(vms->introfn,
sizeof(vms->introfn), curdir, curmsg);
6929 strncat(vms->introfn,
"intro",
sizeof(vms->introfn));
6932 cmd =
play_record_review(chan, NULL, vms->introfn, vmu->
maxsecs, vm_fmts, 1, vmu, (
int *) duration, NULL, NULL, record_gain, vms, flag);
6941 make_file(msgfile,
sizeof(msgfile), curdir, curmsg);
6942 strcpy(textfile, msgfile);
6943 strncat(textfile,
".txt",
sizeof(textfile) - 1);
6953 #ifndef IMAP_STORAGE
6954 if (already_recorded) {
6956 copy(backup_textfile, textfile);
6960 copy(textfile, backup_textfile);
6963 already_recorded = 1;
6968 cmd =
ast_play_and_prepend(chan, NULL, msgfile, 0, vm_fmts, &prepend_duration, NULL, 1, silencethreshold, maxsilence);
6981 *duration = atoi(duration_str);
6983 if (prepend_duration) {
6986 char duration_buf[12];
6988 *duration += prepend_duration;
6990 snprintf(duration_buf, 11,
"%ld", *duration);
7001 *vms->introfn =
'\0';
7010 already_recorded = 0;
7033 if (prepend_duration)
7034 *duration = prepend_duration;
7036 if (already_recorded && cmd == -1) {
7039 rename(backup_textfile, textfile);
7042 if (cmd ==
't' || cmd ==
'S')
7056 context =
"default";
7086 char todir[PATH_MAX], fn[PATH_MAX], ext_context[PATH_MAX], *stringp;
7087 int newmsgs = 0, oldmsgs = 0, urgentmsgs = 0;
7088 const char *category;
7097 #ifndef IMAP_STORAGE
7100 snprintf(todir,
sizeof(todir),
"%simap", VM_SPOOL_DIR);
7102 make_file(fn,
sizeof(fn), todir, msgnum);
7103 snprintf(ext_context,
sizeof(ext_context),
"%s@%s", vmu->
mailbox, vmu->
context);
7123 if (attach_user_voicemail)
7127 sendmail(myserveremail, vmu, msgnum, vmu->
context, vmu->
mailbox,
mbox(vmu, 0), cidnum, cidname, fn, NULL, fmt, duration, attach_user_voicemail, chan, category, flag);
7129 if (attach_user_voicemail)
7134 sendpage(myserveremail, vmu->
pager, msgnum, vmu->
context, vmu->
mailbox,
mbox(vmu, 0), cidnum, cidname, duration, vmu, category, flag);
7138 DELETE(todir, msgnum, fn, vmu);
7152 vm_imap_delete(NULL, vms->
curmsg, vmu);
7195 char ecodes[16] =
"#";
7196 int res = 0, cmd = 0;
7201 int saved_messages = 0;
7202 int valid_extensions = 0;
7205 char urgent_str[7] =
"";
7206 int prompt_played = 0;
7207 #ifndef IMAP_STORAGE
7208 char msgfile[PATH_MAX], textfile[PATH_MAX], backup[PATH_MAX], backup_textfile[PATH_MAX];
7211 ast_copy_string(urgent_str, urgent ?
"Urgent" :
"",
sizeof(urgent_str));
7214 if (vms == NULL)
return -1;
7219 while (!res && !valid_extensions) {
7220 int use_directory = 0;
7225 while ((cmd >= 0) && !done ){
7257 if (cmd < 0 || cmd ==
't')
7261 if (use_directory) {
7264 char old_context[
sizeof(chan->
context)];
7265 char old_exten[
sizeof(chan->
exten)];
7267 struct ast_app* directory_app;
7270 if (directory_app) {
7271 char vmcontext[256];
7274 memcpy(old_exten, chan->
exten,
sizeof(chan->
exten));
7278 snprintf(vmcontext,
sizeof(vmcontext),
"%s,,v", context ? context :
"default");
7279 res =
pbx_exec(chan, directory_app, vmcontext);
7285 memcpy(chan->
exten, old_exten,
sizeof(chan->
exten));
7295 if (res || prompt_played > 4)
7297 if ((res =
ast_readstring(chan, username,
sizeof(username) - 1, 2000, 10000,
"#") < 0))
7305 s =
strsep(&stringp,
"*");
7307 valid_extensions = 1;
7309 if ((is_new_message == 1 || strcmp(s, sender->
mailbox)) && (receiver =
find_user(NULL, context, s))) {
7314 ast_log(
LOG_ERROR,
"Problem in calculating number of voicemail messages available for extension %s\n", s);
7317 valid_extensions = 0;
7321 if ((newmsgs + oldmsgs) >= capacity) {
7322 ast_log(
LOG_NOTICE,
"Mailbox '%s' is full with capacity of %d, prompting for another extension.\n", s, capacity);
7324 valid_extensions = 0;
7345 valid_extensions = 0;
7350 snprintf(fn,
sizeof(fn),
"%s%s/%s/greet", VM_SPOOL_DIR, receiver->
context, s);
7363 s =
strsep(&stringp,
"*");
7366 if (valid_extensions)
7372 if (is_new_message == 1) {
7375 snprintf(mailbox,
sizeof(mailbox),
"%s@%s", username, context);
7378 memset(&leave_options, 0,
sizeof(leave_options));
7385 int copy_msg_result = 0;
7386 memcpy(&vmstmp, vms,
sizeof(vmstmp));
7390 cmd =
vm_forwardoptions(chan, sender, vmstmp.
curdir, curmsg, vmfmts,
S_OR(context,
"default"), record_gain, &duration, &vmstmp, urgent_str);
7394 int attach_user_voicemail;
7398 dstvms = get_vm_state_by_mailbox(vmtmp->mailbox, vmtmp->context, 0);
7400 dstvms = create_vm_state_from_user(vmtmp);
7403 init_mailstream(dstvms, 0);
7404 if (!dstvms->mailstream) {
7407 copy_msg_result =
STORE(vmstmp.
curdir, vmtmp->mailbox, vmtmp->context, dstvms->
curmsg, chan, vmtmp, fmt, duration, dstvms, urgent_str);
7414 myserveremail = vmtmp->serveremail;
7417 sendmail(myserveremail, vmtmp, todircount, vmtmp->context, vmtmp->mailbox,
7421 vmstmp.
fn, vmstmp.introfn, fmt, duration, attach_user_voicemail, chan,
7424 copy_msg_result =
copy_message(chan, sender, 0, curmsg, duration, vmtmp, fmt, dir, urgent_str);
7434 if (saved_messages > 0 && !copy_msg_result) {
7449 #ifndef IMAP_STORAGE
7455 make_file(msgfile,
sizeof(msgfile), dir, curmsg);
7456 strcpy(textfile, msgfile);
7457 strcpy(backup, msgfile);
7458 strcpy(backup_textfile, msgfile);
7459 strncat(textfile,
".txt",
sizeof(textfile) - strlen(textfile) - 1);
7460 strncat(backup,
"-bak",
sizeof(backup) - strlen(backup) - 1);
7461 strncat(backup_textfile,
"-bak.txt",
sizeof(backup_textfile) - strlen(backup_textfile) - 1);
7464 rename(backup_textfile, textfile);
7469 #ifndef IMAP_STORAGE
7471 make_file(msgfile,
sizeof(msgfile), dir, curmsg);
7472 strcpy(textfile, msgfile);
7473 strcpy(backup_textfile, msgfile);
7474 strncat(textfile,
".txt",
sizeof(textfile) - strlen(textfile) - 1);
7475 strncat(backup_textfile,
"-bak.txt",
sizeof(backup_textfile) - strlen(backup_textfile) - 1);
7476 rename(backup_textfile, textfile);
7486 return res ? res : cmd;
7500 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);
7521 struct vm_zone *the_zone = NULL;
7551 if (time_now.tm_year == time_then.tm_year)
7552 snprintf(temp,
sizeof(temp),
"%d", time_now.tm_yday);
7554 snprintf(temp,
sizeof(temp),
"%d", (time_now.tm_year - time_then.tm_year) * 365 + (time_now.tm_yday - time_then.tm_yday));
7561 }
else if (!strncasecmp(chan->
language,
"de", 2)) {
7563 }
else if (!strncasecmp(chan->
language,
"gr", 2)) {
7565 }
else if (!strncasecmp(chan->
language,
"it", 2)) {
7567 }
else if (!strncasecmp(chan->
language,
"nl", 2)) {
7569 }
else if (!strncasecmp(chan->
language,
"no", 2)) {
7571 }
else if (!strncasecmp(chan->
language,
"pl", 2)) {
7573 }
else if (!strncasecmp(chan->
language,
"pt_BR", 5)) {
7575 }
else if (!strncasecmp(chan->
language,
"se", 2)) {
7577 }
else if (!strncasecmp(chan->
language,
"zh", 2)) {
7579 }
else if (!strncasecmp(chan->
language,
"vi", 2)) {
7596 char *callerid, *
name;
7597 char prefile[PATH_MAX] =
"";
7607 if ((cid == NULL)||(context == NULL))
7611 ast_debug(1,
"VM-CID: composite caller ID received: %s, context: %s\n", cid, context);
7617 ast_debug(1,
"VM-CID: comparing internalcontext: %s\n", cidinternalcontexts[i]);
7618 if ((strcmp(cidinternalcontexts[i], context) == 0))
7621 if (i != MAX_NUM_CID_CONTEXTS){
7623 snprintf(prefile,
sizeof(prefile),
"%s%s/%s/greet", VM_SPOOL_DIR, context, callerid);
7627 ast_verb(3,
"Playing envelope info: CID number '%s' matches mailbox number, playing recorded name\n", callerid);
7632 ast_verb(3,
"Playing envelope info: message from '%s'\n", callerid);
7635 res =
wait_file2(chan, vms,
"vm-from-extension");
7641 ast_debug(1,
"VM-CID: Numeric caller id: (%s)\n", callerid);
7644 res =
wait_file2(chan, vms,
"vm-from-phonenumber");
7649 ast_debug(1,
"VM-CID: From an unknown number\n");
7651 res =
wait_file2(chan, vms,
"vm-unknown-caller");
7662 if (duration == NULL)
7666 durations = atoi(duration);
7667 durationm = (durations / 60);
7669 ast_debug(1,
"VM-Duration: duration is: %d seconds converted to: %d minutes\n", durations, durationm);
7671 if ((!res) && (durationm >= minduration)) {
7675 if (!strncasecmp(chan->
language,
"pl", 2)) {
7676 div_t num = div(durationm, 10);
7678 if (durationm == 1) {
7681 }
else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
7709 char filename[256], *cid;
7710 const char *origtime, *
context, *category, *duration, *flag;
7723 snprintf(filename,
sizeof(filename),
"%s.txt", vms->
fn);
7740 if (!strncasecmp(chan->
language,
"pl", 2)) {
7744 ten = (vms->
curmsg + 1) / 10;
7745 one = (vms->
curmsg + 1) % 10;
7748 snprintf(nextmsg,
sizeof(nextmsg),
"digits/n-%d", vms->
curmsg + 1);
7751 snprintf(nextmsg,
sizeof(nextmsg),
"digits/n-%d", ten * 10);
7755 snprintf(nextmsg,
sizeof(nextmsg),
"digits/n-%d", one);
7764 }
else if (!strncasecmp(chan->
language,
"he", 2)) {
7777 }
else if (!strncasecmp(chan->
language,
"vi", 2)) {
7790 if (!strncasecmp(chan->
language,
"se", 2)) {
7791 res =
wait_file2(chan, vms,
"vm-meddelandet");
7821 if (!strncasecmp(
"macro", context, 5))
7868 static int imap_remove_file(
char *dir,
int msgnum)
7871 char full_fn[PATH_MAX];
7872 char intro[PATH_MAX] = {0,};
7876 snprintf(intro,
sizeof(intro),
"%sintro", fn);
7880 if ((msgnum < 0 && imapgreetings) || msgnum > -1) {
7885 snprintf(full_fn,
sizeof(full_fn),
"%s.txt", fn);
7893 static int imap_delete_old_greeting (
char *dir,
struct vm_state *vms)
7895 char *file, *filename;
7905 ast_log(
AST_LOG_ERROR,
"Failed to procure file name from directory passed. You should never see this.\n");
7910 for (i = 0; i < vms->mailstream->nmsgs; i++) {
7911 mail_fetchstructure(vms->mailstream, i + 1, &body);
7913 if (body->nested.part->next && body->nested.part->next->body.parameter->value) {
7914 attachment =
ast_strdupa(body->nested.part->next->body.parameter->value);
7920 filename =
strsep(&attachment,
".");
7921 if (!strcmp(filename, file)) {
7922 sprintf(arg,
"%d", i + 1);
7923 mail_setflag(vms->mailstream, arg,
"\\DELETED");
7926 mail_expunge(vms->mailstream);
7931 #elif !defined(IMAP_STORAGE)
7934 int count_msg, last_msg;
7948 if (count_msg < 0) {
7974 if (last_msg < -1) {
7976 }
else if (vms->
lastmsg != last_msg) {
7977 ast_log(
LOG_NOTICE,
"Resequencing Mailbox: %s, expected %d but found %d message(s) in box with max threshold of %d.\n", vms->
curdir, last_msg + 1, vms->
lastmsg + 1, vmu->
maxmsg);
7988 int last_msg_idx = 0;
7990 #ifndef IMAP_STORAGE
7991 int res = 0, nummsg;
8000 #ifndef IMAP_STORAGE
8008 if (last_msg_idx != vms->
lastmsg) {
8013 for (x = 0; x < last_msg_idx + 1; x++) {
8022 if (strcmp(vms->
fn, fn2)) {
8056 for (x = vms->
curmsg + 1; x <= nummsg; x++) {
8069 for (x = last_msg_idx - 1; x >= 0; x--) {
8110 if (!strcasecmp(box,
"vm-INBOX") || !strcasecmp(box,
"vm-Old")){
8123 if (!strcasecmp(box,
"vm-INBOX") || !strcasecmp(box,
"vm-Old")) {
8124 if (!strcasecmp(box,
"vm-INBOX"))
8139 if (!strcasecmp(box,
"vm-Family") || !strcasecmp(box,
"vm-Friends") || !strcasecmp(box,
"vm-Work")){
8152 if ( !strncasecmp(chan->
language,
"it", 2) ||
8153 !strncasecmp(chan->
language,
"es", 2) ||
8154 !strncasecmp(chan->
language,
"pt", 2)) {
8157 }
else if (!strncasecmp(chan->
language,
"gr", 2)) {
8159 }
else if (!strncasecmp(chan->
language,
"he", 2)) {
8161 }
else if (!strncasecmp(chan->
language,
"pl", 2)) {
8163 }
else if (!strncasecmp(chan->
language,
"ua", 2)) {
8165 }
else if (!strncasecmp(chan->
language,
"vi", 2)) {
8498 }
else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
8525 }
else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
9076 snprintf(prefile,
sizeof(prefile),
"%s%s/%s/temp", VM_SPOOL_DIR, vmu->
context, vms->
username);
9088 }
else if (!strncasecmp(chan->
language,
"cs", 2)) {
9090 }
else if (!strncasecmp(chan->
language,
"cz", 2)) {
9091 static int deprecation_warning = 0;
9092 if (deprecation_warning++ % 10 == 0) {
9093 ast_log(
LOG_WARNING,
"cz is not a standard language code. Please switch to using cs instead.\n");
9096 }
else if (!strncasecmp(chan->
language,
"de", 2)) {
9098 }
else if (!strncasecmp(chan->
language,
"es", 2)) {
9100 }
else if (!strncasecmp(chan->
language,
"fr", 2)) {
9102 }
else if (!strncasecmp(chan->
language,
"gr", 2)) {
9104 }
else if (!strncasecmp(chan->
language,
"he", 2)) {
9106 }
else if (!strncasecmp(chan->
language,
"it", 2)) {
9108 }
else if (!strncasecmp(chan->
language,
"nl", 2)) {
9110 }
else if (!strncasecmp(chan->
language,
"no", 2)) {
9112 }
else if (!strncasecmp(chan->
language,
"pl", 2)) {
9114 }
else if (!strncasecmp(chan->
language,
"pt_BR", 5)) {
9116 }
else if (!strncasecmp(chan->
language,
"pt", 2)) {
9118 }
else if (!strncasecmp(chan->
language,
"ru", 2)) {
9120 }
else if (!strncasecmp(chan->
language,
"se", 2)) {
9122 }
else if (!strncasecmp(chan->
language,
"ua", 2)) {
9124 }
else if (!strncasecmp(chan->
language,
"vi", 2)) {
9126 }
else if (!strncasecmp(chan->
language,
"zh", 2)) {
9170 if (!res && !skipadvanced)
9193 if (!curmsg_deleted) {
9260 char newpassword[80] =
"";
9261 char newpassword2[80] =
"";
9262 char prefile[PATH_MAX] =
"";
9263 unsigned char buf[256];
9278 snprintf(prefile,
sizeof(prefile),
"%s%s/%s/greet", VM_SPOOL_DIR, vmu->
context, vms->
username);
9280 cmd =
play_record_review(chan,
"vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
9281 if (cmd < 0 || cmd ==
't' || cmd ==
'#')
9288 snprintf(prefile,
sizeof(prefile),
"%s%s/%s/unavail", VM_SPOOL_DIR, vmu->
context, vms->
username);
9290 cmd =
play_record_review(chan,
"vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
9291 if (cmd < 0 || cmd ==
't' || cmd ==
'#')
9295 snprintf(prefile,
sizeof(prefile),
"%s%s/%s/busy", VM_SPOOL_DIR, vmu->
context, vms->
username);
9297 cmd =
play_record_review(chan,
"vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
9298 if (cmd < 0 || cmd ==
't' || cmd ==
'#')
9308 newpassword[1] =
'\0';
9311 newpassword[0] =
'\0';
9312 if (cmd < 0 || cmd ==
't' || cmd ==
'#')
9314 cmd =
ast_readstring(chan, newpassword + strlen(newpassword),
sizeof(newpassword) - 1, 2000, 10000,
"#");
9315 if (cmd < 0 || cmd ==
't' || cmd ==
'#')
9322 newpassword2[1] =
'\0';
9325 newpassword2[0] =
'\0';
9326 if (cmd < 0 || cmd ==
't' || cmd ==
'#')
9328 cmd =
ast_readstring(chan, newpassword2 + strlen(newpassword2),
sizeof(newpassword2) - 1, 2000, 10000,
"#");
9329 if (cmd < 0 || cmd ==
't' || cmd ==
'#')
9331 if (!strcmp(newpassword, newpassword2))
9347 ast_debug(1,
"User %s set password to %s of length %d\n", vms->
username, newpassword, (
int) strlen(newpassword));
9358 char newpassword[80] =
"";
9359 char newpassword2[80] =
"";
9360 char prefile[PATH_MAX] =
"";
9361 unsigned char buf[256];
9373 while ((cmd >= 0) && (cmd !=
't')) {
9378 snprintf(prefile,
sizeof(prefile),
"%s%s/%s/unavail", VM_SPOOL_DIR, vmu->
context, vms->
username);
9379 cmd =
play_record_review(chan,
"vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
9382 snprintf(prefile,
sizeof(prefile),
"%s%s/%s/busy", VM_SPOOL_DIR, vmu->
context, vms->
username);
9383 cmd =
play_record_review(chan,
"vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
9386 snprintf(prefile,
sizeof(prefile),
"%s%s/%s/greet", VM_SPOOL_DIR, vmu->
context, vms->
username);
9387 cmd =
play_record_review(chan,
"vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
9397 newpassword[1] =
'\0';
9400 newpassword[0] =
'\0';
9404 if ((cmd =
ast_readstring(chan, newpassword + strlen(newpassword),
sizeof(newpassword) - 1, 2000, 10000,
"#")) < 0) {
9417 newpassword2[1] =
'\0';
9420 newpassword2[0] =
'\0';
9425 if ((cmd =
ast_readstring(chan, newpassword2 + strlen(newpassword2),
sizeof(newpassword2) - 1, 2000, 10000,
"#")) < 0) {
9429 if (strcmp(newpassword, newpassword2)) {
9445 ast_debug(1,
"User %s set password to %s of length %d\n",
9446 vms->
username, newpassword, (
int) strlen(newpassword));
9454 snprintf(prefile,
sizeof(prefile),
"%s%s/%s/temp", VM_SPOOL_DIR, vmu->
context, vms->
username);
9501 char prefile[PATH_MAX] =
"";
9502 unsigned char buf[256];
9515 snprintf(prefile,
sizeof(prefile),
"%s%s/%s/temp", VM_SPOOL_DIR, vmu->
context, vms->
username);
9516 while ((cmd >= 0) && (cmd !=
't')) {
9521 cmd =
play_record_review(chan,
"vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
9529 cmd =
play_record_review(chan,
"vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
9532 DELETE(prefile, -1, prefile, vmu);
9542 "vm-tempgreeting2" :
"vm-tempgreeting");
9571 if (!strcasecmp(vms->
fn,
"INBOX")) {
9599 snprintf(vms->
fn,
sizeof(vms->
fn),
"vm-%s", vms->
curbox);
9625 if (!strcasecmp(vms->
vmbox,
"vm-INBOX") ||!strcasecmp(vms->
vmbox,
"vm-Old")){
9627 snprintf(vms->
fn,
sizeof(vms->
fn),
"vm-%ss", vms->
curbox);
9636 snprintf(vms->
fn,
sizeof(vms->
fn),
"vm-%s", vms->
curbox);
9665 snprintf(vms->
fn,
sizeof(vms->
fn),
"vm-%s", vms->
curbox);
9689 snprintf(vms->
fn,
sizeof(vms->
fn),
"vm-%s", vms->
curbox);
9709 if (!strncasecmp(chan->
language,
"es", 2) ||
9710 !strncasecmp(chan->
language,
"it", 2) ||
9711 !strncasecmp(chan->
language,
"pt", 2) ||
9712 !strncasecmp(chan->
language,
"gr", 2)) {
9714 }
else if (!strncasecmp(chan->
language,
"he", 2)) {
9716 }
else if (!strncasecmp(chan->
language,
"vi", 2)) {
9718 }
else if (!strncasecmp(chan->
language,
"zh", 2)) {
9727 int skipuser,
int max_logins,
int silent)
9729 int useadsi = 0, valid = 0, logretries = 0;
9735 if (!skipuser && useadsi)
9744 while (!valid && (logretries < max_logins)) {
9746 if (!skipuser &&
ast_readstring(chan, mailbox, mailbox_size - 1, 2000, 10000,
"#") < 0) {
9754 ast_verb(3,
"Username not entered\n");
9757 }
else if (mailbox[0] ==
'*') {
9759 ast_verb(4,
"Mailbox begins with '*', attempting jump to extension 'a'\n");
9764 ast_verb(4,
"Jump to extension 'a' failed; setting mailbox to NULL\n");
9772 char fullusername[80] =
"";
9774 strncat(fullusername, mailbox,
sizeof(fullusername) - 1 - strlen(fullusername));
9778 ast_debug(1,
"Before find user for mailbox %s\n", mailbox);
9779 vmu =
find_user(&vmus, context, mailbox);
9788 if (
ast_readstring(chan, password,
sizeof(password) - 1, 2000, 10000,
"#") < 0) {
9791 }
else if (password[0] ==
'*') {
9793 ast_verb(4,
"Password begins with '*', attempting jump to extension 'a'\n");
9799 ast_verb(4,
"Jump to extension 'a' failed; setting mailbox and user to NULL\n");
9808 if (passptr[0] ==
'-') passptr++;
9810 if (vmu && !strcmp(passptr, password))
9813 ast_verb(3,
"Incorrect password '%s' for user '%s' (context = %s)\n", password, mailbox, context ? context :
"default");
9819 if (skipuser || logretries >= max_logins) {
9836 if (!valid && (logretries >= max_logins)) {
9841 if (vmu && !skipuser) {
9855 char prefixstr[80] =
"";
9856 char ext_context[256]=
"";
9862 char *context = NULL;
9865 signed char record_gain = 0;
9867 int play_folder = 0;
9874 memset(&vms, 0,
sizeof(vms));
9878 memset(&vmus, 0,
sizeof(vmus));
9898 if (
args.argc == 2) {
9904 if (sscanf(opts[OPT_ARG_RECORDGAIN],
"%30d", &gain) != 1) {
9905 ast_log(
AST_LOG_WARNING,
"Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
9908 record_gain = (
signed char) gain;
9918 if (isdigit(opts[OPT_ARG_PLAYFOLDER][0])) {
9919 if (sscanf(opts[OPT_ARG_PLAYFOLDER],
"%30d", &play_folder) != 1) {
9928 if (play_folder > 9 || play_folder < 0) {
9930 "Invalid value '%s' provided for folder autoplay option. Defaulting to 'INBOX'\n",
9931 opts[OPT_ARG_PLAYFOLDER]);
9937 while (*(
args.argv0)) {
9938 if (*(
args.argv0) ==
's')
9940 else if (*(
args.argv0) ==
'p')
9951 if ((context = strchr(
args.argv0,
'@')))
9968 ast_debug(1,
"After vm_authenticate\n");
9999 pthread_once(&ts_vmstate.once, ts_vmstate.key_init);
10000 pthread_setspecific(ts_vmstate.key, &vms);
10002 vms.interactive = 1;
10006 vmstate_insert(&vms);
10007 init_vm_state(&vms);
10081 cmd =
vm_newuser(chan, vmu, &vms, vmfmts, record_gain);
10082 if ((cmd ==
't') || (cmd ==
'#')) {
10087 }
else if (cmd < 0) {
10094 #ifdef IMAP_STORAGE
10095 ast_debug(3,
"Checking quotas: comparing %u to %u\n", vms.quota_usage, vms.quota_limit);
10096 if (vms.quota_limit && vms.quota_usage >= vms.quota_limit) {
10097 ast_debug(1,
"*** QUOTA EXCEEDED!!\n");
10117 while ((cmd > -1) && (cmd !=
't') && (cmd !=
'#')) {
10136 }
else if (cmd > 0) {
10142 if (cmd != 11) in_urgent = 0;
10163 while ((cmd > -1) && (cmd !=
't') && (cmd !=
'#')) {
10179 ast_verb(3,
"Callback Requested\n");
10221 cmd =
forward_message(chan, context, &vms, vmu, vmfmts, 1, record_gain, 0);
10292 ast_debug(1,
"No more new messages, opened INBOX and got %d Urgent messages\n", vms.
lastmsg + 1);
10323 ast_debug(1,
"No more urgent messages, opened INBOX and got %d new messages\n", vms.
lastmsg + 1);
10342 if (play_folder == 0) {
10349 else if (play_folder == 1)
10353 if (play_folder == 0) {
10360 else if (play_folder == 1)
10376 if (in_urgent == 1) {
10385 ast_debug(1,
"No more urgent messages, opened INBOX and got %d new messages\n", vms.
lastmsg + 1);
10397 #ifdef IMAP_STORAGE
10404 cmd =
forward_message(chan, context, &vms, vmu, vmfmts, 0, record_gain, in_urgent);
10423 ast_debug(1,
"No more urgent messages, opened INBOX and got %d new messages\n", vms.
lastmsg + 1);
10448 }
else if (cmd > 0) {
10449 box = cmd = cmd -
'0';
10454 #ifndef IMAP_STORAGE
10466 snprintf(vms.
fn,
sizeof(vms.
fn),
"vm-%s",
mbox(vmu, box));
10499 ast_debug(1,
"No more urgent messages, opened INBOX and got %d new messages\n", vms.
lastmsg + 1);
10513 if (!strncasecmp(chan->
language,
"he", 2)) {
10526 cmd =
vm_options(chan, vmu, &vms, vmfmts, record_gain);
10536 if ((cmd ==
't') || (cmd ==
'#')) {
10563 int new = 0, old = 0, urgent = 0;
10564 snprintf(ext_context,
sizeof(ext_context),
"%s@%s", vms.
username, vmu->
context);
10571 #ifdef IMAP_STORAGE
10573 ast_debug(3,
"*** Checking if we can expunge, deleted set to %d, expungeonhangup set to %d\n", deleted, expungeonhangup);
10574 if (vmu && deleted == 1 && expungeonhangup == 1 && vms.mailstream != NULL) {
10576 #ifdef HAVE_IMAP_TK2006
10577 if (LEVELUIDPLUS (vms.mailstream)) {
10578 mail_expunge_full(vms.mailstream, NIL, EX_UID);
10581 mail_expunge(vms.mailstream);
10587 vmstate_delete(&vms);
10593 #ifdef IMAP_STORAGE
10594 pthread_setspecific(ts_vmstate.key, NULL);
10611 memset(&leave_options, 0,
sizeof(leave_options));
10619 if (
args.argc == 2) {
10627 ast_log(
AST_LOG_WARNING,
"Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
10635 leave_options.
exitcontext = opts[OPT_ARG_DTMFEXIT];
10640 res =
ast_app_getdata(chan,
"vm-whichbox", temp,
sizeof(temp) - 1, 0);
10672 ast_log(
LOG_WARNING,
"Mailbox %s in context %s begins with '*' character. The '*' character,"
10673 "\n\twhen it is the first character in a mailbox or password, is used to jump to a"
10674 "\n\tpredefined extension 'a'. A mailbox or password beginning with '*' is not valid"
10675 "\n\tand will be ignored.\n", box, context);
10681 if (strcasecmp(vmu->
context, context)) {
10682 ast_log(
LOG_WARNING,
"\nIt has been detected that you have defined mailbox '%s' in separate\
10683 \n\tcontexts and that you have the 'searchcontexts' option on. This type of\
10684 \n\tconfiguration creates an ambiguity that you likely do not want. Please\
10685 \n\tamend your voicemail.conf file to avoid this situation.\n", box);
10690 if (!strcasecmp(context, vmu->
context) && !strcasecmp(box, vmu->
mailbox)) {
10691 ast_log(
LOG_WARNING,
"Ignoring duplicated mailbox %s in context %s\n", box, context);
10714 char *mailbox_full;
10715 int new = 0, old = 0, urgent = 0;
10716 char secretfn[PATH_MAX] =
"";
10726 if ((s =
strsep(&stringp,
","))) {
10729 "\n\tmust be reset in voicemail.conf.\n", box);
10734 if (stringp && (s =
strsep(&stringp,
","))) {
10737 if (stringp && (s =
strsep(&stringp,
","))) {
10740 if (stringp && (s =
strsep(&stringp,
","))) {
10743 if (stringp && (s =
strsep(&stringp,
","))) {
10749 snprintf(secretfn,
sizeof(secretfn),
"%s%s/%s/secret.conf", VM_SPOOL_DIR, vmu->
context, vmu->
mailbox);
10753 mailbox_full =
ast_alloca(strlen(box) + strlen(context) + 1);
10754 strcpy(mailbox_full, box);
10755 strcat(mailbox_full,
"@");
10756 strcat(mailbox_full, context);
10769 static const char options_string[] =
"attach=yes|attachfmt=wav49|"
10770 "serveremail=someguy@digium.com|tz=central|delete=yes|saycid=yes|"
10771 "sendvoicemail=yes|review=yes|tempgreetwarn=yes|messagewrap=yes|operator=yes|"
10772 "envelope=yes|moveheard=yes|sayduration=yes|saydurationm=5|forcename=yes|"
10773 "forcegreetings=yes|callback=somecontext|dialout=somecontext2|"
10774 "exitcontext=somecontext3|minsecs=10|maxsecs=100|nextaftercmd=yes|"
10775 "backupdeleted=50|volgain=1.3|passwordlocation=spooldir|emailbody="
10776 "Dear ${VM_NAME}:\n\n\tYou were just left a ${VM_DUR} long message|emailsubject="
10777 "[PBX]: New message \\\\${VM_MSGNUM}\\\\ in mailbox ${VM_MAILBOX}";
10778 #ifdef IMAP_STORAGE
10779 static const char option_string2[] =
"imapuser=imapuser|imappassword=imappasswd|"
10780 "imapfolder=INBOX|imapvmshareid=6000";
10785 info->name =
"vmuser";
10786 info->category =
"/apps/app_voicemail/";
10787 info->summary =
"Vmuser unit test";
10788 info->description =
10789 "This tests passing all supported parameters to apply_options, the voicemail user config parser";
10807 if (strcasecmp(vmu->
attachfmt,
"wav49")) {
10811 if (strcasecmp(vmu->
serveremail,
"someguy@digium.com")) {
10815 if (!vmu->
emailsubject || strcasecmp(vmu->
emailsubject,
"[PBX]: New message \\${VM_MSGNUM}\\ in mailbox ${VM_MAILBOX}")) {
10819 if (!vmu->
emailbody || strcasecmp(vmu->
emailbody,
"Dear ${VM_NAME}:\n\n\tYou were just left a ${VM_DUR} long message")) {
10823 if (strcasecmp(vmu->
zonetag,
"central")) {
10879 if (strcasecmp(vmu->
callback,
"somecontext")) {
10883 if (strcasecmp(vmu->
dialout,
"somecontext2")) {
10887 if (strcasecmp(vmu->
exit,
"somecontext3")) {
10915 #ifdef IMAP_STORAGE
10918 if (strcasecmp(vmu->imapuser,
"imapuser")) {
10922 if (strcasecmp(vmu->imappassword,
"imappasswd")) {
10926 if (strcasecmp(vmu->imapfolder,
"INBOX")) {
10930 if (strcasecmp(vmu->imapvmshareid,
"6000")) {
10948 static int dep_warning = 0;
10955 if (!dep_warning) {
10957 ast_log(
AST_LOG_WARNING,
"MailboxExists is deprecated. Please use ${MAILBOX_EXISTS(%s)} instead.\n", (
char *) data);
10964 if (
args.options) {
10967 if ((context = strchr(
args.mbox,
'@'))) {
10991 ast_log(
LOG_ERROR,
"MAILBOX_EXISTS requires an argument (<mailbox>[@<context>])\n");
11000 .
name =
"MAILBOX_EXISTS",
11008 char *options = NULL;
11009 int silent = 0, skipuser = 0;
11015 options =
strsep(&s,
",");
11019 context =
strsep(&s,
"");
11027 silent = (strchr(options,
's')) != NULL;
11030 if (!
vm_authenticate(chan, mailbox,
sizeof(mailbox), &vmus, context, NULL, skipuser, 3, silent)) {
11035 }
else if (mailbox[0] ==
'*') {
11048 const char *cat = NULL;
11057 "=============================================================\n"
11058 "=== Configured Voicemail Users ==============================\n"
11059 "=============================================================\n"
11065 "=== Mailbox ...\n"
11071 "=== ---------------------------------------------------------\n"
11076 "=============================================================\n"
11089 const char *context =
"";
11095 return (state == 0) ?
ast_strdup(
"for") : NULL;
11096 wordlen = strlen(word);
11098 if (!strncasecmp(word, vmu->
context, wordlen)) {
11099 if (context && strcmp(context, vmu->
context) && ++which > state)
11112 #define HVSU_OUTPUT_FORMAT "%-10s %-5s %-25s %-10s %6s\n"
11113 const char *context = NULL;
11114 int users_counter = 0;
11118 e->
command =
"voicemail show users";
11120 "Usage: voicemail show users [for <context>]\n"
11121 " Lists all mailboxes currently set up\n";
11129 if (a->
argc == 5) {
11130 if (strcmp(a->
argv[3],
"for"))
11132 context = a->
argv[4];
11137 ast_cli(a->
fd,
"You must specify a specific context to show users from realtime!\n");
11145 ast_cli(a->
fd,
"There are no voicemail users currently defined\n");
11154 if (!strcmp(context, vmu->
context)) {
11162 ast_cli(a->
fd,
"No such voicemail context \"%s\"\n", context);
11168 int newmsgs = 0, oldmsgs = 0;
11169 char count[12], tmp[256] =
"";
11171 if (!context || !strcmp(context, vmu->
context)) {
11174 snprintf(count,
sizeof(count),
"%d", newmsgs);
11180 ast_cli(a->
fd,
"%d voicemail users configured.\n", users_counter);
11187 struct vm_zone *zone;
11188 #define HVSZ_OUTPUT_FORMAT "%-15s %-20s %-45s\n"
11193 e->
command =
"voicemail show zones";
11195 "Usage: voicemail show zones\n"
11196 " Lists zone message formats\n";
11212 ast_cli(a->
fd,
"There are no voicemail zones currently defined\n");
11225 e->
command =
"voicemail reload";
11227 "Usage: voicemail reload\n"
11228 " Reload voicemail configuration\n";
11237 ast_cli(a->
fd,
"Reloading voicemail configuration...\n");
11249 #ifdef IMAP_STORAGE
11250 #define DATA_EXPORT_VM_USERS(USER) \
11251 USER(ast_vm_user, context, AST_DATA_STRING) \
11252 USER(ast_vm_user, mailbox, AST_DATA_STRING) \
11253 USER(ast_vm_user, password, AST_DATA_PASSWORD) \
11254 USER(ast_vm_user, fullname, AST_DATA_STRING) \
11255 USER(ast_vm_user, email, AST_DATA_STRING) \
11256 USER(ast_vm_user, emailsubject, AST_DATA_STRING) \
11257 USER(ast_vm_user, emailbody, AST_DATA_STRING) \
11258 USER(ast_vm_user, pager, AST_DATA_STRING) \
11259 USER(ast_vm_user, serveremail, AST_DATA_STRING) \
11260 USER(ast_vm_user, language, AST_DATA_STRING) \
11261 USER(ast_vm_user, zonetag, AST_DATA_STRING) \
11262 USER(ast_vm_user, callback, AST_DATA_STRING) \
11263 USER(ast_vm_user, dialout, AST_DATA_STRING) \
11264 USER(ast_vm_user, uniqueid, AST_DATA_STRING) \
11265 USER(ast_vm_user, exit, AST_DATA_STRING) \
11266 USER(ast_vm_user, attachfmt, AST_DATA_STRING) \
11267 USER(ast_vm_user, flags, AST_DATA_UNSIGNED_INTEGER) \
11268 USER(ast_vm_user, saydurationm, AST_DATA_INTEGER) \
11269 USER(ast_vm_user, maxmsg, AST_DATA_INTEGER) \
11270 USER(ast_vm_user, maxdeletedmsg, AST_DATA_INTEGER) \
11271 USER(ast_vm_user, maxsecs, AST_DATA_INTEGER) \
11272 USER(ast_vm_user, imapuser, AST_DATA_STRING) \
11273 USER(ast_vm_user, imappassword, AST_DATA_STRING) \
11274 USER(ast_vm_user, imapvmshareid, AST_DATA_STRING) \
11275 USER(ast_vm_user, volgain, AST_DATA_DOUBLE)
11277 #define DATA_EXPORT_VM_USERS(USER) \
11278 USER(ast_vm_user, context, AST_DATA_STRING) \
11279 USER(ast_vm_user, mailbox, AST_DATA_STRING) \
11280 USER(ast_vm_user, password, AST_DATA_PASSWORD) \
11281 USER(ast_vm_user, fullname, AST_DATA_STRING) \
11282 USER(ast_vm_user, email, AST_DATA_STRING) \
11283 USER(ast_vm_user, emailsubject, AST_DATA_STRING) \
11284 USER(ast_vm_user, emailbody, AST_DATA_STRING) \
11285 USER(ast_vm_user, pager, AST_DATA_STRING) \
11286 USER(ast_vm_user, serveremail, AST_DATA_STRING) \
11287 USER(ast_vm_user, language, AST_DATA_STRING) \
11288 USER(ast_vm_user, zonetag, AST_DATA_STRING) \
11289 USER(ast_vm_user, callback, AST_DATA_STRING) \
11290 USER(ast_vm_user, dialout, AST_DATA_STRING) \
11291 USER(ast_vm_user, uniqueid, AST_DATA_STRING) \
11292 USER(ast_vm_user, exit, AST_DATA_STRING) \
11293 USER(ast_vm_user, attachfmt, AST_DATA_STRING) \
11294 USER(ast_vm_user, flags, AST_DATA_UNSIGNED_INTEGER) \
11295 USER(ast_vm_user, saydurationm, AST_DATA_INTEGER) \
11296 USER(ast_vm_user, maxmsg, AST_DATA_INTEGER) \
11297 USER(ast_vm_user, maxdeletedmsg, AST_DATA_INTEGER) \
11298 USER(ast_vm_user, maxsecs, AST_DATA_INTEGER) \
11299 USER(ast_vm_user, volgain, AST_DATA_DOUBLE)
11304 #define DATA_EXPORT_VM_ZONES(ZONE) \
11305 ZONE(vm_zone, name, AST_DATA_STRING) \
11306 ZONE(vm_zone, timezone, AST_DATA_STRING) \
11307 ZONE(vm_zone, msg_format, AST_DATA_STRING)
11321 struct ast_data *data_user, *data_zone;
11323 struct vm_zone *zone = NULL;
11324 int urgentmsg = 0, newmsg = 0, oldmsg = 0;
11325 char ext_context[256] =
"";
11347 snprintf(ext_context,
sizeof(ext_context),
"%s@%s", user->
mailbox, user->
context);
11348 inboxcount2(ext_context, &urgentmsg, &newmsg, &oldmsg);
11385 AST_DATA_ENTRY(
"asterisk/application/voicemail/list", &vm_users_data_provider)
11390 int new = 0, old = 0, urgent = 0;
11392 inboxcount2(mwi_sub->mailbox, &urgent, &
new, &old);
11394 if (urgent != mwi_sub->old_urgent ||
new != mwi_sub->old_new || old != mwi_sub->old_old) {
11395 mwi_sub->old_urgent = urgent;
11396 mwi_sub->old_new =
new;
11397 mwi_sub->old_old = old;
11418 while (poll_thread_run) {
11419 struct timespec ts = { 0, };
11420 struct timeval wait;
11423 ts.tv_sec = wait.tv_sec;
11424 ts.tv_nsec = wait.tv_usec * 1000;
11430 if (!poll_thread_run)
11447 uint32_t *uniqueid = datap;
11451 if (mwi_sub->uniqueid == *uniqueid) {
11472 len =
sizeof(*mwi_sub);
11477 len += strlen(p->
context) + 1;
11484 strcpy(mwi_sub->mailbox, p->
mailbox);
11487 strcat(mwi_sub->mailbox,
"@");
11488 strcat(mwi_sub->mailbox, p->
context);
11537 if ((mwist =
ast_calloc(1, (
sizeof(*mwist)))) == NULL) {
11564 poll_thread_run = 1;
11573 poll_thread_run = 0;
11577 mwi_sub_sub = NULL;
11580 if (mwi_unsub_sub) {
11582 mwi_unsub_sub = NULL;
11589 pthread_join(poll_thread, NULL);
11599 char actionid[128] =
"";
11602 snprintf(actionid,
sizeof(actionid),
"ActionID: %s\r\n",
id);
11607 astman_send_ack(s, m,
"There are no voicemail users currently defined.");
11617 #ifdef IMAP_STORAGE
11625 "Event: VoicemailUserEntry\r\n"
11626 "VMContext: %s\r\n"
11627 "VoiceMailbox: %s\r\n"
11631 "ServerEmail: %s\r\n"
11632 "MailCommand: %s\r\n"
11638 "ExitContext: %s\r\n"
11639 "SayDurationMinimum: %d\r\n"
11640 "SayEnvelope: %s\r\n"
11642 "AttachMessage: %s\r\n"
11643 "AttachmentFormat: %s\r\n"
11644 "DeleteMessage: %s\r\n"
11645 "VolumeGain: %.2f\r\n"
11646 "CanReview: %s\r\n"
11647 "CallOperator: %s\r\n"
11648 "MaxMessageCount: %d\r\n"
11649 "MaxMessageLength: %d\r\n"
11650 "NewMessageCount: %d\r\n"
11651 #ifdef IMAP_STORAGE
11652 "OldMessageCount: %d\r\n"
11681 #ifdef IMAP_STORAGE
11682 new, old, vmu->imapuser
11688 astman_append(s,
"Event: VoicemailUserEntryComplete\r\n%s\r\n", actionid);
11710 struct vm_zone *zcur;
11727 for (current = (
char *) value; *current; current++) {
11728 if (*current ==
'\\') {
11734 switch (*current) {
11742 #ifdef IMAP_STORAGE
11743 if (!str->used || str->str[str->used - 1] !=
'\r') {
11777 ast_log(
LOG_ERROR,
"Config file users.conf is in an invalid format. Avoiding.\n");
11792 ast_log(
LOG_ERROR,
"Config file users.conf is in an invalid format. Avoiding.\n");
11805 #ifdef TEST_FRAMEWORK
11820 char *q, *stringp, *tmp;
11822 unsigned int tmpadsi[4];
11823 char secretfn[PATH_MAX] =
"";
11825 #ifdef IMAP_STORAGE
11843 memset(ext_pass_cmd, 0,
sizeof(ext_pass_cmd));
11844 memset(ext_pass_check_cmd, 0,
sizeof(ext_pass_check_cmd));
11863 sscanf(val,
"%30lf", &volgain);
11865 #ifdef ODBC_STORAGE
11866 strcpy(odbc_database,
"asterisk");
11870 strcpy(odbc_table,
"voicemessages");
11882 maxsilence = atoi(val);
11883 if (maxsilence > 0)
11884 maxsilence *= 1000;
11890 maxmsg = atoi(val);
11903 if (sscanf(val,
"%30d", &x) == 1)
11910 if (maxdeletedmsg < 0) {
11940 ast_copy_string(ext_pass_check_cmd, val,
sizeof(ext_pass_check_cmd));
11944 #ifdef IMAP_STORAGE
11972 expungeonhangup = 0;
11974 expungeonhangup = 1;
11976 expungeonhangup = 1;
12006 mail_parameters(NIL, SET_READTIMEOUT, (
void *) (atol(val)));
12008 mail_parameters(NIL, SET_READTIMEOUT, (
void *) 60L);
12012 mail_parameters(NIL, SET_WRITETIMEOUT, (
void *) (atol(val)));
12014 mail_parameters(NIL, SET_WRITETIMEOUT, (
void *) 60L);
12018 mail_parameters(NIL, SET_OPENTIMEOUT, (
void *) (atol(val)));
12020 mail_parameters(NIL, SET_OPENTIMEOUT, (
void *) 60L);
12024 mail_parameters(NIL, SET_CLOSETIMEOUT, (
void *) (atol(val)));
12026 mail_parameters(NIL, SET_CLOSETIMEOUT, (
void *) 60L);
12035 ast_debug(1,
"found externnotify: %s\n", externnotify);
12037 externnotify[0] =
'\0';
12042 ast_debug(1,
"Enabled SMDI voicemail notification\n");
12046 ast_debug(1,
"No SMDI interface set, trying default (/dev/ttyS0)\n");
12050 ast_log(
AST_LOG_ERROR,
"No valid SMDI interface specfied, disabling SMDI voicemail notification\n");
12057 silencethreshold = atoi(val);
12065 if (sscanf(val,
"%30d", &x) == 1) {
12071 static int maxmessage_deprecate = 0;
12072 if (maxmessage_deprecate == 0) {
12073 maxmessage_deprecate = 1;
12076 if (sscanf(val,
"%30d", &x) == 1) {
12085 if (sscanf(val,
"%30d", &x) == 1) {
12087 if (maxsilence / 1000 >= vmminsecs) {
12094 static int maxmessage_deprecate = 0;
12095 if (maxmessage_deprecate == 0) {
12096 maxmessage_deprecate = 1;
12099 if (sscanf(val,
"%30d", &x) == 1) {
12101 if (maxsilence / 1000 >= vmminsecs) {
12116 ast_log(
LOG_ERROR,
"Error processing format string, defaulting to format 'wav'\n");
12124 if (sscanf(val,
"%30d", &x) == 1) {
12132 if (sscanf(val,
"%30d", &x) == 1) {
12141 if (sscanf(val,
"%30d", &x) == 1) {
12150 if (sscanf(val,
"%30d", &x) == 1) {
12168 ast_debug(1,
"VM_CID Internal context string: %s\n", val);
12172 q =
strsep(&stringp,
",");
12173 while ((*q ==
' ')||(*q ==
'\t'))
12175 ast_copy_string(cidinternalcontexts[x], q,
sizeof(cidinternalcontexts[x]));
12176 ast_debug(1,
"VM_CID Internal context %d: %s\n", x, cidinternalcontexts[x]);
12178 cidinternalcontexts[x][0] =
'\0';
12183 ast_debug(1,
"VM Review Option disabled globally\n");
12190 ast_debug(1,
"VM Temporary Greeting Reminder Option disabled globally\n");
12193 ast_debug(1,
"VM Temporary Greeting Reminder Option enabled globally\n");
12197 ast_debug(1,
"VM next message wrap disabled globally\n");
12203 ast_debug(1,
"VM Operator break disabled globally\n");
12209 ast_debug(1,
"VM CID Info before msg disabled globally\n");
12215 ast_debug(1,
"Send Voicemail msg disabled globally\n");
12221 ast_debug(1,
"ENVELOPE before msg enabled globally\n");
12227 ast_debug(1,
"Move Heard enabled globally\n");
12233 ast_debug(1,
"Autoset of Urgent flag on forwarded Urgent messages disabled globally\n");
12239 ast_debug(1,
"Duration info before msg enabled globally\n");
12244 saydurationminfo = 2;
12246 if (sscanf(val,
"%30d", &x) == 1) {
12247 saydurationminfo = x;
12254 ast_debug(1,
"We are not going to skip to the next msg after save/delete\n");
12261 ast_debug(1,
"found dialout context: %s\n", dialcontext);
12263 dialcontext[0] =
'\0';
12268 ast_debug(1,
"found callback context: %s\n", callcontext);
12270 callcontext[0] =
'\0';
12275 ast_debug(1,
"found operator context: %s\n", exitcontext);
12277 exitcontext[0] =
'\0';
12286 ast_copy_string(vm_invalid_password, val,
sizeof(vm_invalid_password));
12290 ast_copy_string(vm_reenterpassword, val,
sizeof(vm_reenterpassword));
12297 ast_copy_string(vm_prepend_timeout, val,
sizeof(vm_prepend_timeout));
12301 ast_copy_string(listen_control_forward_key, val,
sizeof(listen_control_forward_key));
12303 ast_copy_string(listen_control_reverse_key, val,
sizeof(listen_control_reverse_key));
12305 ast_copy_string(listen_control_pause_key, val,
sizeof(listen_control_pause_key));
12307 ast_copy_string(listen_control_restart_key, val,
sizeof(listen_control_restart_key));
12309 ast_copy_string(listen_control_stop_key, val,
sizeof(listen_control_stop_key));
12316 val =
"voicemail.conf";
12318 if (!(strcmp(val,
"spooldir"))) {
12326 if (sscanf(val,
"%30u", &poll_freq) != 1) {
12332 poll_mailboxes = 0;
12336 memset(fromstring, 0,
sizeof(fromstring));
12337 memset(pagerfromstring, 0,
sizeof(pagerfromstring));
12338 strcpy(charset,
"ISO-8859-1");
12343 if (emailsubject) {
12345 emailsubject = NULL;
12351 if (pagersubject) {
12353 pagersubject = NULL;
12364 sscanf(val,
"%2x%2x%2x%2x", &tmpadsi[0], &tmpadsi[1], &tmpadsi[2], &tmpadsi[3]);
12365 for (x = 0; x < 4; x++) {
12366 memcpy(&adsifdn[x], &tmpadsi[x], 1);
12370 sscanf(val,
"%2x%2x%2x%2x", &tmpadsi[0], &tmpadsi[1], &tmpadsi[2], &tmpadsi[3]);
12371 for (x = 0; x < 4; x++) {
12372 memcpy(&adsisec[x], &tmpadsi[x], 1);
12377 adsiver = atoi(val);
12402 if (!strcasecmp(cat,
"general")) {
12417 snprintf(secretfn,
sizeof(secretfn),
"%s%s/%s/secret.conf", VM_SPOOL_DIR, current->
context, current->
mailbox);
12427 if (strcasecmp(cat,
"general")) {
12429 if (strcasecmp(cat,
"zonemessages")) {
12442 tzone =
strsep(&msg_format,
"|,");
12483 char dir[PATH_MAX];
12484 snprintf(dir,
sizeof(dir),
"%s%s/%s/greet", VM_SPOOL_DIR, context, mailbox);
12485 ast_debug(2,
"About to try retrieving name file %s\n", dir);
12486 RETRIEVE(dir, -1, mailbox, context);
12508 ast_log(
LOG_NOTICE,
"Failed reading voicemail password from %s, using secret from config file\n", secretfn);
12556 if ((context = strchr(args_copy,
'@'))) {
12559 context =
"default";
12562 if ((res =
sayname(chan, args_copy, context) < 0)) {
12563 ast_debug(3,
"Greeting not found for '%s@%s', falling back to mailbox number.\n", args_copy, context);
12573 #ifdef TEST_FRAMEWORK
12586 char dir[PATH_MAX];
12587 char dir2[PATH_MAX];
12588 static const char TEST_CONTEXT[] =
"very_long_unique_context_so_that_nobody_will_ever_have_the_same_one_configured_3141592653";
12589 static const char TEST_EXTENSION[] =
"1234";
12595 .
write = fake_write,
12601 info->name =
"vmsayname_exec";
12602 info->category =
"/apps/app_voicemail/";
12603 info->summary =
"Vmsayname unit test";
12604 info->description =
12605 "This tests passing various parameters to vmsayname";
12612 NULL, NULL, 0, 0,
"TestChannel1"))) {
12613 goto exit_vmsayname_test;
12622 test_channel1->
tech = &fake_tech;
12625 snprintf(dir,
sizeof(dir),
"%s@%s", TEST_EXTENSION, TEST_CONTEXT);
12627 snprintf(dir,
sizeof(dir),
"%s%s/%s/greet", VM_SPOOL_DIR, TEST_CONTEXT, TEST_EXTENSION);
12629 ast_test_status_update(test,
"This should not happen, most likely means clean up from previous test failed\n");
12631 goto exit_vmsayname_test;
12634 if ((res =
create_dirpath(dir,
sizeof(dir), TEST_CONTEXT, TEST_EXTENSION,
""))) {
12636 goto exit_vmsayname_test;
12639 snprintf(dir2,
sizeof(dir2),
"%s%s/%s/greet.gsm", VM_SPOOL_DIR, TEST_CONTEXT, TEST_EXTENSION);
12641 if ((res = symlink(dir, dir2))) {
12643 goto exit_vmsayname_test;
12646 snprintf(dir,
sizeof(dir),
"%s@%s", TEST_EXTENSION, TEST_CONTEXT);
12651 snprintf(dir2,
sizeof(dir2),
"%s%s/%s", VM_SPOOL_DIR, TEST_CONTEXT, TEST_EXTENSION);
12653 snprintf(dir2,
sizeof(dir2),
"%s%s", VM_SPOOL_DIR, TEST_CONTEXT);
12658 exit_vmsayname_test:
12660 if (test_channel1) {
12673 #ifdef IMAP_STORAGE
12682 const char origweasels[] =
"tt-weasels";
12683 const char testcontext[] =
"test";
12684 const char testmailbox[] =
"00000000";
12685 const char testspec[] =
"00000000@test";
12687 int new, old, urgent;
12688 const char *folders[3] = {
"Old",
"Urgent",
"INBOX" };
12689 const int folder2mbox[3] = { 1, 11, 0 };
12690 const int expected_results[3][12] = {
12692 { 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0 },
12693 { 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1 },
12694 { 1, 1, 1, 1, 0, 2, 1, 1, 1, 1, 1, 2 },
12699 info->name =
"test_voicemail_msgcount";
12700 info->category =
"/apps/app_voicemail/";
12701 info->summary =
"Test Voicemail status checks";
12702 info->description =
12703 "Verify that message counts are correct when retrieved through the public API";
12710 snprintf(syscmd,
sizeof(syscmd),
"rm -rf \"%s%s/%s\"", VM_SPOOL_DIR, testcontext, testmailbox);
12713 syserr > 0 ? strerror(syserr) :
"unable to fork()");
12717 #ifdef IMAP_STORAGE
12724 if (!(vmu =
find_user(&svm, testcontext, testmailbox)) &&
12728 #ifdef IMAP_STORAGE
12735 memset(&vms, 0,
sizeof(vms));
12738 for (i = 0; i < 3; i++) {
12739 create_dirpath(tmp[i].dir,
sizeof(tmp[i].dir), testcontext, testmailbox, folders[i]);
12740 make_file(tmp[i].file,
sizeof(tmp[i].file), tmp[i].dir, 0);
12741 snprintf(tmp[i].txtfile,
sizeof(tmp[i].txtfile),
"%s.txt", tmp[i].file);
12744 snprintf(syscmd,
sizeof(syscmd),
"cp \"%s/sounds/en/%s.gsm\" \"%s/%s/%s/%s/msg0000.gsm\"",
ast_config_AST_DATA_DIR, origweasels,
12745 VM_SPOOL_DIR, testcontext, testmailbox, folders[i]);
12748 syserr > 0 ? strerror(syserr) :
"unable to fork()");
12750 #ifdef IMAP_STORAGE
12757 if ((txt = fopen(tmp[i].txtfile,
"w+"))) {
12758 fprintf(txt,
"; just a stub\n[message]\nflag=%s\n", strcmp(folders[i],
"Urgent") ?
"" :
"Urgent");
12766 STORE(tmp[i].dir, testmailbox, testcontext, 0, chan, vmu,
"gsm", 600, &vms, strcmp(folders[i],
"Urgent") ?
"" :
"Urgent");
12769 for (j = 0; j < 3; j++) {
12778 new = old = urgent = 0;
12782 }
else if (old != expected_results[i][3 + 0] ||
new != expected_results[i][3 + 2]) {
12784 testspec, old, expected_results[i][3 + 0],
new, expected_results[i][3 + 2]);
12788 new = old = urgent = 0;
12792 }
else if (old != expected_results[i][6 + 0] ||
12793 urgent != expected_results[i][6 + 1] ||
12794 new != expected_results[i][6 + 2] ) {
12795 ast_test_status_update(test,
"inboxcount2(%s) returned old=%d (expected %d), urgent=%d (expected %d), and new=%d (expected %d)\n",
12796 testspec, old, expected_results[i][6 + 0], urgent, expected_results[i][6 + 1],
new, expected_results[i][6 + 2]);
12800 new = old = urgent = 0;
12801 for (j = 0; j < 3; j++) {
12802 if (
ast_app_messagecount(testcontext, testmailbox, folders[j]) != expected_results[i][9 + j]) {
12804 testspec, folders[j],
ast_app_messagecount(testcontext, testmailbox, folders[j]), expected_results[i][9 + j]);
12810 for (i = 0; i < 3; i++) {
12814 DELETE(tmp[i].dir, 0, tmp[i].file, vmu);
12825 #ifdef IMAP_STORAGE
12830 snprintf(syscmd,
sizeof(syscmd),
"rm -rf \"%s%s/%s\"", VM_SPOOL_DIR, testcontext, testmailbox);
12833 syserr > 0 ? strerror(syserr) :
"unable to fork()");
12842 char testcontext[] =
"test";
12843 char testmailbox[] =
"00000000";
12844 char from[] =
"test@example.net", cidnum[] =
"1234", cidname[] =
"Mark Spencer", format[] =
"gsm";
12845 char attach[256], attach2[256];
12846 char buf[256] =
"";
12854 enum { INT, FLAGVAL, STATIC, STRPTR }
type;
12861 {
"plain jane config", STATIC, vmus.
password, .u.strval =
"1234" },
12862 {
"emailsubject", STRPTR, vmus.
emailsubject, .u.strval =
"Oogly boogly\xf8koogly with what appears to be UTF-8" },
12863 {
"emailbody", STRPTR, vmus.
emailbody, .u.strval =
"This is a test\n\twith multiple\nlines\nwithin\n" },
12864 {
"serveremail", STATIC, vmus.
serveremail, .u.strval =
"\"\xf8Something\xe8that\xd8seems to have UTF-8 chars\" <test@example.net>" },
12865 {
"attachment flag", FLAGVAL, &vmus.
flags, .u.intval =
VM_ATTACH },
12866 {
"attach2", STRPTR, attach2, .u.strval =
"" },
12867 {
"attach", STRPTR, attach, .u.strval =
"" },
12873 info->name =
"test_voicemail_notify_endl";
12874 info->category =
"/apps/app_voicemail/";
12875 info->summary =
"Test Voicemail notification end-of-line";
12876 info->description =
12877 "Verify that notification emails use a consistent end-of-line character";
12886 if (!(vmu =
find_user(&vmus, testcontext, testmailbox)) &&
12892 if (vmu != &vmus && !(vmu =
find_user(&vmus, testcontext, testmailbox))) {
12899 #ifdef IMAP_STORAGE
12904 for (which = 0; which <
ARRAY_LEN(test_items); which++) {
12907 if (ftruncate(fileno(file), 0)) {
12914 if (test_items[which].
type == INT) {
12915 *((
int *) test_items[which].location) = test_items[which].u.intval;
12916 }
else if (test_items[which].
type == FLAGVAL) {
12922 }
else if (test_items[which].
type == STATIC) {
12923 strcpy(test_items[which].location, test_items[which].u.strval);
12924 }
else if (test_items[which].
type == STRPTR) {
12925 test_items[which].location = test_items[which].u.strval;
12928 make_email_file(file, from, vmu, 0, testcontext, testmailbox,
"INBOX", cidnum, cidname, attach, attach2, format, 999, 1, chan, NULL, 0, NULL);
12930 while (fgets(buf,
sizeof(buf), file)) {
12932 #ifdef IMAP_STORAGE
12933 buf[strlen(buf) - 2] !=
'\r'
12935 buf[strlen(buf) - 2] ==
'\r'
12937 || buf[strlen(buf) - 1] !=
'\n') {
12951 char config_filename[32] =
"/tmp/voicemail.conf.XXXXXX";
12958 info->name =
"test_voicemail_load_config";
12959 info->category =
"/apps/app_voicemail/";
12960 info->summary =
"Test loading Voicemail config";
12961 info->description =
12962 "Verify that configuration is loaded consistently. "
12963 "This is to test regressions of ASTERISK-18838 where it was noticed that "
12964 "some options were loaded after the mailboxes were instantiated, causing "
12965 "those options not to be set correctly.";
12972 if ((fd = mkstemp(config_filename)) < 0) {
12975 if (!(file = fdopen(fd,
"w"))) {
12977 unlink(config_filename);
12980 fputs(
"[general]\ncallback=somecontext\nlocale=de_DE.UTF-8\ntz=european\n[test]", file);
12981 fputs(
"00000001 => 9999,Mr. Test,,,callback=othercontext|locale=nl_NL.UTF-8|tz=central\n", file);
12982 fputs(
"00000002 => 9999,Mrs. Test\n", file);
12990 load_config_from_memory(1, cfg, NULL);
12993 #define CHECK(u, attr, value) else if (strcmp(u->attr, value)) { \
12994 ast_test_status_update(test, "mailbox %s should have %s '%s', but has '%s'\n", \
12995 u->mailbox, #attr, value, u->attr); res = AST_TEST_FAIL; break; }
12999 if (!strcmp(vmu->
mailbox,
"00000001")) {
13001 CHECK(vmu, callback,
"othercontext")
13002 CHECK(vmu, locale, "nl_NL.UTF-8")
13003 CHECK(vmu, zonetag, "central")
13004 }
else if (!strcmp(vmu->mailbox, "00000002")) {
13006 CHECK(vmu, callback,
"somecontext")
13007 CHECK(vmu, locale, "de_DE.UTF-8")
13008 CHECK(vmu, zonetag, "european")
13019 unlink(config_filename);
13042 #ifdef TEST_FRAMEWORK
13051 ao2_ref(inprocess_container, -1);
13068 my_umask = umask(0);
13092 #ifdef TEST_FRAMEWORK
13116 char destination[80] =
"";
13120 ast_verb(3,
"Destination number will be entered manually\n");
13121 while (retries < 3 && cmd !=
't') {
13122 destination[1] =
'\0';
13131 destination[0] = cmd;
13140 ast_verb(3,
"User hit '*' to cancel outgoing call\n");
13143 if ((cmd =
ast_readstring(chan, destination + strlen(destination),
sizeof(destination) - 1, 6000, 10000,
"#")) < 0)
13150 if (retries >= 3) {
13161 if (destination[strlen(destination) -1 ] ==
'*')
13189 char filename[PATH_MAX];
13191 const char *origtime, *
context;
13202 snprintf(filename,
sizeof(filename),
"%s.txt", vms->
fn);
13219 if (!strncasecmp(
"macro", context, 5))
13237 while ((res > -1) && (res !=
't')) {
13261 ast_verb(3,
"Caller can not specify callback number - no dialout context available\n");
13283 ast_verb(3,
"Confirm CID number '%s' is number to use for callback\n", num);
13319 else if (res ==
'*')
13331 ast_verb(3,
"No CID number available, no reply sent\n");
13341 snprintf(mailbox,
sizeof(mailbox),
"%s@%s", num, vmu->
context);
13343 ast_verb(3,
"Leaving voicemail for '%s' in context '%s'\n", num, vmu->
context);
13345 memset(&leave_options, 0,
sizeof(leave_options));
13354 ast_verb(3,
"No mailbox number '%s' in context '%s', no reply sent\n", num, vmu->
context);
13368 #ifndef IMAP_STORAGE
13371 vms->
heard[msg] = 1;
13379 int outsidecaller,
struct ast_vm_user *vmu,
int *duration,
int *sound_duration,
const char *unlockdir,
13385 int max_attempts = 3;
13388 int msg_exists = 0;
13389 signed char zero_gain = 0;
13390 char tempfile[PATH_MAX];
13392 char *canceldtmf =
"";
13393 int canceleddtmf = 0;
13398 if (duration == NULL) {
13403 if (!outsidecaller)
13404 snprintf(tempfile,
sizeof(tempfile),
"%s.tmp", recordfile);
13410 while ((cmd >= 0) && (cmd !=
't')) {
13419 ast_verb(3,
"Saving message as is\n");
13420 if (!outsidecaller)
13423 if (!outsidecaller) {
13433 ast_verb(3,
"Reviewing the message\n");
13440 ast_verb(3,
"Re-recording the message\n");
13442 ast_verb(3,
"Recording the message\n");
13444 if (recorded && outsidecaller) {
13454 cmd =
ast_play_and_record_full(chan, playfile, tempfile, maxtime, fmt, duration, sound_duration, silencethreshold, maxsilence, unlockdir, acceptdtmf, canceldtmf);
13455 if (strchr(canceldtmf, cmd)) {
13463 if (!outsidecaller) {
13471 }
else if (cmd ==
'*') {
13474 }
else if (vmu->review && sound_duration && (*sound_duration < 5)) {
13476 ast_verb(3,
"Message too short\n");
13480 }
else if (vmu->review && (cmd == 2 && sound_duration && *sound_duration < (maxsilence + 3))) {
13482 ast_verb(3,
"Nothing recorded\n");
13496 if (outsidecaller) {
13501 strcpy(flag,
"Urgent");
13530 if (outsidecaller) {
13542 if (msg_exists || recorded) {
13550 }
else if (cmd ==
'4') {
13553 strcpy(flag,
"Urgent");
13559 DELETE(tempfile, -1, tempfile, vmu);
13572 if (!cmd && outsidecaller) {
13599 if (attempts > max_attempts) {
13604 if (!outsidecaller && (cmd == -1 || cmd ==
't')) {
13609 if (cmd !=
't' && outsidecaller)
13623 .nonoptreq =
"res_adsi,res_smdi",
static const char * ast_str_encode_mime(struct ast_str **end, ssize_t maxlen, const char *start, size_t preamble, size_t postamble)
Encode a string according to the MIME rules for encoding strings that are not 7-bit clean or contain ...
int ast_filecopy(const char *oldname, const char *newname, const char *fmt)
Copies a file.
static void adsi_password(struct ast_channel *chan)
static void poll_subscribed_mailboxes(void)
static int vm_options(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain)
#define AST_THREADSTORAGE(name)
Define a thread storage variable.
static int vm_intro_fr(struct ast_channel *chan, struct vm_state *vms)
static void mwi_unsub_event_cb(const struct ast_event *event, void *userdata)
int ast_hangup(struct ast_channel *chan)
Hang up a channel.
#define SMDI_MWI_WAIT_TIMEOUT
static char listen_control_restart_key[12]
static int vm_play_folder_name_pl(struct ast_channel *chan, char *box)
#define ast_channel_lock(chan)
static int vm_intro(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms)
static char exten[AST_MAX_EXTENSION]
Main Channel structure associated with a channel.
int ast_adsi_voice_mode(unsigned char *buf, int when)
Puts CPE in voice mode.
static struct ast_flags globalflags
#define AST_CLI_DEFINE(fn, txt,...)
char * str
Subscriber phone number (Malloced)
static int check_mime(const char *str)
Check if the string would need encoding within the MIME standard, to avoid confusing certain mail sof...
#define AST_APP_OPTION_ARG(option, flagno, argno)
Declares an application option that accepts an argument.
int ast_store_realtime(const char *family,...) attribute_sentinel
Create realtime configuration.
static int inboxcount2(const char *mailbox, int *urgentmsgs, int *newmsgs, int *oldmsgs)
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
#define AST_LIST_LOCK(head)
Locks a list.
static struct ast_vm_user * find_user(struct ast_vm_user *ivm, const char *context, const char *mailbox)
Finds a voicemail user from the users file or the realtime engine.
int ast_safe_system(const char *s)
Safely spawn an external program while closing file descriptors.
Asterisk locking-related definitions:
void astman_append(struct mansession *s, const char *fmt,...)
Asterisk main include file. File version handling, generic pbx functions.
#define ao2_link(arg1, arg2)
static char listen_control_forward_key[12]
static struct ast_vm_user * find_user_realtime(struct ast_vm_user *ivm, const char *context, const char *mailbox)
Finds a voicemail user from the realtime engine.
static int vm_exec(struct ast_channel *chan, const char *data)
#define DEFAULT_LISTEN_CONTROL_REVERSE_KEY
const char * ast_variable_retrieve(const struct ast_config *config, const char *category, const char *variable)
Gets a variable.
int ast_adsi_begin_download(struct ast_channel *chan, char *service, unsigned char *fdn, unsigned char *sec, int version)
static void free_zone(struct vm_zone *z)
int ast_play_and_record_full(struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime_sec, const char *fmt, int *duration, int *sound_duration, int silencethreshold, int maxsilence_ms, const char *path, const char *acceptdtmf, const char *canceldtmf)
Record a file based on input from a channel This function will play "auth-thankyou" upon successful r...
#define AST_APP_OPTIONS(holder, options...)
Declares an array of options for an application.
static char vm_passchanged[80]
The data tree to be returned by the callbacks and managed by functions local to this file...
static int vmauthenticate(struct ast_channel *chan, const char *data)
static int inchar(struct baseio *bio, FILE *fi)
utility used by base_encode()
int ast_app_getdata(struct ast_channel *c, const char *prompt, char *s, int maxlen, int timeout)
Plays a stream and gets DTMF data from a channel.
struct ast_frame ast_null_frame
struct ast_party_caller caller
Channel Caller ID information.
static void * mb_poll_thread(void *data)
#define PWDCHANGE_EXTERNAL
char * strsep(char **str, const char *delims)
static char userscontext[AST_MAX_EXTENSION]
struct ast_app * pbx_findapp(const char *app)
Look up an application.
static int last_message_index(struct ast_vm_user *vmu, char *dir)
Determines the highest message number in use for a given user and mailbox folder. ...
static int vm_intro_pt_BR(struct ast_channel *chan, struct vm_state *vms)
int ast_callerid_split(const char *src, char *name, int namelen, char *num, int numlen)
int ast_safe_fork(int stop_reaper)
Common routine to safely fork without a chance of a signal handler firing badly in the child...
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized...
int pbx_exec(struct ast_channel *c, struct ast_app *app, const char *data)
Execute an application.
static int play_record_review(struct ast_channel *chan, char *playfile, char *recordfile, int maxtime, char *fmt, int outsidecaller, struct ast_vm_user *vmu, int *duration, int *sound_duration, const char *unlockdir, signed char record_gain, struct vm_state *vms, char *flag)
enum ast_event_type ast_event_get_type(const struct ast_event *event)
Get the type for an event.
static unsigned int poll_mailboxes
static int wait_file(struct ast_channel *chan, struct vm_state *vms, char *file)
int ast_adsi_data_mode(unsigned char *buf)
Puts CPE in data mode.
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
static unsigned char adsifdn[4]
#define ast_channel_unref(c)
Decrease channel reference count.
static int vm_intro_es(struct ast_channel *chan, struct vm_state *vms)
#define DELETE(a, b, c, d)
static int vm_intro_zh(struct ast_channel *chan, struct vm_state *vms)
int ast_control_streamfile(struct ast_channel *chan, const char *file, const char *fwd, const char *rev, const char *stop, const char *pause, const char *restart, int skipms, long *offsetms)
Stream a file with fast forward, pause, reverse, restart.
static int check_password(struct ast_vm_user *vmu, char *password)
Check that password meets minimum required length.
static int vm_delete(char *file)
Removes the voicemail sound and information file.
#define ast_set2_flag(p, value, flag)
#define ast_test_flag(p, flag)
static struct ast_event_sub * mwi_sub_sub
int ast_unload_realtime(const char *family)
Release any resources cached for a realtime family.
static int vm_newuser(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain)
static char * handle_voicemail_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Reload voicemail configuration from the CLI.
Time-related functions and macros.
struct ast_party_name name
Subscriber name.
struct ast_party_id from
Who is redirecting the call (Sent to the party the call is redirected toward)
static int advanced_options(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int msg, int option, signed char record_gain)
The advanced options within a message.
int ast_taskprocessor_push(struct ast_taskprocessor *tps, int(*task_exe)(void *datap), void *datap)
Push a task into the specified taskprocessor queue and signal the taskprocessor thread.
Convenient Signal Processing routines.
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
char context[AST_MAX_CONTEXT]
int ast_app_has_voicemail(const char *mailbox, const char *folder)
Determine if a given mailbox has any voicemail If folder is NULL, defaults to "INBOX". If folder is "INBOX", includes the number of messages in the "Urgent" folder.
static char pagerdateformat[32]
#define ast_set_flag(p, flag)
int ast_event_queue_and_cache(struct ast_event *event)
Queue and cache an event.
void ast_event_report_subs(const struct ast_event_sub *sub)
Report current subscriptions to a subscription subscriber.
descriptor for a cli entry.
#define DEFAULT_LISTEN_CONTROL_FORWARD_KEY
int ast_update2_realtime(const char *family,...) attribute_sentinel
Update realtime configuration.
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
static char vm_password[80]
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category)
Goes through variables.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
static char intro[ADSI_MAX_INTRO][20]
static int inbuf(struct baseio *bio, FILE *fi)
utility used by inchar(), for base_encode()
#define ASTERISK_USERNAME
struct ast_taskprocessor * ast_taskprocessor_get(const char *name, enum ast_tps_options create)
Get a reference to a taskprocessor with the specified name and create the taskprocessor if necessary...
static char externnotify[160]
void ast_verbose(const char *fmt,...)
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
static int add_email_attachment(FILE *p, struct ast_vm_user *vmu, char *format, char *attach, char *greeting_attachment, char *mailbox, char *bound, char *filename, int last, int msgnum)
struct ast_smdi_interface * ast_smdi_interface_find(const char *iface_name)
Find an SMDI interface with the specified name.
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
int ast_unlock_path(const char *path)
Unlock a path.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
static int create_dirpath(char *dest, int len, const char *context, const char *ext, const char *folder)
basically mkdir -p $dest/$context/$ext/$folder
This entries are for multiple registers.
static int unload_module(void)
Structure for variables, used for configurations and for channel variables.
static struct ast_vm_user * find_or_create(const char *context, const char *box)
#define DATA_EXPORT_VM_USERS(USER)
static int vm_play_folder_name_ua(struct ast_channel *chan, char *box)
int ast_adsi_set_keys(unsigned char *buf, unsigned char *keys)
Set which soft keys should be displayed.
static void adsi_delete(struct ast_channel *chan, struct vm_state *vms)
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
int ast_adsi_load_session(struct ast_channel *chan, unsigned char *app, int ver, int data)
Check if scripts for a given app are already loaded. Version may be -1, if any version is okay...
void ast_str_substitute_variables(struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ)
#define VOICEMAIL_DIR_MODE
struct ast_party_redirecting redirecting
Redirecting/Diversion information.
int ast_say_digit_str(struct ast_channel *chan, const char *num, const char *ints, const char *lang)
says digits of a string
#define AST_TEST_REGISTER(cb)
static void apply_option(struct ast_vm_user *vmu, const char *var, const char *value)
Sets a a specific property value.
static int vm_instructions_en(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int skipadvanced, int in_urgent)
Configuration File Parser.
int ast_adsi_download_disconnect(unsigned char *buf)
Disconnects (and hopefully saves) a downloaded script.
static void queue_mwi_event(const char *box, int urgent, int new, int old)
char * str
Subscriber name (Malloced)
int ast_config_text_file_save(const char *filename, const struct ast_config *cfg, const char *generator)
static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_options *options)
Prompts the user and records a voicemail to a mailbox.
struct ast_variable * ast_load_realtime(const char *family,...) attribute_sentinel
Retrieve realtime configuration.
static int vm_execmain(struct ast_channel *chan, const char *data)
#define DEFAULT_LISTEN_CONTROL_STOP_KEY
static unsigned int poll_freq
static int get_folder_by_name(const char *name)
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
static int has_voicemail(const char *mailbox, const char *folder)
Determines if the given folder has messages.
static struct ast_threadstorage buf2
static int vm_intro_no(struct ast_channel *chan, struct vm_state *vms)
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms)
Number of new messages Used by: AST_EVENT_MWI Payload type: UINT.
struct ast_str * ast_str_create(size_t init_len)
Create a malloc'ed dynamic length string.
static char listen_control_pause_key[12]
Number of Used by: AST_EVENT_MWI Payload type: UINT.
#define HVSZ_OUTPUT_FORMAT
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
static int vm_users_data_provider_get(const struct ast_data_search *search, struct ast_data *data_root)
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
#define ast_mutex_lock(a)
unsigned char iobuf[BASEMAXINLINE]
static int vm_instructions(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int skipadvanced, int in_urgent)
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
static void start_poll_thread(void)
#define ast_copy_flags(dest, src, flagz)
#define ast_str_alloca(init_len)
static int adsi_logo(unsigned char *buf)
const char * ast_config_option(struct ast_config *cfg, const char *cat, const char *var)
Retrieve a configuration variable within the configuration set.
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
static char * handle_voicemail_show_users(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Show a list of voicemail users in the CLI.
#define HVSU_OUTPUT_FORMAT
static int handle_unsubscribe(void *datap)
static int play_message_category(struct ast_channel *chan, const char *category)
Definitions to aid in the use of thread local storage.
static int vm_intro_nl(struct ast_channel *chan, struct vm_state *vms)
int ast_filedelete(const char *filename, const char *fmt)
Deletes a file.
void ast_cli(int fd, const char *fmt,...)
ADSI Support (built upon Caller*ID)
static int input(yyscan_t yyscanner)
static int vm_play_folder_name_gr(struct ast_channel *chan, char *box)
#define AST_DATA_ENTRY(__path, __handler)
int ast_channel_setoption(struct ast_channel *channel, int option, void *data, int datalen, int block)
Sets an option on a channel.
list of users found in the config file
static int vm_intro_it(struct ast_channel *chan, struct vm_state *vms)
int ast_unregister_application(const char *app)
Unregister an application.
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
static char vm_reenterpassword[80]
#define ast_cond_signal(cond)
#define ast_verb(level,...)
void ast_config_destroy(struct ast_config *config)
Destroys a config.
static int copy_message(struct ast_channel *chan, struct ast_vm_user *vmu, int imbox, int msgnum, long duration, struct ast_vm_user *recip, char *fmt, char *dir, const char *flag)
Copies a message from one mailbox to another.
void ast_unreplace_sigchld(void)
Restore the SIGCHLD handler.
static void free_vm_zones(void)
Free the zones structure.
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return * the previous value of *p. This can be used to handle reference co...
#define ast_test_suite_assert(exp)
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
struct ast_channel * ast_channel_alloc(int needqueue, int state, const char *cid_num, const char *cid_name, const char *acctcode, const char *exten, const char *context, const char *linkedid, const int amaflag, const char *name_fmt,...)
int ast_canmatch_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Looks for a valid matching extension.
static ast_mutex_t poll_lock
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
static void adsi_status(struct ast_channel *chan, struct vm_state *vms)
static int get_folder2(struct ast_channel *chan, char *fn, int start)
plays a prompt and waits for a keypress.
String fields in structures.
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
static void adsi_login(struct ast_channel *chan)
pthread_cond_t ast_cond_t
char cause[SMDI_MWI_FAIL_CAUSE_LEN+1]
#define ast_manager_event(chan, category, event, contents,...)
static int vm_browse_messages_he(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
struct ast_category * ast_category_new(const char *name, const char *in_file, int lineno)
Create a category structure.
static unsigned char adsisec[4]
int ast_smdi_mwi_set(struct ast_smdi_interface *iface, const char *mailbox)
Set the MWI indicator for a mailbox.
#define PWDCHANGE_INTERNAL
static void prep_email_sub_vars(struct ast_channel *ast, struct ast_vm_user *vmu, int msgnum, char *context, char *mailbox, const char *fromfolder, char *cidnum, char *cidname, char *dur, char *date, const char *category, const char *flag)
static struct ast_smdi_interface * smdi_iface
static void rename_file(char *sfn, char *dfn)
Renames a message in a mailbox folder.
#define ADSI_DIR_FROM_LEFT
Custom localtime functions for multiple timezones.
static int vm_box_exists(struct ast_channel *chan, const char *data)
#define RETRIEVE(a, b, c, d)
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
struct ast_party_id id
Caller party ID.
static int vm_intro_pt(struct ast_channel *chan, struct vm_state *vms)
struct ast_category * ast_category_get(const struct ast_config *config, const char *category_name)
Retrieve a category if it exists.
int ast_update_realtime(const char *family, const char *keyfield, const char *lookup,...) attribute_sentinel
Update realtime configuration.
#define MAX_NUM_CID_CONTEXTS
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
static void adsi_status2(struct ast_channel *chan, struct vm_state *vms)
int ast_get_time_t(const char *src, time_t *dst, time_t _default, int *consumed)
get values from config variables.
static int play_message_duration(struct ast_channel *chan, struct vm_state *vms, const char *duration, int minduration)
#define ast_debug(level,...)
Log a DEBUG message.
int ast_adsi_set_line(unsigned char *buf, int page, int line)
Sets the current line and page.
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
Play a stream and wait for a digit, returning the digit that was pressed.
enum AST_LOCK_RESULT ast_lock_path(const char *path)
Lock a filesystem path.
Context IE Used by AST_EVENT_MWI Payload type: str.
#define AST_DATA_HANDLER_VERSION
The Data API structures version.
void ast_category_destroy(struct ast_category *cat)
int ast_adsi_input_format(unsigned char *buf, int num, int dir, int wrap, char *format1, char *format2)
Set input format.
static FILE * vm_mkftemp(char *template)
int ast_say_counted_noun(struct ast_channel *chan, int num, const char *noun)
#define COPY(a, b, c, d, e, f, g, h)
int ast_build_string(char **buffer, size_t *space, const char *fmt,...)
Build a string in a buffer, designed to be called repeatedly.
static int sayname(struct ast_channel *chan, const char *mailbox, const char *context)
char * ast_callerid_merge(char *buf, int bufsiz, const char *name, const char *num, const char *unknown)
static char * pagersubject
static void vm_change_password(struct ast_vm_user *vmu, const char *newpassword)
The handler for the change password option.
General Asterisk PBX channel definitions.
int ast_destroy_realtime(const char *family, const char *keyfield, const char *lookup,...) attribute_sentinel
Destroy realtime configuration.
static int quote(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
static int saydurationminfo
static int load_config(int reload)
static char exitcontext[AST_MAX_CONTEXT]
static int vm_intro_de(struct ast_channel *chan, struct vm_state *vms)
#define ast_test_status_update(a, b, c...)
#define STORE(a, b, c, d, e, f, g, h, i, j)
#define ast_config_load(filename, flags)
Load a config file.
#define ast_manager_register_xml(a, b, c)
Register a manager callback using XML documentation to describe the manager.
static struct ast_event_sub * mwi_sub
static int inprocess_count(const char *context, const char *mailbox, int delta)
#define AST_PTHREADT_NULL
static int sendpage(char *srcemail, char *pager, int msgnum, char *context, char *mailbox, const char *fromfolder, char *cidnum, char *cidname, int duration, struct ast_vm_user *vmu, const char *category, const char *flag)
static force_inline int attribute_pure ast_strlen_zero(const char *s)
static int valid_config(const struct ast_config *cfg)
Check if configuration file is valid.
struct sla_ringing_trunk * last
Data structure associated with a custom dialplan function.
static char ext_pass_cmd[128]
struct ast_data * ast_data_add_node(struct ast_data *root, const char *childname)
Add a container child.
char mailbox[AST_MAX_EXTENSION]
#define AST_MAX_EXTENSION
#define AST_RWLIST_TRAVERSE
static void apply_options(struct ast_vm_user *vmu, const char *options)
Destructively Parse options and apply.
#define ast_data_unregister(path)
static void run_externnotify(char *context, char *extension, const char *flag)
static char * strip_control_and_high(const char *input, char *buf, size_t buflen)
Strips control and non 7-bit clean characters from input string.
static ast_cond_t poll_cond
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
static struct ast_data_handler vm_users_data_provider
char * ast_category_browse(struct ast_config *config, const char *prev)
Goes through categories.
#define ao2_ref(o, delta)
#define DEFAULT_LISTEN_CONTROL_PAUSE_KEY
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
static int wait_file2(struct ast_channel *chan, struct vm_state *vms, char *file)
#define DATA_EXPORT_VM_ZONES(ZONE)
char context[AST_MAX_CONTEXT]
long int ast_random(void)
static int vm_intro_cs(struct ast_channel *chan, struct vm_state *vms)
struct timeval ast_samp2tv(unsigned int _nsamp, unsigned int _rate)
Returns a timeval corresponding to the duration of n samples at rate r. Useful to convert samples to ...
static struct ast_app_option vm_app_options[128]
static int base_encode(char *filename, FILE *so)
Performs a base 64 encode algorithm on the contents of a File.
static char language[MAX_LANGUAGE]
int ast_adsi_display(unsigned char *buf, int page, int line, int just, int wrap, char *col1, char *col2)
Loads a line of info into the display.
int ast_strftime_locale(char *buf, size_t len, const char *format, const struct ast_tm *tm, const char *locale)
char * ast_format_str_reduce(char *fmts)
static int notify_new_message(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int msgnum, long duration, char *fmt, char *cidnum, char *cidname, const char *flag)
Sends email notification that a user has a new voicemail waiting for them.
static int vm_browse_messages_en(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
Default English syntax for 'You have N messages' greeting.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
int ast_app_inboxcount(const char *mailbox, int *newmsgs, int *oldmsgs)
Determine number of new/old messages in a mailbox.
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
static int vm_forwardoptions(struct ast_channel *chan, struct ast_vm_user *vmu, char *curdir, int curmsg, char *vm_fmts, char *context, signed char record_gain, long *duration, struct vm_state *vms, char *flag)
presents the option to prepend to an existing message when forwarding it.
#define ast_data_register_multiple(data_entries, entries)
static int vm_play_folder_name(struct ast_channel *chan, char *mbox)
static struct ast_data_entry vm_data_providers[]
Structure to describe a channel "technology", ie a channel driver See for examples: ...
Core PBX routines and definitions.
static char * show_users_realtime(int fd, const char *context)
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
static void copy_plain_file(char *frompath, char *topath)
Copies a voicemail information (envelope) file.
#define ast_data_add_structure(structure_name, root, structure)
int ast_app_inboxcount2(const char *mailbox, int *urgentmsgs, int *newmsgs, int *oldmsgs)
Determine number of urgent/new/old messages in a mailbox.
Event type Used by: AST_EVENT_SUB, AST_EVENT_UNSUB Payload type: UINT.
The list of nodes with their search requirement.
#define ASTOBJ_UNREF(object, destructor)
Decrement the reference count on an object.
#define AST_LIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a list of specified type, statically initialized.
static int play_message_datetime(struct ast_channel *chan, struct ast_vm_user *vmu, const char *origtime, const char *filename)
#define ast_test_suite_event_notify(s, f,...)
static void stop_poll_thread(void)
static void adsi_goodbye(struct ast_channel *chan)
const char * ast_config_AST_DATA_DIR
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
static int vm_intro_en(struct ast_channel *chan, struct vm_state *vms)
#define ast_strdupa(s)
duplicate a string in memory from the stack
int ast_adsi_transmit_message(struct ast_channel *chan, unsigned char *msg, int msglen, int msgtype)
static void populate_defaults(struct ast_vm_user *vmu)
Sets default voicemail system options to a voicemail user.
static int inprocess_cmp_fn(void *obj, void *arg, int flags)
#define AST_LIST_HEAD_NOLOCK_STATIC(name, type)
Defines a structure to be used to hold a list of specified type, statically initialized.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
SQLHSTMT ast_odbc_direct_execute(struct odbc_obj *obj, SQLHSTMT(*exec_cb)(struct odbc_obj *obj, void *data), void *data)
Executes an non prepared statement and returns the resulting statement handle.
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
static int acf_mailbox_exists(struct ast_channel *chan, const char *cmd, char *args, char *buf, size_t len)
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
static struct ast_tm * vmu_tm(const struct ast_vm_user *vmu, struct ast_tm *tm)
fill in *tm for current time according to the proper timezone, if any.
static int append_mailbox(const char *context, const char *box, const char *data)
void ast_data_remove_node(struct ast_data *root, struct ast_data *child)
Remove a node that was added using ast_data_add_.
#define AST_TEST_UNREGISTER(cb)
static char fromstring[100]
static char emaildateformat[32]
void ast_variable_append(struct ast_category *category, struct ast_variable *variable)
static int write_password_to_file(const char *secretfn, const char *password)
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
static const char * substitute_escapes(const char *value)
enum ast_channel_state _state
static char VM_SPOOL_DIR[PATH_MAX]
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
const ast_string_field name
static int vm_users_data_provider_get_helper(const struct ast_data_search *search, struct ast_data *data_root, struct ast_vm_user *user)
static int get_date(char *s, int len)
Gets the current date and time, as formatted string.
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
static unsigned char poll_thread_run
static int handle_subscribe(void *datap)
#define ao2_alloc(data_size, destructor_fn)
static int copy(char *infile, char *outfile)
Utility function to copy a file.
int ast_goto_if_exists(struct ast_channel *chan, const char *context, const char *exten, int priority)
static const char * ast_str_quote(struct ast_str **buf, ssize_t maxlen, const char *from)
Wraps a character sequence in double quotes, escaping occurences of quotes within the string...
static char vm_pls_try_again[80]
static struct ast_event_sub * mwi_unsub_sub
static int say_and_wait(struct ast_channel *chan, int num, const char *language)
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
int ast_say_counted_adjective(struct ast_channel *chan, int num, const char *adjective, const char *gender)
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
static struct ast_threadstorage buf1
#define DEFAULT_POLL_FREQ
static int __has_voicemail(const char *context, const char *mailbox, const char *folder, int shortcircuit)
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
#define ao2_find(arg1, arg2, arg3)
static int vm_authenticate(struct ast_channel *chan, char *mailbox, int mailbox_size, struct ast_vm_user *res_vmu, const char *context, const char *prefix, int skipuser, int max_logins, int silent)
#define ast_channel_unlock(chan)
static void parse(struct mgcp_request *req)
static char ext_pass_check_cmd[128]
static int actual_load_config(int reload, struct ast_config *cfg, struct ast_config *ucfg)
#define ast_pthread_create(a, b, c, d)
char macrocontext[AST_MAX_CONTEXT]
static const char * mbox(struct ast_vm_user *vmu, int id)
struct ast_config * ast_config_new(void)
Create a new base configuration structure.
int ast_adsi_end_download(struct ast_channel *chan)
static int vm_browse_messages_zh(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
Chinese (Taiwan)syntax for 'You have N messages' greeting.
int ast_stream_and_wait(struct ast_channel *chan, const char *file, const char *digits)
stream file until digit If the file name is non-empty, try to play it.
int ast_say_character_str(struct ast_channel *chan, const char *num, const char *ints, const char *lang)
#define ast_odbc_request_obj(a, b)
static char * emailsubject
static char * vm_check_password_shell(char *command, char *buf, size_t len)
static char dialcontext[AST_MAX_CONTEXT]
static int invent_message(struct ast_channel *chan, char *context, char *ext, int busy, char *ecodes)
void ast_close_fds_above_n(int n)
Common routine for child processes, to close all fds prior to exec(2)
SMDI support for Asterisk.
static pthread_t poll_thread
static void free_user(struct ast_vm_user *vmu)
int ast_adsi_load_soft_key(unsigned char *buf, int key, const char *llabel, const char *slabel, char *ret, int data)
Creates "load soft key" parameters.
static int inprocess_hash_fn(const void *obj, const int flags)
static char vm_mismatch[80]
static int count_messages(struct ast_vm_user *vmu, char *dir)
Find all .txt files - even if they are not in sequence from 0000.
static char * handle_voicemail_show_zones(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Show a list of voicemail zones in the CLI.
#define RENAME(a, b, c, d, e, f, g, h)
const char * ast_config_AST_SPOOL_DIR
int ast_strftime(char *buf, size_t len, const char *format, const struct ast_tm *tm)
Special version of strftime(3) that handles fractions of a second. Takes the same arguments as strfti...
static SQLHSTMT generic_prepare(struct odbc_obj *obj, void *data)
#define ADSI_MSG_DOWNLOAD
An API for managing task processing threads that can be shared across modules.
int ast_variable_update(struct ast_category *category, const char *variable, const char *value, const char *match, unsigned int object)
Update variable value within a config.
char fwd_st[SMDI_MAX_STATION_NUM_LEN+1]
static int make_file(char *dest, const int len, const char *dir, const int num)
Creates a file system path expression for a folder within the voicemail data folder and the appropria...
if(yyss+yystacksize-1<=yyssp)
#define EXISTS(a, b, c, d)
structure to hold users read from users.conf
static void * cleanup(void *unused)
#define VMSTATE_MAX_MSG_ARRAY
Structure used to handle boolean flags.
#define DEFAULT_LISTEN_CONTROL_RESTART_KEY
int ast_realtime_require_field(const char *family,...) attribute_sentinel
Inform realtime what fields that may be stored.
#define ast_clear_flag(p, flag)
Support for logging to various files, console and syslog Configuration in file logger.conf.
void ast_install_vm_functions(int(*has_voicemail_func)(const char *mailbox, const char *folder), int(*inboxcount_func)(const char *mailbox, int *newmsgs, int *oldmsgs), int(*inboxcount2_func)(const char *mailbox, int *urgentmsgs, int *newmsgs, int *oldmsgs), int(*messagecount_func)(const char *context, const char *mailbox, const char *folder), int(*sayname_func)(struct ast_channel *chan, const char *mailbox, const char *context))
Set voicemail function callbacks.
static int load_module(void)
Options for leaving voicemail with the voicemail() application.
static int silencethreshold
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
uint32_t ast_event_get_ie_uint(const struct ast_event *event, enum ast_event_ie_type ie_type)
Get the value of an information element that has an integer payload.
int(*const write)(struct ast_channel *chan, struct ast_frame *frame)
Write a frame, in standard format (see frame.h)
static int change_password_realtime(struct ast_vm_user *vmu, const char *password)
Performs a change of the voicemail passowrd in the realtime engine.
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
static void adsi_begin(struct ast_channel *chan, int *useadsi)
char language[MAX_LANGUAGE]
int ast_play_and_prepend(struct ast_channel *chan, char *playfile, char *recordfile, int maxtime_sec, char *fmt, int *duration, int *sound_duration, int beep, int silencethreshold, int maxsilence_ms)
Record a file based on input frm a channel. Recording is performed in 'prepend' mode which works a li...
static int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu, int box)
static void adsi_folders(struct ast_channel *chan, int start, char *label)
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
#define EVENT_FLAG_REPORTING
static int messagecount(const char *context, const char *mailbox, const char *folder)
static int inboxcount(const char *mailbox, int *newmsgs, int *oldmsgs)
static void vm_change_password_shell(struct ast_vm_user *vmu, char *newpassword)
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
#define AST_RWLIST_INSERT_TAIL
static int vmsayname_exec(struct ast_channel *chan, const char *data)
static const char *const mailbox_folders[]
static char serveremail[80]
SQLHSTMT ast_odbc_prepare_and_execute(struct odbc_obj *obj, SQLHSTMT(*prepare_cb)(struct odbc_obj *obj, void *data), void *data)
Prepares, executes, and returns the resulting statement handle.
int ast_adsi_available(struct ast_channel *chan)
Returns non-zero if Channel does or might support ADSI.
#define VOICEMAIL_FILE_MODE
A ast_taskprocessor structure is a singleton by name.
static struct ast_cli_entry cli_voicemail[]
int ast_say_number(struct ast_channel *chan, int num, const char *ints, const char *lang, const char *options)
says a number
Standard Command Line Interface.
struct ast_event * ast_event_new(enum ast_event_type event_type,...)
Create a new event.
static int adsi_load_vmail(struct ast_channel *chan, int *useadsi)
struct ast_event_sub * ast_event_subscribe(enum ast_event_type event_type, ast_event_cb_t cb, const char *description, void *userdata,...)
Subscribe to events.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
#define ao2_container_alloc(arg1, arg2, arg3)
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
void * ast_taskprocessor_unreference(struct ast_taskprocessor *tps)
Unreference the specified taskprocessor and its reference count will decrement.
ast_app: A registered application
static int vm_allocate_dh(struct vm_state *vms, struct ast_vm_user *vmu, int count_msg)
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is "false"...
int ast_cli_register_multiple(struct ast_cli_entry *e, int len)
Register multiple commands.
SAY_EXTERN int(* ast_say_date_with_format)(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *timezone) SAY_INIT(ast_say_date_with_format)
#define AST_OPTION_RXGAIN
static void mwi_sub_destroy(struct mwi_sub *mwi_sub)
static char vm_prepend_timeout[80]
static int dialout(struct ast_channel *chan, struct ast_vm_user *vmu, char *num, char *outgoing_context)
#define ast_realloc(a, b)
int ast_waitstream(struct ast_channel *c, const char *breakon)
Waits for a stream to stop or digit to be pressed.
int ast_fileexists(const char *filename, const char *fmt, const char *preflang)
Checks for the existence of a given file.
static char vm_newpassword[80]
int ast_answer(struct ast_channel *chan)
Answer a channel.
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
void ast_smdi_mwi_message_destroy(struct ast_smdi_mwi_message *msg)
ast_smdi_mwi_message destructor.
static char pagerfromstring[100]
Data structure associated with a single frame of data.
#define AST_DATA_STRUCTURE(__struct, __name)
static void adsi_message(struct ast_channel *chan, struct vm_state *vms)
static struct ast_custom_function mailbox_exists_acf
static void mwi_sub_event_cb(const struct ast_event *event, void *userdata)
#define AST_TEST_DEFINE(hdr)
Unique ID Used by: AST_EVENT_SUB, AST_EVENT_UNSUB Payload type: UINT.
static int forward_message(struct ast_channel *chan, char *context, struct vm_state *vms, struct ast_vm_user *sender, char *fmt, int is_new_message, signed char record_gain, int urgent)
Sends a voicemail message to a mailbox recipient.
int ast_filerename(const char *oldname, const char *newname, const char *fmt)
Renames a file.
static int play_message_callerid(struct ast_channel *chan, struct vm_state *vms, char *cid, const char *context, int callback)
#define AST_APP_ARG(name)
Define an application argument.
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
static int vm_intro_multilang(struct ast_channel *chan, struct vm_state *vms, const char message_gender[])
struct ast_variable * next
int ast_adsi_input_control(unsigned char *buf, int page, int line, int display, int format, int just)
Set input information.
static char * complete_voicemail_show_users(const char *line, const char *word, int pos, int state)
static char cidinternalcontexts[MAX_NUM_CID_CONTEXTS][64]
#define ast_mutex_init(pmutex)
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
unsigned char valid
TRUE if the name information is valid/present.
static void read_password_from_file(const char *secretfn, char *password, int passwordlen)
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
void ast_category_append(struct ast_config *config, struct ast_category *cat)
static int vm_intro_gr(struct ast_channel *chan, struct vm_state *vms)
#define CONFIG_STATUS_FILEINVALID
int ast_smdi_mwi_unset(struct ast_smdi_interface *iface, const char *mailbox)
Unset the MWI indicator for a mailbox.
static char context[AST_MAX_CONTEXT]
int ast_readstring(struct ast_channel *c, char *s, int len, int timeout, int rtimeout, char *enders)
Reads multiple digits.
static int vm_intro_se(struct ast_channel *chan, struct vm_state *vms)
#define ast_mutex_destroy(a)
static char listen_control_stop_key[12]
int ast_adsi_unload_session(struct ast_channel *chan)
static int vm_intro_vi(struct ast_channel *chan, struct vm_state *vms)
const char * ast_event_get_ie_str(const struct ast_event *event, enum ast_event_ie_type ie_type)
Get the value of an information element that has a string payload.
#define AST_NONSTANDARD_APP_ARGS(args, parse, sep)
Performs the 'nonstandard' argument separation process for an application.
static void free_vm_users(void)
Free the users structure.
static int vm_tempgreeting(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain)
The handler for 'record a temporary greeting'.
static int close_mailbox(struct vm_state *vms, struct ast_vm_user *vmu)
struct ast_channel * ast_dummy_channel_alloc(void)
Create a fake channel structure.
void ast_odbc_release_obj(struct odbc_obj *obj)
Releases an ODBC object previously allocated by ast_odbc_request_obj()
static int passwordlocation
static char vm_invalid_password[80]
Say numbers and dates (maybe words one day too)
static int get_folder(struct ast_channel *chan, int start)
get_folder: Folder menu Plays "press 1 for INBOX messages" etc. Should possibly be internationalized ...
int ast_app_messagecount(const char *context, const char *mailbox, const char *folder)
Check number of messages in a given context, mailbox, and folder.
#define ASTERISK_GPL_KEY
The text the key() function should return.
struct ast_smdi_mwi_message * ast_smdi_mwi_message_wait_station(struct ast_smdi_interface *iface, int timeout, const char *station)
int ast_dsp_get_threshold_from_settings(enum threshold which)
Get silence threshold from dsp.conf.
static char * sayname_app
Asterisk module definitions.
const char * ast_config_AST_VAR_DIR
static void poll_subscribed_mailbox(struct mwi_sub *mwi_sub)
static int manager_list_voicemail_users(struct mansession *s, const struct message *m)
Manager list voicemail users command.
static int vm_intro_pl(struct ast_channel *chan, struct vm_state *vms)
static void delete_file(struct phoneprov_file *file)
static int vm_browse_messages(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
Top level method to invoke the language variant vm_browse_messages_XX function.
static snd_pcm_format_t format
static int vm_intro_he(struct ast_channel *chan, struct vm_state *vms)
static char callcontext[AST_MAX_CONTEXT]
struct ast_channel_tech * tech
struct ast_data * ast_data_add_int(struct ast_data *root, const char *childname, int value)
Add an integer node type.
struct ast_event_sub * ast_event_unsubscribe(struct ast_event_sub *event_sub)
Un-subscribe from events.
static struct ast_taskprocessor * mwi_subscription_tps
unsigned char valid
TRUE if the number information is valid/present.
#define ast_cond_timedwait(cond, mutex, time)
static int make_dir(char *dest, int len, const char *context, const char *ext, const char *folder)
Creates a file system path expression for a folder within the voicemail data folder and the appropria...
int ast_data_search_match(const struct ast_data_search *search, struct ast_data *data)
Check the current generated node to know if it matches the search condition.
#define ast_custom_function_register(acf)
Register a custom function.
static char listen_control_reverse_key[12]
#define AST_RWLIST_TRAVERSE_SAFE_END
const ast_string_field language
static int vm_browse_messages_latin(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
Common LATIN languages syntax for 'You have N messages' greeting.
uint32_t version
Structure version.
char exten[AST_MAX_EXTENSION]
static int vm_lock_path(const char *path)
Lock file path only return failure if ast_lock_path returns 'timeout', not if the path does not exist...
#define AST_MUTEX_DEFINE_STATIC(mutex)
int ast_stopstream(struct ast_channel *c)
Stops a stream.
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
static int reset_user_pw(const char *context, const char *mailbox, const char *newpass)
Resets a user password to a specified password.
struct ast_variable * ast_variable_new(const char *name, const char *value, const char *filename)
static int sendmail(char *srcemail, struct ast_vm_user *vmu, int msgnum, char *context, char *mailbox, const char *fromfolder, char *cidnum, char *cidname, char *attach, char *attach2, char *format, int duration, int attach_user_voicemail, struct ast_channel *chan, const char *category, const char *flag)
Structure for mutex and tracking information.
An SMDI message waiting indicator message.
static void make_email_file(FILE *p, char *srcemail, struct ast_vm_user *vmu, int msgnum, char *context, char *mailbox, const char *fromfolder, char *cidnum, char *cidname, char *attach, char *attach2, char *format, int duration, int attach_user_voicemail, struct ast_channel *chan, const char *category, int imap, const char *flag)
Creates the email file to be sent to indicate a new voicemail exists for a user.
static char mailbox[AST_MAX_EXTENSION]
static int ochar(struct baseio *bio, int c, FILE *so)
utility used by base_encode()
static int is_valid_dtmf(const char *key)
Determines if a DTMF key entered is valid.
The structure of the node handler.
static void apply_options_full(struct ast_vm_user *retval, struct ast_variable *var)
Loads the options specific to a voicemail user.
int ast_manager_unregister(char *action)
Unregister a registered manager command.
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
static int save_to_folder(struct ast_vm_user *vmu, struct vm_state *vms, int msg, int box)
struct ast_config * ast_load_realtime_multientry(const char *family,...) attribute_sentinel
Retrieve realtime configuration.
#define AST_APP_OPTION(option, flagno)
Declares an application option that does not accept an argument.
#define CONFIG_STATUS_FILEUNCHANGED
struct ao2_container * inprocess_container
#define ast_mutex_unlock(a)
static char prefix[MAX_PREFIX]
static int resequence_mailbox(struct ast_vm_user *vmu, char *dir, int stopcount)
int ast_mkdir(const char *path, int mode)
Recursively create directory path.
int ast_callerid_parse(char *instr, char **name, char **location)
Destructively parse inbuf into name and location (or number)
void ast_uninstall_vm_functions(void)
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
int ast_check_realtime(const char *family)
Check if realtime engine is configured for family.
struct ast_party_number number
Subscriber phone number.
static int vm_instructions_zh(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int skipadvanced, int in_urgent)
static int vm_browse_messages_vi(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
Vietnamese syntax for 'You have N messages' greeting.