71 #ifdef USE_SYSTEM_IMAP
72 #include <imap/c-client.h>
73 #include <imap/imap4r1.h>
74 #include <imap/linkage.h>
75 #elif defined (USE_SYSTEM_CCLIENT)
76 #include <c-client/c-client.h>
77 #include <c-client/imap4r1.h>
78 #include <c-client/linkage.h>
88 #include "asterisk/paths.h"
94 #if defined(__FreeBSD__) || defined(__OpenBSD__)
367 static char imapserver[48];
368 static char imapport[8];
369 static char imapflags[128];
370 static char imapfolder[64];
371 static char imapparentfolder[64] =
"\0";
372 static char greetingfolder[64];
373 static char authuser[32];
374 static char authpassword[42];
375 static int imapversion = 1;
377 static int expungeonhangup = 1;
378 static int imapgreetings = 0;
379 static char delimiter =
'\0';
387 static int init_mailstream(
struct vm_state *vms,
int box);
388 static void write_file(
char *filename,
char *buffer,
unsigned long len);
389 static char *get_header_by_tag(
char *header,
char *tag,
char *buf,
size_t len);
390 static void vm_imap_delete(
char *file,
int msgnum,
struct ast_vm_user *vmu);
391 static char *get_user_by_mailbox(
char *
mailbox,
char *buf,
size_t len);
392 static struct vm_state *get_vm_state_by_imapuser(
const char *
user,
int interactive);
393 static struct vm_state *get_vm_state_by_mailbox(
const char *
mailbox,
const char *
context,
int interactive);
395 static void vmstate_insert(
struct vm_state *vms);
396 static void vmstate_delete(
struct vm_state *vms);
397 static void set_update(MAILSTREAM * stream);
398 static void init_vm_state(
struct vm_state *vms);
399 static int save_body(BODY *body,
struct vm_state *vms,
char *section,
char *
format,
int is_intro);
400 static void get_mailbox_delimiter(MAILSTREAM *stream);
401 static void mm_parsequota (MAILSTREAM *stream,
unsigned char *msg, QUOTALIST *pquota);
402 static void imap_mailbox_name(
char *spec,
size_t len,
struct vm_state *vms,
int box,
int target);
403 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);
404 static void update_messages_by_imapuser(
const char *
user,
unsigned long number);
407 static int imap_remove_file (
char *dir,
int msgnum);
408 static int imap_retrieve_file (
const char *dir,
const int msgnum,
const char *
mailbox,
const char *
context);
409 static int imap_delete_old_greeting (
char *dir,
struct vm_state *vms);
421 #define SMDI_MWI_WAIT_TIMEOUT 1000
423 #define COMMAND_TIMEOUT 5000
425 #define VOICEMAIL_DIR_MODE 0777
426 #define VOICEMAIL_FILE_MODE 0666
427 #define CHUNKSIZE 65536
429 #define VOICEMAIL_CONFIG "voicemail.conf"
430 #define ASTERISK_USERNAME "asterisk"
435 #define DEFAULT_LISTEN_CONTROL_FORWARD_KEY "#"
436 #define DEFAULT_LISTEN_CONTROL_REVERSE_KEY "*"
437 #define DEFAULT_LISTEN_CONTROL_PAUSE_KEY "0"
438 #define DEFAULT_LISTEN_CONTROL_RESTART_KEY "2"
439 #define DEFAULT_LISTEN_CONTROL_STOP_KEY "13456789"
440 #define VALID_DTMF "1234567890*#"
444 #define SENDMAIL "/usr/sbin/sendmail -t"
446 #define INTRO "vm-intro"
449 #define MAXMSGLIMIT 9999
451 #define MINPASSWORD 0
453 #define BASELINELEN 72
454 #define BASEMAXINLINE 256
461 #define MAX_DATETIME_FORMAT 512
462 #define MAX_NUM_CID_CONTEXTS 10
464 #define VM_REVIEW (1 << 0)
465 #define VM_OPERATOR (1 << 1)
466 #define VM_SAYCID (1 << 2)
467 #define VM_SVMAIL (1 << 3)
468 #define VM_ENVELOPE (1 << 4)
469 #define VM_SAYDURATION (1 << 5)
470 #define VM_SKIPAFTERCMD (1 << 6)
471 #define VM_FORCENAME (1 << 7)
472 #define VM_FORCEGREET (1 << 8)
473 #define VM_PBXSKIP (1 << 9)
474 #define VM_DIRECFORWARD (1 << 10)
475 #define VM_ATTACH (1 << 11)
476 #define VM_DELETE (1 << 12)
477 #define VM_ALLOCED (1 << 13)
478 #define VM_SEARCH (1 << 14)
479 #define VM_TEMPGREETWARN (1 << 15)
480 #define VM_MOVEHEARD (1 << 16)
481 #define VM_MESSAGEWRAP (1 << 17)
482 #define VM_FWDURGAUTO (1 << 18)
483 #define ERROR_LOCK_PATH -100
484 #define OPERATOR_EXIT 300
535 #ifdef TEST_FRAMEWORK
660 char imappassword[80];
662 char imapvmshareid[80];
674 char msg_format[512];
677 #define VMSTATE_MAX_MSG_ARRAY 256
684 char curdir[PATH_MAX];
685 char vmbox[PATH_MAX];
702 unsigned msg_array_max;
703 MAILSTREAM *mailstream;
709 char introfn[PATH_MAX];
710 unsigned int quota_limit;
711 unsigned int quota_usage;
717 static char odbc_database[80];
718 static char odbc_table[80];
719 #define RETRIEVE(a,b,c,d) retrieve_file(a,b)
720 #define DISPOSE(a,b) remove_file(a,b)
721 #define STORE(a,b,c,d,e,f,g,h,i,j) store_file(a,b,c,d)
722 #define EXISTS(a,b,c,d) (message_exists(a,b))
723 #define RENAME(a,b,c,d,e,f,g,h) (rename_file(a,b,c,d,e,f))
724 #define COPY(a,b,c,d,e,f,g,h) (copy_file(a,b,c,d,e,f))
725 #define DELETE(a,b,c,d) (delete_file(a,b))
728 #define DISPOSE(a,b) (imap_remove_file(a,b))
729 #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))
730 #define RETRIEVE(a,b,c,d) imap_retrieve_file(a,b,c,d)
731 #define EXISTS(a,b,c,d) (ast_fileexists(c,NULL,d) > 0)
732 #define RENAME(a,b,c,d,e,f,g,h) (rename_file(g,h));
733 #define COPY(a,b,c,d,e,f,g,h) (copy_file(g,h));
734 #define DELETE(a,b,c,d) (vm_imap_delete(a,b,d))
736 #define RETRIEVE(a,b,c,d)
738 #define STORE(a,b,c,d,e,f,g,h,i,j)
739 #define EXISTS(a,b,c,d) (ast_fileexists(c,NULL,d) > 0)
740 #define RENAME(a,b,c,d,e,f,g,h) (rename_file(g,h));
741 #define COPY(a,b,c,d,e,f,g,h) (copy_plain_file(g,h));
742 #define DELETE(a,b,c,d) (vm_delete(c))
753 #define PWDCHANGE_INTERNAL (1 << 1)
754 #define PWDCHANGE_EXTERNAL (1 << 2)
758 #define tdesc "Comedian Mail (Voicemail System) with ODBC Storage"
761 # define tdesc "Comedian Mail (Voicemail System) with IMAP Storage"
763 # define tdesc "Comedian Mail (Voicemail System)"
772 static char *
app =
"VoiceMail";
775 static char *
app2 =
"VoiceMailMain";
777 static char *
app3 =
"MailboxExists";
778 static char *
app4 =
"VMAuthenticate";
811 #define DEFAULT_POLL_FREQ 30
896 static unsigned char adsifdn[4] =
"\x00\x00\x00\x0F";
897 static unsigned char adsisec[4] =
"\x9B\xDB\xF7\xAC";
907 char *fmt,
int outsidecaller,
struct ast_vm_user *vmu,
int *duration,
int *sound_duration,
const char *unlockdir,
908 signed char record_gain,
struct vm_state *vms,
char *flag);
912 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);
938 if (strcmp(i->
mailbox, j->mailbox)) {
946 struct inprocess *i, *arg =
ast_alloca(
sizeof(*arg) + strlen(context) + strlen(mailbox) + 2);
951 if ((i =
ao2_find(inprocess_container, arg, 0))) {
960 if (!(i =
ao2_alloc(
sizeof(*i) + strlen(context) + strlen(mailbox) + 2, NULL))) {
974 #if !(defined(ODBC_STORAGE) || defined(IMAP_STORAGE))
987 for (; *
input; input++) {
992 if (bufptr == buf + buflen - 1) {
1018 if (saydurationminfo) {
1035 if (maxdeletedmsg) {
1044 ast_copy_string(vmu->imapfolder, imapfolder,
sizeof(vmu->imapfolder));
1059 if (!strcasecmp(var,
"attach")) {
1061 }
else if (!strcasecmp(var,
"attachfmt")) {
1063 }
else if (!strcasecmp(var,
"serveremail")) {
1065 }
else if (!strcasecmp(var,
"emailbody")) {
1067 }
else if (!strcasecmp(var,
"emailsubject")) {
1069 }
else if (!strcasecmp(var,
"language")) {
1071 }
else if (!strcasecmp(var,
"tz")) {
1073 }
else if (!strcasecmp(var,
"locale")) {
1076 }
else if (!strcasecmp(var,
"imapuser")) {
1078 vmu->imapversion = imapversion;
1079 }
else if (!strcasecmp(var,
"imappassword") || !strcasecmp(var,
"imapsecret")) {
1081 vmu->imapversion = imapversion;
1082 }
else if (!strcasecmp(var,
"imapfolder")) {
1084 }
else if (!strcasecmp(var,
"imapvmshareid")) {
1085 ast_copy_string(vmu->imapvmshareid, value,
sizeof(vmu->imapvmshareid));
1086 vmu->imapversion = imapversion;
1088 }
else if (!strcasecmp(var,
"delete") || !strcasecmp(var,
"deletevoicemail")) {
1090 }
else if (!strcasecmp(var,
"saycid")){
1092 }
else if (!strcasecmp(var,
"sendvoicemail")){
1094 }
else if (!strcasecmp(var,
"review")){
1096 }
else if (!strcasecmp(var,
"tempgreetwarn")){
1098 }
else if (!strcasecmp(var,
"messagewrap")){
1100 }
else if (!strcasecmp(var,
"operator")) {
1102 }
else if (!strcasecmp(var,
"envelope")){
1104 }
else if (!strcasecmp(var,
"moveheard")){
1106 }
else if (!strcasecmp(var,
"sayduration")){
1108 }
else if (!strcasecmp(var,
"saydurationm")){
1109 if (sscanf(value,
"%30d", &x) == 1) {
1114 }
else if (!strcasecmp(var,
"forcename")){
1116 }
else if (!strcasecmp(var,
"forcegreetings")){
1118 }
else if (!strcasecmp(var,
"callback")) {
1120 }
else if (!strcasecmp(var,
"dialout")) {
1122 }
else if (!strcasecmp(var,
"exitcontext")) {
1124 }
else if (!strcasecmp(var,
"minsecs")) {
1125 if (sscanf(value,
"%30d", &x) == 1 && x >= 0) {
1128 ast_log(
LOG_WARNING,
"Invalid min message length of %s. Using global value %d\n", value, vmminsecs);
1131 }
else if (!strcasecmp(var,
"maxmessage") || !strcasecmp(var,
"maxsecs")) {
1139 if (!strcasecmp(var,
"maxmessage"))
1140 ast_log(
AST_LOG_WARNING,
"Option 'maxmessage' has been deprecated in favor of 'maxsecs'. Please make that change in your voicemail config.\n");
1141 }
else if (!strcasecmp(var,
"maxmsg")) {
1142 vmu->
maxmsg = atoi(value);
1151 }
else if (!strcasecmp(var,
"nextaftercmd")) {
1153 }
else if (!strcasecmp(var,
"backupdeleted")) {
1154 if (sscanf(value,
"%30d", &x) == 1)
1162 ast_log(
AST_LOG_WARNING,
"Invalid number of deleted messages saved per mailbox backupdeleted=%s. Using default value %d\n", value,
MAXMSG);
1168 }
else if (!strcasecmp(var,
"volgain")) {
1169 sscanf(value,
"%30lf", &vmu->
volgain);
1170 }
else if (!strcasecmp(var,
"passwordlocation")) {
1171 if (!strcasecmp(value,
"spooldir")) {
1176 }
else if (!strcasecmp(var,
"options")) {
1183 int fds[2], pid = 0;
1185 memset(buf, 0, len);
1188 snprintf(buf, len,
"FAILURE: Pipe failed: %s", strerror(
errno));
1197 snprintf(buf, len,
"FAILURE: Fork failed");
1201 if (read(fds[0], buf, len) < 0) {
1213 dup2(fds[1], STDOUT_FILENO);
1219 execv(arg.v[0], arg.v);
1220 printf(
"FAILURE: %s", strerror(
errno));
1237 if (strlen(password) < minpassword)
1243 char cmd[255], buf[255];
1247 snprintf(cmd,
sizeof(cmd),
"%s %s %s %s %s", ext_pass_check_cmd, vmu->
mailbox, vmu->
context, vmu->
password, password);
1250 if (!strncasecmp(buf,
"VALID", 5)) {
1251 ast_debug(3,
"Passed password check: '%s'\n", buf);
1253 }
else if (!strncasecmp(buf,
"FAILURE", 7)) {
1278 if (!strcmp(vmu->
password, password)) {
1283 if (strlen(password) > 10) {
1303 while ((s =
strsep(&stringp,
"|"))) {
1305 if ((var =
strsep(&value,
"=")) && value) {
1318 for (;
var; var = var->
next) {
1319 if (!strcasecmp(var->
name,
"vmsecret")) {
1321 }
else if (!strcasecmp(var->
name,
"secret") || !strcasecmp(var->
name,
"password")) {
1325 "\n\tmust be reset in voicemail.conf.\n", retval->
mailbox);
1330 }
else if (!strcasecmp(var->
name,
"uniqueid")) {
1332 }
else if (!strcasecmp(var->
name,
"pager")) {
1334 }
else if (!strcasecmp(var->
name,
"email")) {
1336 }
else if (!strcasecmp(var->
name,
"fullname")) {
1338 }
else if (!strcasecmp(var->
name,
"context")) {
1340 }
else if (!strcasecmp(var->
name,
"emailsubject")) {
1343 }
else if (!strcasecmp(var->
name,
"emailbody")) {
1347 }
else if (!strcasecmp(var->
name,
"imapuser")) {
1349 retval->imapversion = imapversion;
1350 }
else if (!strcasecmp(var->
name,
"imappassword") || !strcasecmp(var->
name,
"imapsecret")) {
1352 retval->imapversion = imapversion;
1353 }
else if (!strcasecmp(var->
name,
"imapfolder")) {
1355 }
else if (!strcasecmp(var->
name,
"imapvmshareid")) {
1357 retval->imapversion = imapversion;
1376 for (i = 0; i < strlen(key); ++i) {
1401 if ((retval = (ivm ? ivm :
ast_calloc(1,
sizeof(*retval))))) {
1403 memset(retval, 0,
sizeof(*retval));
1444 context =
"default";
1448 if (cur->imapversion != imapversion) {
1454 if (context && (!strcasecmp(context, cur->context)) && (!strcasecmp(mailbox, cur->mailbox)))
1459 if ((vmu = (ivm ? ivm :
ast_malloc(
sizeof(*vmu))))) {
1491 if ((!context || !strcasecmp(context, cur->
context)) &&
1492 (!strcasecmp(mailbox, cur->
mailbox)))
1523 char *category = NULL, *
value = NULL, *
new = NULL;
1524 const char *tmp = NULL;
1526 char secretfn[PATH_MAX] =
"";
1535 snprintf(secretfn,
sizeof(secretfn),
"%s%s/%s/secret.conf", VM_SPOOL_DIR, vmu->
context, vmu->
mailbox);
1538 ast_verb(4,
"Writing voicemail password to file %s succeeded\n", secretfn);
1543 ast_verb(4,
"Writing voicemail password to file %s failed, falling back to config file\n", secretfn);
1549 if (!strcasecmp(category, vmu->
context)) {
1554 value = strstr(tmp,
",");
1557 sprintf(
new,
"%s", newpassword);
1559 new =
ast_alloca((strlen(value) + strlen(newpassword) + 1));
1560 sprintf(
new,
"%s%s", newpassword, value);
1572 ast_test_suite_event_notify(
"PASSWORDCHANGED",
"Message: voicemail.conf updated with new password\r\nPasswordSource: voicemail.conf");
1589 ast_debug(4,
"users.conf: %s\n", category);
1590 if (!strcasecmp(category, vmu->
mailbox)) {
1592 ast_debug(3,
"looks like we need to make vmsecret!\n");
1598 sprintf(
new,
"%s", newpassword);
1600 ast_debug(4,
"failed to get category!\n");
1629 snprintf(buf,
sizeof(buf),
"%s %s %s %s", ext_pass_cmd, vmu->
context, vmu->
mailbox, newpassword);
1630 ast_debug(1,
"External password: %s\n",buf);
1654 return snprintf(dest, len,
"%s%s/%s/%s", VM_SPOOL_DIR, context, ext, folder);
1669 static int make_file(
char *dest,
const int len,
const char *dir,
const int num)
1671 return snprintf(dest, len,
"%s/msg%04d", dir, num);
1678 int pfd = mkstemp(
template);
1681 p = fdopen(pfd,
"w+");
1703 make_dir(dest, len, context, ext, folder);
1733 if (vmu &&
id == 0) {
1734 return vmu->imapfolder;
1737 return (
id >= 0 &&
id <
ARRAY_LEN(mailbox_folders)) ? mailbox_folders[
id] :
"Unknown";
1744 for (i = 0; i <
ARRAY_LEN(mailbox_folders); i++) {
1745 if (strcasecmp(name, mailbox_folders[i]) == 0) {
1769 int arraysize = (vmu->
maxmsg > count_msg ? vmu->
maxmsg : count_msg);
1782 if (arraysize > 0) {
1800 static void vm_imap_delete(
char *file,
int msgnum,
struct ast_vm_user *vmu)
1804 unsigned long messageNum;
1807 if (msgnum < 0 && !imapgreetings) {
1812 if (!(vms = get_vm_state_by_mailbox(vmu->
mailbox, vmu->
context, 1)) && !(vms = get_vm_state_by_mailbox(vmu->
mailbox, vmu->
context, 0))) {
1813 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);
1818 imap_delete_old_greeting(file, vms);
1824 messageNum = vms->msgArray[msgnum];
1825 if (messageNum == 0) {
1826 ast_log(
LOG_WARNING,
"msgnum %d, mailbox message %lu is zero.\n", msgnum, messageNum);
1830 ast_log(
LOG_DEBUG,
"deleting msgnum %d, which is mailbox message %lu\n", msgnum, messageNum);
1832 snprintf (arg,
sizeof(arg),
"%lu", messageNum);
1834 mail_setflag (vms->mailstream, arg,
"\\DELETED");
1835 mail_expunge(vms->mailstream);
1839 static int imap_retrieve_greeting(
const char *dir,
const int msgnum,
struct ast_vm_user *vmu)
1842 char *file, *filename;
1850 if (msgnum > -1 || !imapgreetings) {
1857 ast_debug (1,
"Failed to procure file name from directory passed.\n");
1863 if (!(vms_p = get_vm_state_by_mailbox(vmu->
mailbox, vmu->
context, 1)) &&
1864 !(vms_p = get_vm_state_by_mailbox(vmu->
mailbox, vmu->
context, 0))) {
1869 if (!(vms_p = create_vm_state_from_user(vmu))) {
1876 *vms_p->introfn =
'\0';
1880 if (!vms_p->mailstream) {
1887 for (i = 0; i < vms_p->mailstream->nmsgs; i++) {
1888 mail_fetchstructure(vms_p->mailstream, i + 1, &body);
1890 if (body->nested.part && body->nested.part->next && body->nested.part->next->body.parameter->value) {
1891 attachment =
ast_strdupa(body->nested.part->next->body.parameter->value);
1897 filename =
strsep(&attachment,
".");
1898 if (!strcmp(filename, file)) {
1900 vms_p->msgArray[vms_p->
curmsg] = i + 1;
1901 save_body(body, vms_p,
"2", attachment, 0);
1911 static int imap_retrieve_file(
const char *dir,
const int msgnum,
const char *
mailbox,
const char *
context)
1914 char *header_content;
1915 char *attachedfilefmt;
1918 char text_file[PATH_MAX];
1919 FILE *text_file_ptr;
1923 if (!(vmu =
find_user(NULL, context, mailbox))) {
1929 if (imapgreetings) {
1930 res = imap_retrieve_greeting(dir, msgnum, vmu);
1941 if (!(vms = get_vm_state_by_mailbox(vmu->
mailbox, vmu->
context, 1)) && !(vms = get_vm_state_by_mailbox(vmu->
mailbox, vmu->
context, 0))) {
1955 snprintf(vms->introfn,
sizeof(vms->introfn),
"%sintro", vms->
fn);
1964 ast_log(
LOG_DEBUG,
"Before mail_fetchheaders, curmsg is: %d, imap messages is %lu\n", msgnum, vms->msgArray[msgnum]);
1965 if (vms->msgArray[msgnum] == 0) {
1973 header_content = mail_fetchheader (vms->mailstream, vms->msgArray[msgnum]);
1977 ast_log(
LOG_ERROR,
"Could not fetch header for message number %ld\n", vms->msgArray[msgnum]);
1983 mail_fetchstructure(vms->mailstream, vms->msgArray[msgnum], &body);
1987 if (body->nested.part && body->nested.part->next && body->nested.part->next->body.parameter->value) {
1988 attachedfilefmt =
ast_strdupa(body->nested.part->next->body.parameter->value);
1997 strsep(&attachedfilefmt,
".");
1998 if (!attachedfilefmt) {
1999 ast_log(
LOG_ERROR,
"File format could not be obtained from IMAP message attachment\n");
2004 save_body(body, vms,
"2", attachedfilefmt, 0);
2005 if (save_body(body, vms,
"3", attachedfilefmt, 1)) {
2006 *vms->introfn =
'\0';
2010 snprintf(text_file,
sizeof(text_file),
"%s.%s", vms->
fn,
"txt");
2012 if (!(text_file_ptr = fopen(text_file,
"w"))) {
2016 fprintf(text_file_ptr,
"%s\n",
"[message]");
2018 get_header_by_tag(header_content,
"X-Asterisk-VM-Caller-ID-Name:", buf,
sizeof(buf));
2019 fprintf(text_file_ptr,
"callerid=\"%s\" ",
S_OR(buf,
""));
2020 get_header_by_tag(header_content,
"X-Asterisk-VM-Caller-ID-Num:", buf,
sizeof(buf));
2021 fprintf(text_file_ptr,
"<%s>\n",
S_OR(buf,
""));
2022 get_header_by_tag(header_content,
"X-Asterisk-VM-Context:", buf,
sizeof(buf));
2023 fprintf(text_file_ptr,
"context=%s\n",
S_OR(buf,
""));
2024 get_header_by_tag(header_content,
"X-Asterisk-VM-Orig-time:", buf,
sizeof(buf));
2025 fprintf(text_file_ptr,
"origtime=%s\n",
S_OR(buf,
""));
2026 get_header_by_tag(header_content,
"X-Asterisk-VM-Duration:", buf,
sizeof(buf));
2027 fprintf(text_file_ptr,
"duration=%s\n",
S_OR(buf,
""));
2028 get_header_by_tag(header_content,
"X-Asterisk-VM-Category:", buf,
sizeof(buf));
2029 fprintf(text_file_ptr,
"category=%s\n",
S_OR(buf,
""));
2030 get_header_by_tag(header_content,
"X-Asterisk-VM-Flag:", buf,
sizeof(buf));
2031 fprintf(text_file_ptr,
"flag=%s\n",
S_OR(buf,
""));
2032 fclose(text_file_ptr);
2039 static int folder_int(
const char *folder)
2045 if (!strcasecmp(folder, imapfolder)) {
2047 }
else if (!strcasecmp(folder,
"Old")) {
2049 }
else if (!strcasecmp(folder,
"Work")) {
2051 }
else if (!strcasecmp(folder,
"Family")) {
2053 }
else if (!strcasecmp(folder,
"Friends")) {
2055 }
else if (!strcasecmp(folder,
"Cust1")) {
2057 }
else if (!strcasecmp(folder,
"Cust2")) {
2059 }
else if (!strcasecmp(folder,
"Cust3")) {
2061 }
else if (!strcasecmp(folder,
"Cust4")) {
2063 }
else if (!strcasecmp(folder,
"Cust5")) {
2065 }
else if (!strcasecmp(folder,
"Urgent")) {
2072 static int __messagecount(
const char *context,
const char *mailbox,
const char *folder)
2080 int fold = folder_int(folder);
2093 vmu =
find_user(&vmus, context, mailbox);
2099 if (vmu->imapuser[0] ==
'\0') {
2106 if (vmu->imapuser[0] ==
'\0') {
2114 vms_p = get_vm_state_by_imapuser(vmu->imapuser, 1);
2116 vms_p = get_vm_state_by_mailbox(mailbox, context, 1);
2119 ast_debug(3,
"Returning before search - user is logged in\n");
2129 vms_p = get_vm_state_by_imapuser(vmu->imapuser, 0);
2131 vms_p = get_vm_state_by_mailbox(mailbox, context, 0);
2135 vms_p = create_vm_state_from_user(vmu);
2137 ret = init_mailstream(vms_p, fold);
2138 if (!vms_p->mailstream) {
2144 pgm = mail_newsearchpgm ();
2145 hdr = mail_newsearchheader (
"X-Asterisk-VM-Extension", (
char *)(!
ast_strlen_zero(vmu->imapvmshareid) ? vmu->imapvmshareid : mailbox));
2146 hdr->next = mail_newsearchheader(
"X-Asterisk-VM-Context", (
char *)
S_OR(context,
"default"));
2172 vms_p->vmArrayIndex = 0;
2173 mail_search_full (vms_p->mailstream, NULL, pgm, NIL);
2174 if (fold == 0 && urgent == 0)
2178 if (fold == 0 && urgent == 1)
2181 mail_free_searchpgm(&pgm);
2184 return vms_p->vmArrayIndex;
2187 mail_ping(vms_p->mailstream);
2196 check_quota(vms, vmu->imapfolder);
2197 if (vms->quota_limit && vms->quota_usage >= vms->quota_limit) {
2198 ast_debug(1,
"*** QUOTA EXCEEDED!! %u >= %u\n", vms->quota_usage, vms->quota_limit);
2206 ast_log(
LOG_WARNING,
"Unable to leave message since we will exceed the maximum number of messages allowed (%u >= %u)\n", msgnum, vmu->
maxmsg);
2224 static int messagecount(
const char *context,
const char *mailbox,
const char *folder)
2227 return __messagecount(context, mailbox,
"INBOX") + __messagecount(context, mailbox,
"Urgent");
2229 return __messagecount(context, mailbox, folder);
2233 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)
2237 char introfn[PATH_MAX];
2241 char tmp[80] =
"/tmp/astmail-XXXXXX";
2247 char *imap_flags = NIL;
2253 if(!imapgreetings) {
2260 if (imap_check_limits(chan, vms, vmu, msgcount)) {
2266 ast_debug(3,
"Setting message flag \\\\FLAGGED.\n");
2267 imap_flags =
"\\FLAGGED";
2283 snprintf(introfn,
sizeof(introfn),
"%sintro", fn);
2298 if (!strcmp(fmt,
"wav49"))
2300 ast_debug(3,
"Storing file '%s', format '%s'\n", fn, fmt);
2307 *(vmu->
email) =
'\0';
2311 if (msgnum < 0 && imapgreetings) {
2316 imap_delete_old_greeting(fn, vms);
2322 fn, introfn, fmt, duration, 1, chan, NULL, 1, flag);
2330 *(vmu->
email) =
'\0';
2333 if (fread(buf, len, 1, p) <
len) {
2339 ((
char *) buf)[
len] =
'\0';
2340 INIT(&str, mail_string, buf, len);
2341 ret = init_mailstream(vms, box);
2343 imap_mailbox_name(mailbox,
sizeof(mailbox), vms, box, 1);
2345 if(!mail_append_full(vms->mailstream, mailbox, imap_flags, NIL, &str))
2361 *(vmu->
email) =
'\0';
2380 static int inboxcount2(
const char *mailbox_context,
int *urgentmsgs,
int *newmsgs,
int *oldmsgs)
2382 char tmp[PATH_MAX] =
"";
2394 ast_debug(3,
"Mailbox is set to %s\n", mailbox_context);
2400 context = strchr(tmp,
'@');
2401 if (strchr(mailbox_context,
',')) {
2402 int tmpnew, tmpold, tmpurgent;
2405 while ((cur =
strsep(&mb,
", "))) {
2407 if (
inboxcount2(cur, urgentmsgs ? &tmpurgent : NULL, newmsgs ? &tmpnew : NULL, oldmsgs ? &tmpold : NULL))
2415 *urgentmsgs += tmpurgent;
2426 context =
"default";
2427 mailboxnc = (
char *) mailbox_context;
2436 if ((*newmsgs = __messagecount(context, mailboxnc, vmu->imapfolder)) < 0) {
2443 if ((*oldmsgs = __messagecount(context, mailboxnc,
"Old")) < 0) {
2448 if ((*urgentmsgs = __messagecount(context, mailboxnc,
"Urgent")) < 0) {
2465 static int has_voicemail(
const char *mailbox,
const char *folder)
2467 char tmp[256], *tmp2, *box, *
context;
2470 if (strchr(tmp2,
',') || strchr(tmp2,
'&')) {
2471 while ((box =
strsep(&tmp2,
",&"))) {
2479 if ((context = strchr(tmp,
'@'))) {
2482 context =
"default";
2484 return __messagecount(context, tmp, folder) ? 1 : 0;
2504 struct vm_state *sendvms = NULL, *destvms = NULL;
2505 char messagestring[10];
2506 if (msgnum >= recip->
maxmsg) {
2510 if (!(sendvms = get_vm_state_by_imapuser(vmu->imapuser, 0))) {
2514 if (!(destvms = get_vm_state_by_imapuser(recip->imapuser, 0))) {
2518 snprintf(messagestring,
sizeof(messagestring),
"%ld", sendvms->msgArray[msgnum]);
2520 if ((mail_copy(sendvms->mailstream, messagestring, (
char *)
mbox(vmu, imbox)) == T)) {
2529 static void imap_mailbox_name(
char *spec,
size_t len,
struct vm_state *vms,
int box,
int use_folder)
2531 char tmp[256], *t = tmp;
2532 size_t left =
sizeof(tmp);
2543 snprintf(vms->
vmbox,
sizeof(vms->
vmbox),
"vm-%s",
mbox(NULL, box));
2564 snprintf(spec, len,
"%s%s", tmp, use_folder? vms->imapfolder:
"INBOX");
2566 snprintf(spec, len,
"%s%s", tmp, greetingfolder);
2570 snprintf(spec, len,
"%s%s%c%s", tmp, imapparentfolder, delimiter,
mbox(NULL, box));
2572 snprintf(spec, len,
"%s%s", tmp,
mbox(NULL, box));
2577 static int init_mailstream(
struct vm_state *vms,
int box)
2579 MAILSTREAM *stream = NIL;
2589 if (vms->mailstream == NIL || !vms->mailstream) {
2593 stream = vms->mailstream;
2598 if (delimiter ==
'\0') {
2600 #ifdef USE_SYSTEM_IMAP
2601 #include <imap/linkage.c>
2602 #elif defined(USE_SYSTEM_CCLIENT)
2603 #include <c-client/linkage.c>
2605 #include "linkage.c"
2608 imap_mailbox_name(tmp,
sizeof(tmp), vms, 0, 1);
2610 stream = mail_open (stream, tmp, debug ? OP_DEBUG : NIL);
2612 if (stream == NIL) {
2616 get_mailbox_delimiter(stream);
2618 for (cp = vms->imapfolder; *cp; cp++)
2623 imap_mailbox_name(tmp,
sizeof(tmp), vms, box, 1);
2627 vms->mailstream = mail_open (stream, tmp, debug ? OP_DEBUG : NIL);
2629 if (vms->mailstream == NIL) {
2640 int ret, urgent = 0;
2649 ast_copy_string(vms->imapfolder, vmu->imapfolder,
sizeof(vms->imapfolder));
2650 vms->imapversion = vmu->imapversion;
2651 ast_debug(3,
"Before init_mailstream, user is %s\n", vmu->imapuser);
2653 if ((ret = init_mailstream(vms, box)) || !vms->mailstream) {
2662 ast_debug(3,
"Mailbox name set to: %s, about to check quotas\n",
mbox(vmu, box));
2663 check_quota(vms, (
char *)
mbox(vmu, box));
2667 pgm = mail_newsearchpgm();
2670 hdr = mail_newsearchheader(
"X-Asterisk-VM-Extension", (!
ast_strlen_zero(vmu->imapvmshareid) ? vmu->imapvmshareid : vmu->
mailbox));
2671 hdr->next = mail_newsearchheader(
"X-Asterisk-VM-Context", vmu->
context);
2682 }
else if (box ==
NEW_FOLDER && urgent == 0) {
2692 ast_debug(3,
"Before mail_search_full, user is %s\n", vmu->imapuser);
2694 vms->vmArrayIndex = 0;
2695 mail_search_full (vms->mailstream, NULL, pgm, NIL);
2696 vms->
lastmsg = vms->vmArrayIndex - 1;
2697 mail_free_searchpgm(&pgm);
2703 ast_log(
LOG_WARNING,
"The code expects the old messages to be checked first, fix the code.\n");
2714 static void write_file(
char *filename,
char *buffer,
unsigned long len)
2718 output = fopen (filename,
"w");
2719 if (fwrite(buffer, len, 1, output) != 1) {
2720 if (ferror(output)) {
2727 static void update_messages_by_imapuser(
const char *
user,
unsigned long number)
2729 struct vm_state *vms = get_vm_state_by_imapuser(user, 1);
2731 if (!vms && !(vms = get_vm_state_by_imapuser(user, 0))) {
2735 ast_debug(3,
"saving mailbox message number %lu as message %d. Interactive set to %d\n", number, vms->vmArrayIndex, vms->interactive);
2738 if (vms->vmArrayIndex >= vms->msg_array_max) {
2739 long *new_mem =
ast_realloc(vms->msgArray, 2 * vms->msg_array_max *
sizeof(
long));
2743 vms->msgArray = new_mem;
2744 vms->msg_array_max *= 2;
2747 vms->msgArray[vms->vmArrayIndex++] = number;
2750 void mm_searched(MAILSTREAM *stream,
unsigned long number)
2752 char *mailbox = stream->mailbox, buf[1024] =
"", *
user;
2754 if (!(user = get_user_by_mailbox(mailbox, buf,
sizeof(buf))))
2757 update_messages_by_imapuser(user, number);
2760 static struct ast_vm_user *find_user_realtime_imapuser(
const char *imapuser)
2785 void mm_exists(MAILSTREAM * stream,
unsigned long number)
2788 ast_debug(4,
"Entering EXISTS callback for message %ld\n", number);
2789 if (number == 0)
return;
2794 void mm_expunged(MAILSTREAM * stream,
unsigned long number)
2797 ast_debug(4,
"Entering EXPUNGE callback for message %ld\n", number);
2798 if (number == 0)
return;
2803 void mm_flags(MAILSTREAM * stream,
unsigned long number)
2806 ast_debug(4,
"Entering FLAGS callback for message %ld\n", number);
2807 if (number == 0)
return;
2812 void mm_notify(MAILSTREAM * stream,
char *
string,
long errflg)
2814 ast_debug(5,
"Entering NOTIFY callback, errflag is %ld, string is %s\n", errflg,
string);
2815 mm_log (
string, errflg);
2819 void mm_list(MAILSTREAM * stream,
int delim,
char *mailbox,
long attributes)
2821 if (delimiter ==
'\0') {
2825 ast_debug(5,
"Delimiter set to %c and mailbox %s\n", delim, mailbox);
2826 if (attributes & LATT_NOINFERIORS)
2828 if (attributes & LATT_NOSELECT)
2830 if (attributes & LATT_MARKED)
2832 if (attributes & LATT_UNMARKED)
2837 void mm_lsub(MAILSTREAM * stream,
int delim,
char *mailbox,
long attributes)
2839 ast_debug(5,
"Delimiter set to %c and mailbox %s\n", delim, mailbox);
2840 if (attributes & LATT_NOINFERIORS)
2842 if (attributes & LATT_NOSELECT)
2844 if (attributes & LATT_MARKED)
2846 if (attributes & LATT_UNMARKED)
2851 void mm_status(MAILSTREAM * stream,
char *mailbox, MAILSTATUS *
status)
2854 if (status->flags & SA_MESSAGES)
2856 if (status->flags & SA_RECENT)
2858 if (status->flags & SA_UNSEEN)
2860 if (status->flags & SA_UIDVALIDITY)
2862 if (status->flags & SA_UIDNEXT)
2868 void mm_log(
char *
string,
long errflg)
2870 switch ((
short) errflg) {
2872 ast_debug(1,
"IMAP Info: %s\n",
string);
2885 void mm_dlog(
char *
string)
2891 void mm_login(NETMBX * mb,
char *user,
char *pwd,
long trial)
2895 ast_debug(4,
"Entering callback mm_login\n");
2904 if (!strcasecmp(mb->user, vmu->imapuser)) {
2910 if ((vmu = find_user_realtime_imapuser(mb->user))) {
2919 void mm_critical(MAILSTREAM * stream)
2924 void mm_nocritical(MAILSTREAM * stream)
2929 long mm_diskerror(MAILSTREAM * stream,
long errcode,
long serious)
2931 kill (getpid (), SIGSTOP);
2936 void mm_fatal(
char *
string)
2942 static void mm_parsequota(MAILSTREAM *stream,
unsigned char *msg, QUOTALIST *pquota)
2945 char *mailbox = stream->mailbox, *
user;
2946 char buf[1024] =
"";
2947 unsigned long usage = 0, limit = 0;
2950 usage = pquota->usage;
2951 limit = pquota->limit;
2952 pquota = pquota->next;
2955 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)))) {
2960 ast_debug(3,
"User %s usage is %lu, limit is %lu\n", user, usage, limit);
2962 vms->quota_usage = usage;
2963 vms->quota_limit = limit;
2966 static char *get_header_by_tag(
char *header,
char *tag,
char *buf,
size_t len)
2968 char *start, *eol_pnt;
2974 taglen = strlen(tag) + 1;
2978 if (!(start = strstr(header, tag)))
2982 memset(buf, 0, len);
2985 if ((eol_pnt = strchr(buf,
'\r')) || (eol_pnt = strchr(buf,
'\n')))
2990 static char *get_user_by_mailbox(
char *mailbox,
char *buf,
size_t len)
2992 char *start, *
quote, *eol_pnt;
2997 if (!(start = strstr(mailbox,
"/user=")))
3002 if (!(quote = strchr(buf,
'\"'))) {
3003 if (!(eol_pnt = strchr(buf,
'/')))
3004 eol_pnt = strchr(buf,
'}');
3008 eol_pnt = strchr(buf+1,
'\"');
3018 pthread_once(&ts_vmstate.once, ts_vmstate.key_init);
3019 if ((vms_p = pthread_getspecific(ts_vmstate.key)) && !strcmp(vms_p->imapuser, vmu->imapuser) && !strcmp(vms_p->
username, vmu->
mailbox)) {
3025 if (!(vms_p =
ast_calloc(1,
sizeof(*vms_p))))
3027 ast_copy_string(vms_p->imapuser, vmu->imapuser,
sizeof(vms_p->imapuser));
3028 ast_copy_string(vms_p->imapfolder, vmu->imapfolder,
sizeof(vms_p->imapfolder));
3031 vms_p->mailstream = NIL;
3032 vms_p->imapversion = vmu->imapversion;
3038 init_vm_state(vms_p);
3039 vmstate_insert(vms_p);
3043 static struct vm_state *get_vm_state_by_imapuser(
const char *user,
int interactive)
3045 struct vmstate *vlist = NULL;
3049 pthread_once(&ts_vmstate.once, ts_vmstate.key_init);
3050 vms = pthread_getspecific(ts_vmstate.key);
3057 ast_debug(3,
"error: vms is NULL for %s\n", user);
3060 if (vlist->vms->imapversion != imapversion) {
3063 if (!vlist->vms->imapuser) {
3064 ast_debug(3,
"error: imapuser is NULL for %s\n", user);
3068 if (!strcmp(vlist->vms->imapuser, user) && (interactive == 2 || vlist->vms->interactive == interactive)) {
3075 ast_debug(3,
"%s not found in vmstates\n", user);
3080 static struct vm_state *get_vm_state_by_mailbox(
const char *mailbox,
const char *context,
int interactive)
3083 struct vmstate *vlist = NULL;
3084 const char *local_context =
S_OR(context,
"default");
3088 pthread_once(&ts_vmstate.once, ts_vmstate.key_init);
3089 vms = pthread_getspecific(ts_vmstate.key);
3096 ast_debug(3,
"error: vms is NULL for %s\n", mailbox);
3099 if (vlist->vms->imapversion != imapversion) {
3102 if (!vlist->vms->username || !vlist->vms->context) {
3103 ast_debug(3,
"error: username is NULL for %s\n", mailbox);
3107 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);
3109 if (!strcmp(vlist->vms->username, mailbox) && !strcmp(vlist->vms->context, local_context) && vlist->vms->interactive == interactive) {
3117 ast_debug(3,
"%s not found in vmstates\n", mailbox);
3122 static void vmstate_insert(
struct vm_state *vms)
3130 if (vms->interactive == 1) {
3136 vms->vmArrayIndex = altvms->vmArrayIndex;
3141 vms->persist_vms = altvms;
3143 #ifdef REALLY_FAST_EVEN_IF_IT_MEANS_RESOURCE_LEAKS
3144 vms->mailstream = altvms->mailstream;
3146 vms->mailstream = NIL;
3157 ast_debug(3,
"Inserting vm_state for user:%s, mailbox %s\n", vms->imapuser, vms->
username);
3164 static void vmstate_delete(
struct vm_state *vms)
3166 struct vmstate *vc = NULL;
3171 if (vms->interactive == 1 && (altvms = vms->persist_vms)) {
3175 altvms->updated = 1;
3176 vms->mailstream = mail_close(vms->mailstream);
3182 ast_debug(3,
"Removing vm_state for user:%s, mailbox %s\n", vms->imapuser, vms->
username);
3186 if (vc->vms == vms) {
3197 vc->vms->msgArray = NULL;
3198 vc->vms->msg_array_max = 0;
3206 static void set_update(MAILSTREAM * stream)
3209 char *mailbox = stream->mailbox, *
user;
3210 char buf[1024] =
"";
3212 if (!(user = get_user_by_mailbox(mailbox, buf,
sizeof(buf))) || !(vms = get_vm_state_by_imapuser(user, 0))) {
3218 ast_debug(3,
"User %s mailbox set for update.\n", user);
3223 static void init_vm_state(
struct vm_state *vms)
3226 vms->msgArray =
ast_calloc(vms->msg_array_max,
sizeof(
long));
3227 if (!vms->msgArray) {
3229 vms->msg_array_max = 0;
3231 vms->vmArrayIndex = 0;
3235 static int save_body(BODY *body,
struct vm_state *vms,
char *section,
char *
format,
int is_intro)
3239 char *fn = is_intro ? vms->introfn : vms->
fn;
3241 unsigned long newlen;
3244 if (!body || body == NIL)
3248 body_content = mail_fetchbody(vms->mailstream, vms->msgArray[vms->
curmsg], section, &len);
3250 if (body_content != NIL) {
3251 snprintf(filename,
sizeof(filename),
"%s.%s", fn, format);
3253 body_decoded = rfc822_base64((
unsigned char *) body_content, len, &newlen);
3258 write_file(filename, (
char *) body_decoded, newlen);
3260 ast_debug(5,
"Body of message is NULL.\n");
3273 static void get_mailbox_delimiter(MAILSTREAM *stream) {
3275 snprintf(tmp,
sizeof(tmp),
"{%s}", imapserver);
3276 mail_list(stream, tmp,
"*");
3286 static void check_quota(
struct vm_state *vms,
char *mailbox) {
3288 mail_parameters(NULL, SET_QUOTA, (
void *) mm_parsequota);
3289 ast_debug(3,
"Mailbox name set to: %s, about to check quotas\n", mailbox);
3290 if (vms && vms->mailstream != NULL) {
3291 imap_getquotaroot(vms->mailstream, mailbox);
3316 struct generic_prepare_struct {
3324 struct generic_prepare_struct *gps = data;
3328 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->
con, &stmt);
3329 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
3333 res = SQLPrepare(stmt, (
unsigned char *) gps->sql, SQL_NTS);
3334 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
3336 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
3339 for (i = 0; i < gps->argc; i++)
3340 SQLBindParameter(stmt, i + 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(gps->argv[i]), 0, gps->argv[i], 0, NULL);
3359 static int retrieve_file(
char *dir,
int msgnum)
3365 void *fdm = MAP_FAILED;
3366 SQLSMALLINT colcount = 0;
3373 SQLSMALLINT datatype;
3374 SQLSMALLINT decimaldigits;
3375 SQLSMALLINT nullable;
3381 char full_fn[PATH_MAX];
3383 char *argv[] = { dir, msgnums };
3384 struct generic_prepare_struct gps = { .sql = sql, .argc = 2, .argv = argv };
3390 c = strchr(fmt,
'|');
3393 if (!strcasecmp(fmt,
"wav49"))
3395 snprintf(msgnums,
sizeof(msgnums),
"%d", msgnum);
3402 snprintf(full_fn,
sizeof(full_fn),
"%s.txt", fn);
3404 if (!(f = fopen(full_fn,
"w+"))) {
3409 snprintf(full_fn,
sizeof(full_fn),
"%s.%s", fn, fmt);
3410 snprintf(sql,
sizeof(sql),
"SELECT * FROM %s WHERE dir=? AND msgnum=?", odbc_table);
3417 res = SQLFetch(stmt);
3418 if (res == SQL_NO_DATA) {
3419 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
3422 }
else if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
3424 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
3431 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
3435 res = SQLNumResultCols(stmt, &colcount);
3436 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
3438 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
3443 fprintf(f,
"[message]\n");
3444 for (x = 0; x < colcount; x++) {
3447 collen =
sizeof(coltitle);
3448 res = SQLDescribeCol(stmt, x + 1, (
unsigned char *) coltitle,
sizeof(coltitle), &collen,
3449 &datatype, &colsize, &decimaldigits, &nullable);
3450 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
3452 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
3456 if (!strcasecmp(coltitle,
"recording")) {
3458 res = SQLGetData(stmt, x + 1, SQL_BINARY, rowdata, 0, &colsize2);
3462 lseek(fd, fdlen - 1, SEEK_SET);
3463 if (write(fd, tmp, 1) != 1) {
3469 for (offset = 0; offset < colsize2; offset +=
CHUNKSIZE) {
3470 if ((fdm = mmap(NULL,
CHUNKSIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset)) == MAP_FAILED) {
3472 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
3476 res = SQLGetData(stmt, x + 1, SQL_BINARY, fdm,
CHUNKSIZE, NULL);
3478 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
3481 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
3487 if (truncate(full_fn, fdlen) < 0) {
3492 res = SQLGetData(stmt, x + 1, SQL_CHAR, rowdata,
sizeof(rowdata), NULL);
3493 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
3495 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
3499 if (strcasecmp(coltitle,
"msgnum") && strcasecmp(coltitle,
"dir") && f)
3500 fprintf(f,
"%s=%s\n", coltitle, rowdata);
3503 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
3533 char *argv[] = { dir };
3534 struct generic_prepare_struct gps = { .sql = sql, .argc = 1, .argv = argv };
3539 snprintf(sql,
sizeof(sql),
"SELECT msgnum FROM %s WHERE dir=? order by msgnum desc", odbc_table);
3547 res = SQLFetch(stmt);
3548 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
3549 if (res == SQL_NO_DATA) {
3550 ast_log(
AST_LOG_DEBUG,
"Directory '%s' has no messages and therefore no index was retrieved.\n", dir);
3555 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
3559 res = SQLGetData(stmt, 1, SQL_CHAR, rowdata,
sizeof(rowdata), NULL);
3560 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
3562 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
3566 if (sscanf(rowdata,
"%30d", &x) != 1)
3568 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
3586 static int message_exists(
char *dir,
int msgnum)
3594 char *argv[] = { dir, msgnums };
3595 struct generic_prepare_struct gps = { .sql = sql, .argc = 2, .argv = argv };
3600 snprintf(msgnums,
sizeof(msgnums),
"%d", msgnum);
3601 snprintf(sql,
sizeof(sql),
"SELECT COUNT(*) FROM %s WHERE dir=? AND msgnum=?", odbc_table);
3608 res = SQLFetch(stmt);
3609 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
3611 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
3615 res = SQLGetData(stmt, 1, SQL_CHAR, rowdata,
sizeof(rowdata), NULL);
3616 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
3618 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
3622 if (sscanf(rowdata,
"%30d", &x) != 1)
3624 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
3648 char *argv[] = { dir };
3649 struct generic_prepare_struct gps = { .sql = sql, .argc = 1, .argv = argv };
3654 snprintf(sql,
sizeof(sql),
"SELECT COUNT(*) FROM %s WHERE dir=?", odbc_table);
3661 res = SQLFetch(stmt);
3662 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
3664 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
3668 res = SQLGetData(stmt, 1, SQL_CHAR, rowdata,
sizeof(rowdata), NULL);
3669 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
3671 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
3675 if (sscanf(rowdata,
"%30d", &x) != 1)
3677 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
3697 static void delete_file(
const char *sdir,
int smsg)
3702 char *argv[] = { NULL, msgnums };
3703 struct generic_prepare_struct gps = { .sql = sql, .argc = 2, .argv = argv };
3710 snprintf(msgnums,
sizeof(msgnums),
"%d", smsg);
3711 snprintf(sql,
sizeof(sql),
"DELETE FROM %s WHERE dir=? AND msgnum=?", odbc_table);
3716 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
3734 static void copy_file(
char *sdir,
int smsg,
char *ddir,
int dmsg,
char *dmailboxuser,
char *dmailboxcontext)
3741 char *argv[] = { ddir, msgnumd, dmailboxuser, dmailboxcontext, sdir, msgnums };
3742 struct generic_prepare_struct gps = { .sql = sql, .argc = 6, .argv = argv };
3747 snprintf(msgnums,
sizeof(msgnums),
"%d", smsg);
3748 snprintf(msgnumd,
sizeof(msgnumd),
"%d", dmsg);
3749 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);
3752 ast_log(
AST_LOG_WARNING,
"SQL Execute error!\n[%s] (You probably don't have MySQL 4.1 or later installed)\n\n", sql);
3754 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
3761 struct insert_data {
3764 const char *msgnums;
3769 const char *macrocontext;
3770 const char *callerid;
3771 const char *origtime;
3772 const char *duration;
3773 const char *mailboxuser;
3774 const char *mailboxcontext;
3775 const char *category;
3779 static SQLHSTMT insert_data_cb(
struct odbc_obj *obj,
void *vdata)
3781 struct insert_data *data = vdata;
3785 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->
con, &stmt);
3786 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
3788 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
3792 SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->dir), 0, (
void *) data->dir, 0, NULL);
3793 SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->msgnums), 0, (
void *) data->msgnums, 0, NULL);
3794 SQLBindParameter(stmt, 3, SQL_PARAM_INPUT, SQL_C_BINARY, SQL_LONGVARBINARY, data->datalen, 0, (
void *) data->data, data->datalen, &data->indlen);
3795 SQLBindParameter(stmt, 4, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->context), 0, (
void *) data->context, 0, NULL);
3796 SQLBindParameter(stmt, 5, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->macrocontext), 0, (
void *) data->macrocontext, 0, NULL);
3797 SQLBindParameter(stmt, 6, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->callerid), 0, (
void *) data->callerid, 0, NULL);
3798 SQLBindParameter(stmt, 7, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->origtime), 0, (
void *) data->origtime, 0, NULL);
3799 SQLBindParameter(stmt, 8, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->duration), 0, (
void *) data->duration, 0, NULL);
3800 SQLBindParameter(stmt, 9, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->mailboxuser), 0, (
void *) data->mailboxuser, 0, NULL);
3801 SQLBindParameter(stmt, 10, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->mailboxcontext), 0, (
void *) data->mailboxcontext, 0, NULL);
3802 SQLBindParameter(stmt, 11, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->flag), 0, (
void *) data->flag, 0, NULL);
3804 SQLBindParameter(stmt, 12, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->category), 0, (
void *) data->category, 0, NULL);
3806 res = SQLExecDirect(stmt, (
unsigned char *) data->sql, SQL_NTS);
3807 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
3809 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
3829 static int store_file(
const char *dir,
const char *mailboxuser,
const char *mailboxcontext,
int msgnum)
3833 void *fdm = MAP_FAILED;
3839 char full_fn[PATH_MAX];
3844 struct insert_data idata = { .sql = sql, .msgnums = msgnums, .dir = dir, .mailboxuser = mailboxuser, .mailboxcontext = mailboxcontext,
3845 .context =
"", .macrocontext =
"", .callerid =
"", .origtime =
"", .duration =
"", .category =
"", .flag =
"" };
3856 c = strchr(fmt,
'|');
3859 if (!strcasecmp(fmt,
"wav49"))
3861 snprintf(msgnums,
sizeof(msgnums),
"%d", msgnum);
3866 snprintf(full_fn,
sizeof(full_fn),
"%s.txt", fn);
3868 snprintf(full_fn,
sizeof(full_fn),
"%s.%s", fn, fmt);
3869 fd = open(full_fn, O_RDWR);
3880 idata.macrocontext =
"";
3883 idata.callerid =
"";
3886 idata.origtime =
"";
3889 idata.duration =
"";
3892 idata.category =
"";
3898 fdlen = lseek(fd, 0, SEEK_END);
3899 if (fdlen < 0 || lseek(fd, 0, SEEK_SET) < 0) {
3904 fdm = mmap(NULL, fdlen, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
3905 if (fdm == MAP_FAILED) {
3911 idata.datalen = idata.indlen = fdlen;
3914 snprintf(sql,
sizeof(sql),
"INSERT INTO %s (dir,msgnum,recording,context,macrocontext,callerid,origtime,duration,mailboxuser,mailboxcontext,flag,category) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)", odbc_table);
3916 snprintf(sql,
sizeof(sql),
"INSERT INTO %s (dir,msgnum,recording,context,macrocontext,callerid,origtime,duration,mailboxuser,mailboxcontext,flag) VALUES (?,?,?,?,?,?,?,?,?,?,?)", odbc_table);
3919 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
3930 if (fdm != MAP_FAILED)
3950 static void rename_file(
char *sdir,
int smsg,
char *mailboxuser,
char *mailboxcontext,
char *ddir,
int dmsg)
3957 char *argv[] = { ddir, msgnumd, mailboxuser, mailboxcontext, sdir, msgnums };
3958 struct generic_prepare_struct gps = { .sql = sql, .argc = 6, .argv = argv };
3963 snprintf(msgnums,
sizeof(msgnums),
"%d", smsg);
3964 snprintf(msgnumd,
sizeof(msgnumd),
"%d", dmsg);
3965 snprintf(sql,
sizeof(sql),
"UPDATE %s SET dir=?, msgnum=?, mailboxuser=?, mailboxcontext=? WHERE dir=? AND msgnum=?", odbc_table);
3970 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
3988 static int remove_file(
char *dir,
int msgnum)
3991 char full_fn[PATH_MAX];
3995 snprintf(msgnums,
sizeof(msgnums),
"%d", msgnum);
4000 snprintf(full_fn,
sizeof(full_fn),
"%s.txt", fn);
4005 #ifndef IMAP_STORAGE
4020 struct dirent *vment = NULL;
4025 if ((vmdir = opendir(dir))) {
4026 while ((vment = readdir(vmdir))) {
4027 if (strlen(vment->d_name) > 7 && !strncmp(vment->d_name + 7,
".txt", 4)) {
4047 char stxt[PATH_MAX];
4048 char dtxt[PATH_MAX];
4050 snprintf(stxt,
sizeof(stxt),
"%s.txt", sfn);
4051 snprintf(dtxt,
sizeof(dtxt),
"%s.txt", dfn);
4074 struct dirent *msgdirent;
4083 if (!(msgdir = opendir(dir))) {
4087 while ((msgdirent = readdir(msgdir))) {
4088 if (sscanf(msgdirent->d_name,
"msg%30d.%3s", &msgdirint, extension) == 2 && !strcmp(extension,
"txt") && msgdirint <
MAXMSGLIMIT) {
4091 ast_debug(4,
"%s map[%d] = %d, count = %d\n", dir, msgdirint, map[msgdirint], stopcount);
4096 for (x = 0; x < vmu->
maxmsg; x++) {
4099 }
else if (map[x] == 0 && !stopcount) {
4109 #ifndef IMAP_STORAGE
4120 static int copy(
char *infile,
char *outfile)
4128 #ifdef HARDLINK_WHEN_POSSIBLE
4130 if (link(infile, outfile)) {
4132 if ((ifd = open(infile, O_RDONLY)) < 0) {
4142 len = read(ifd, buf,
sizeof(buf));
4149 res = write(ofd, buf, len);
4150 if (
errno == ENOMEM ||
errno == ENOSPC || res != len) {
4161 #ifdef HARDLINK_WHEN_POSSIBLE
4180 char frompath2[PATH_MAX], topath2[PATH_MAX];
4182 const char *origmailbox = NULL, *context = NULL, *macrocontext = NULL, *
exten = NULL, *priority = NULL, *callerchan = NULL, *callerid = NULL, *origdate = NULL, *origtime = NULL, *category = NULL, *duration = NULL;
4184 snprintf(frompath2,
sizeof(frompath2),
"%s.txt", frompath);
4185 snprintf(topath2,
sizeof(topath2),
"%s.txt", topath);
4189 for (tmp = var; tmp; tmp = tmp->
next) {
4190 if (!strcasecmp(tmp->
name,
"origmailbox")) {
4191 origmailbox = tmp->
value;
4192 }
else if (!strcasecmp(tmp->
name,
"context")) {
4193 context = tmp->
value;
4194 }
else if (!strcasecmp(tmp->
name,
"macrocontext")) {
4195 macrocontext = tmp->
value;
4196 }
else if (!strcasecmp(tmp->
name,
"exten")) {
4198 }
else if (!strcasecmp(tmp->
name,
"priority")) {
4199 priority = tmp->
value;
4200 }
else if (!strcasecmp(tmp->
name,
"callerchan")) {
4201 callerchan = tmp->
value;
4202 }
else if (!strcasecmp(tmp->
name,
"callerid")) {
4203 callerid = tmp->
value;
4204 }
else if (!strcasecmp(tmp->
name,
"origdate")) {
4205 origdate = tmp->
value;
4206 }
else if (!strcasecmp(tmp->
name,
"origtime")) {
4207 origtime = tmp->
value;
4208 }
else if (!strcasecmp(tmp->
name,
"category")) {
4209 category = tmp->
value;
4210 }
else if (!strcasecmp(tmp->
name,
"duration")) {
4211 duration = tmp->
value;
4214 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);
4216 copy(frompath2, topath2);
4234 txtsize = (strlen(file) + 5)*
sizeof(
char);
4242 snprintf(txt, txtsize,
"%s.txt", file);
4277 if (!
inbuf(bio, fi))
4290 if (fputs(
ENDL, so) == EOF) {
4297 if (putc(((
unsigned char) c), so) == EOF) {
4317 static const unsigned char dtable[] = {
'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
'I',
'J',
'K',
4318 'L',
'M',
'N',
'O',
'P',
'Q',
'R',
'S',
'T',
'U',
'V',
'W',
'X',
'Y',
'Z',
'a',
'b',
'c',
'd',
'e',
'f',
4319 'g',
'h',
'i',
'j',
'k',
'l',
'm',
'n',
'o',
'p',
'q',
'r',
's',
't',
'u',
'v',
'w',
'x',
'y',
'z',
'0',
4320 '1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'+',
'/'};
4325 memset(&bio, 0,
sizeof(bio));
4328 if (!(fi = fopen(filename,
"rb"))) {
4334 unsigned char igroup[3], ogroup[4];
4337 memset(igroup, 0,
sizeof(igroup));
4339 for (n = 0; n < 3; n++) {
4340 if ((c =
inchar(&bio, fi)) == EOF) {
4345 igroup[n] = (
unsigned char) c;
4349 ogroup[0]= dtable[igroup[0] >> 2];
4350 ogroup[1]= dtable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)];
4351 ogroup[2]= dtable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)];
4352 ogroup[3]= dtable[igroup[2] & 0x3F];
4361 for (i = 0; i < 4; i++)
4362 ochar(&bio, ogroup[i], so);
4368 if (fputs(
ENDL, so) == EOF) {
4375 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)
4379 char fromdir[256], fromfile[256];
4381 const char *origcallerid, *origtime;
4382 char origcidname[80], origcidnum[80], origdate[80];
4389 snprintf(num,
sizeof(num),
"%d", msgnum);
4394 ast_callerid_merge(callerid,
sizeof(callerid), cidname, cidnum, NULL) :
"an unknown caller");
4403 make_file(fromfile,
sizeof(fromfile), fromdir, msgnum - 1);
4404 if (strlen(fromfile) <
sizeof(fromfile) - 5) {
4405 strcat(fromfile,
".txt");
4409 ast_log(
LOG_DEBUG,
"Config load for message text file '%s' failed\n", fromfile);
4416 ast_callerid_split(origcallerid, origcidname,
sizeof(origcidname), origcidnum,
sizeof(origcidnum));
4421 if ((origtime =
ast_variable_retrieve(msg_cfg,
"message",
"origtime")) && sscanf(origtime,
"%30d", &inttime) == 1) {
4422 struct timeval tv = { inttime, };
4445 for (ptr = from; *ptr; ptr++) {
4446 if (*ptr ==
'"' || *ptr ==
'\\') {
4463 const struct vm_zone *z = NULL;
4486 for (; *
str; str++) {
4487 if (*str > 126 || *str < 32 || strchr(
"()<>@,:;/\"[]?.=", *str)) {
4514 int first_section = 1;
4518 for (; *start; start++) {
4519 int need_encoding = 0;
4520 if (*start < 33 || *start > 126 || strchr(
"()<>@,:;/\"[]?.=_", *start)) {
4523 if ((first_section && need_encoding && preamble +
ast_str_strlen(tmp) > 70) ||
4524 (first_section && !need_encoding && preamble +
ast_str_strlen(tmp) > 72) ||
4526 (!first_section && !need_encoding &&
ast_str_strlen(tmp) > 72)) {
4532 if (need_encoding && *start ==
' ') {
4534 }
else if (need_encoding) {
4567 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)
4575 char enc_cidnum[256] =
"", enc_cidname[256] =
"";
4577 char *greeting_attachment;
4580 if (!str1 || !str2) {
4592 gethostname(host,
sizeof(host) - 1);
4594 if (strchr(srcemail,
'@')) {
4597 snprintf(who,
sizeof(who),
"%s@%s", srcemail, host);
4600 greeting_attachment = strrchr(
ast_strdupa(attach),
'/');
4601 if (greeting_attachment) {
4602 *greeting_attachment++ =
'\0';
4605 snprintf(dur,
sizeof(dur),
"%d:%02d", duration / 60, duration % 60);
4607 fprintf(p,
"Date: %s" ENDL, date);
4616 prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, enc_cidnum, enc_cidname, dur, date, category, flag);
4638 fprintf(p,
"From: Asterisk PBX <%s>" ENDL, who);
4661 prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
4684 fprintf(p,
"Subject: New message %d in mailbox %s" ENDL, msgnum + 1, mailbox);
4686 fprintf(p,
"Subject: New %s message %d in mailbox %s" ENDL, flag, msgnum + 1, mailbox);
4690 fprintf(p,
"Subject: [PBX]: New message %d in mailbox %s" ENDL, msgnum + 1, mailbox);
4692 fprintf(p,
"Subject: [PBX]: New %s message %d in mailbox %s" ENDL, flag, msgnum + 1, mailbox);
4696 fprintf(p,
"Message-ID: <Asterisk-%d-%u-%s-%d@%s>" ENDL, msgnum + 1,
4697 (
unsigned int)
ast_random(), mailbox, (
int) getpid(), host);
4700 fprintf(p,
"X-Asterisk-VM-Message-Num: %d" ENDL, msgnum + 1);
4702 fprintf(p,
"X-Asterisk-VM-Server-Name: %s" ENDL, fromstring);
4703 fprintf(p,
"X-Asterisk-VM-Context: %s" ENDL, context);
4705 fprintf(p,
"X-Asterisk-VM-Extension: %s" ENDL, (!
ast_strlen_zero(vmu->imapvmshareid) ? vmu->imapvmshareid : mailbox));
4707 fprintf(p,
"X-Asterisk-VM-Extension: %s" ENDL, mailbox);
4710 fprintf(p,
"X-Asterisk-VM-Flag: %s" ENDL, flag);
4711 fprintf(p,
"X-Asterisk-VM-Priority: %d" ENDL, chan->
priority);
4712 fprintf(p,
"X-Asterisk-VM-Caller-channel: %s" ENDL, chan->
name);
4713 fprintf(p,
"X-Asterisk-VM-Caller-ID-Num: %s" ENDL, enc_cidnum);
4714 fprintf(p,
"X-Asterisk-VM-Caller-ID-Name: %s" ENDL, enc_cidname);
4715 fprintf(p,
"X-Asterisk-VM-Duration: %d" ENDL, duration);
4717 fprintf(p,
"X-Asterisk-VM-Category: %s" ENDL, category);
4719 fprintf(p,
"X-Asterisk-VM-Category: " ENDL);
4721 fprintf(p,
"X-Asterisk-VM-Message-Type: %s" ENDL, msgnum > -1 ?
"Message" : greeting_attachment);
4722 fprintf(p,
"X-Asterisk-VM-Orig-date: %s" ENDL, date);
4723 fprintf(p,
"X-Asterisk-VM-Orig-time: %ld" ENDL, (
long) time(NULL));
4726 fprintf(p,
"X-Asterisk-CallerID: %s" ENDL, enc_cidnum);
4729 fprintf(p,
"X-Asterisk-CallerIDName: %s" ENDL, enc_cidname);
4731 fprintf(p,
"MIME-Version: 1.0" ENDL);
4732 if (attach_user_voicemail) {
4734 snprintf(bound,
sizeof(bound),
"----voicemail_%d%s%d%u", msgnum + 1, mailbox,
4735 (
int) getpid(), (
unsigned int)
ast_random());
4737 fprintf(p,
"Content-Type: multipart/mixed; boundary=\"%s\"" ENDL, bound);
4738 fprintf(p,
ENDL ENDL "This is a multi-part message in MIME format." ENDL ENDL);
4739 fprintf(p,
"--%s" ENDL, bound);
4741 fprintf(p,
"Content-Type: text/plain; charset=%s" ENDL "Content-Transfer-Encoding: 8bit" ENDL ENDL, charset);
4746 prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
4754 if ((next = strchr(line,
'\n'))) {
4757 fprintf(p,
"%s" ENDL, line);
4768 }
else if (msgnum > -1) {
4769 if (strcmp(vmu->
mailbox, mailbox)) {
4774 char fromdir[256], fromfile[256], origdate[80] =
"", origcallerid[80] =
"";
4778 make_file(fromfile,
sizeof(fromfile), fromdir, msgnum);
4779 if (strlen(fromfile) <
sizeof(fromfile) - 5) {
4780 strcat(fromfile,
".txt");
4789 if ((v =
ast_variable_retrieve(msg_cfg,
"message",
"origtime")) && sscanf(v,
"%30d", &inttime) == 1) {
4790 struct timeval tv = { inttime, };
4795 fprintf(p,
"Dear %s:" ENDL ENDL
"\tJust wanted to let you know you were just forwarded"
4796 " a %s long message (number %d)" ENDL
"in mailbox %s from %s, on %s" ENDL
4797 "(originally sent by %s on %s)" ENDL
"so you might want to check it when you get a"
4798 " chance. Thanks!" ENDL ENDL
"\t\t\t\t--Asterisk" ENDL ENDL, vmu->
fullname, dur,
4799 msgnum + 1, mailbox, (cidname ? cidname : (cidnum ? cidnum :
"an unknown caller")),
4800 date, origcallerid, origdate);
4807 fprintf(p,
"Dear %s:" ENDL ENDL
"\tJust wanted to let you know you were just left a "
4808 "%s long message (number %d)" ENDL
"in mailbox %s from %s, on %s so you might" ENDL
4809 "want to check it when you get a chance. Thanks!" ENDL ENDL
"\t\t\t\t--Asterisk"
4810 ENDL ENDL, vmu->
fullname, dur, msgnum + 1, mailbox,
4811 (cidname ? cidname : (cidnum ? cidnum :
"an unknown caller")), date);
4814 fprintf(p,
"This message is to let you know that your greeting was changed on %s." ENDL
4815 "Please do not delete this message, lest your greeting vanish with it." ENDL ENDL, date);
4818 if (imap || attach_user_voicemail) {
4820 snprintf(filename,
sizeof(filename),
"msg%04d.%s", msgnum, format);
4821 ast_debug(5,
"creating second attachment filename %s\n", filename);
4822 add_email_attachment(p, vmu, format, attach, greeting_attachment, mailbox, bound, filename, 0, msgnum);
4823 snprintf(filename,
sizeof(filename),
"msgintro%04d.%s", msgnum, format);
4824 ast_debug(5,
"creating attachment filename %s\n", filename);
4825 add_email_attachment(p, vmu, format, attach2, greeting_attachment, mailbox, bound, filename, 1, msgnum);
4827 snprintf(filename,
sizeof(filename),
"msg%04d.%s", msgnum, format);
4828 ast_debug(5,
"creating attachment filename %s, no second attachment.\n", filename);
4829 add_email_attachment(p, vmu, format, attach, greeting_attachment, mailbox, bound, filename, 1, msgnum);
4838 char tmpdir[256], newtmp[256];
4845 char *ctype = (!strcasecmp(format,
"ogg")) ?
"application/" :
"audio/x-";
4849 snprintf(newtmp,
sizeof(newtmp),
"%s/XXXXXX", tmpdir);
4850 tmpfd = mkstemp(newtmp);
4854 snprintf(tmpcmd,
sizeof(tmpcmd),
"sox -v %.4f %s.%s %s.%s", vmu->
volgain, attach, format, newtmp, format);
4857 ast_debug(3,
"VOLGAIN: Stored at: %s.%s - Level: %.4f - Mailbox: %s\n", attach, format, vmu->
volgain, mailbox);
4859 ast_log(
LOG_WARNING,
"Sox failed to re-encode %s.%s: %s (have you installed support for all sox file formats?)\n", attach, format,
4860 soxstatus == 1 ?
"Problem with command line options" :
"An error occurred during file processing");
4865 fprintf(p,
"--%s" ENDL, bound);
4867 fprintf(p,
"Content-Type: %s%s; name=\"%s\"" ENDL, ctype, format, filename);
4869 fprintf(p,
"Content-Type: %s%s; name=\"%s.%s\"" ENDL, ctype, format, greeting_attachment, format);
4870 fprintf(p,
"Content-Transfer-Encoding: base64" ENDL);
4871 fprintf(p,
"Content-Description: Voicemail sound attachment." ENDL);
4873 fprintf(p,
"Content-Disposition: attachment; filename=\"%s\"" ENDL ENDL, filename);
4875 fprintf(p,
"Content-Disposition: attachment; filename=\"%s.%s\"" ENDL ENDL, greeting_attachment, format);
4876 snprintf(fname,
sizeof(fname),
"%s.%s", attach, format);
4879 fprintf(p, ENDL ENDL
"--%s--" ENDL
"." ENDL, bound);
4881 if (soxstatus == 0) {
4890 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)
4893 char tmp[80] =
"/tmp/astmail-XXXXXX";
4907 if (!strcmp(format,
"wav49"))
4909 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));
4916 make_email_file(p, srcemail, vmu, msgnum, context, mailbox, fromfolder, cidnum, cidname, attach, attach2, format, duration, attach_user_voicemail, chan, category, 0, flag);
4918 snprintf(tmp2,
sizeof(tmp2),
"( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
4920 ast_debug(1,
"Sent mail to %s with command '%s'\n", vmu->
email, mailcmd);
4925 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)
4927 char enc_cidnum[256], enc_cidname[256];
4932 char tmp[80] =
"/tmp/astmail-XXXXXX";
4933 char tmp2[PATH_MAX];
4938 if (!str1 || !str2) {
4957 gethostname(host,
sizeof(host)-1);
4958 if (strchr(srcemail,
'@')) {
4961 snprintf(who,
sizeof(who),
"%s@%s", srcemail, host);
4963 snprintf(dur,
sizeof(dur),
"%d:%02d", duration / 60, duration % 60);
4965 fprintf(p,
"Date: %s\n", date);
4974 prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, enc_cidnum, enc_cidname, dur, date, category, flag);
4996 fprintf(p,
"From: Asterisk PBX <%s>" ENDL, who);
5018 prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
5041 fprintf(p,
"Subject: New VM\n\n");
5043 fprintf(p,
"Subject: New %s VM\n\n", flag);
5050 prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
5058 fprintf(p,
"New %s long %s msg in box %s\n"
5059 "from %s, on %s", dur, flag, mailbox, (cidname ? cidname : (cidnum ? cidnum :
"unknown")), date);
5063 snprintf(tmp2,
sizeof(tmp2),
"( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
5065 ast_debug(1,
"Sent page to %s with command '%s'\n", pager, mailcmd);
5087 return ast_strftime(s, len,
"%a %b %e %r UTC %Y", &tm);
5094 char dest[PATH_MAX];
5096 snprintf(fn,
sizeof(fn),
"%s%s/%s/greet", VM_SPOOL_DIR, context, ext);
5098 if ((res =
create_dirpath(dest,
sizeof(dest), context, ext,
""))) {
5130 static int inboxcount2(
const char *mailbox,
int *urgentmsgs,
int *newmsgs,
int *oldmsgs)
5134 SQLHSTMT stmt = NULL;
5137 char tmp[PATH_MAX] =
"";
5140 struct generic_prepare_struct gps = { .sql = sql, .argc = 0 };
5155 if (strchr(mailbox,
' ') || strchr(mailbox,
',')) {
5157 char *next, *remaining = tmp;
5158 while ((next =
strsep(&remaining,
" ,"))) {
5159 if (
inboxcount2(next, urgentmsgs ? &u : NULL, &n, &o)) {
5175 context = strchr(tmp,
'@');
5180 context =
"default";
5185 snprintf(sql,
sizeof(sql),
"SELECT COUNT(*) FROM %s WHERE dir = '%s%s/%s/%s'", odbc_table, VM_SPOOL_DIR, context, tmp,
"INBOX");
5190 res = SQLFetch(stmt);
5191 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
5195 res = SQLGetData(stmt, 1, SQL_CHAR, rowdata,
sizeof(rowdata), NULL);
5196 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
5200 *newmsgs = atoi(rowdata);
5201 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
5205 snprintf(sql,
sizeof(sql),
"SELECT COUNT(*) FROM %s WHERE dir = '%s%s/%s/%s'", odbc_table, VM_SPOOL_DIR, context, tmp,
"Old");
5210 res = SQLFetch(stmt);
5211 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
5215 res = SQLGetData(stmt, 1, SQL_CHAR, rowdata,
sizeof(rowdata), NULL);
5216 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
5220 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
5221 *oldmsgs = atoi(rowdata);
5225 snprintf(sql,
sizeof(sql),
"SELECT COUNT(*) FROM %s WHERE dir = '%s%s/%s/%s'", odbc_table, VM_SPOOL_DIR, context, tmp,
"Urgent");
5230 res = SQLFetch(stmt);
5231 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
5235 res = SQLGetData(stmt, 1, SQL_CHAR, rowdata,
sizeof(rowdata), NULL);
5236 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
5240 *urgentmsgs = atoi(rowdata);
5250 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
5267 static int messagecount(
const char *context,
const char *mailbox,
const char *folder)
5272 SQLHSTMT stmt = NULL;
5275 struct generic_prepare_struct gps = { .sql = sql, .argc = 0 };
5284 if (!strcmp(folder,
"INBOX")) {
5285 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);
5287 snprintf(sql,
sizeof(sql),
"SELECT COUNT(*) FROM %s WHERE dir = '%s%s/%s/%s'", odbc_table, VM_SPOOL_DIR, context, mailbox, folder);
5294 res = SQLFetch(stmt);
5295 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
5297 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
5300 res = SQLGetData(stmt, 1, SQL_CHAR, rowdata,
sizeof(rowdata), NULL);
5301 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
5303 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
5306 nummsgs = atoi(rowdata);
5307 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
5325 static int has_voicemail(
const char *mailbox,
const char *folder)
5327 char tmp[256], *tmp2 = tmp, *box, *
context;
5329 while ((context = box =
strsep(&tmp2,
",&"))) {
5332 context =
"default";
5339 #ifndef IMAP_STORAGE
5358 char fromdir[PATH_MAX], todir[PATH_MAX], frompath[PATH_MAX], topath[PATH_MAX];
5359 const char *frombox =
mbox(vmu, imbox);
5360 const char *userfolder;
5367 userfolder =
"Urgent";
5369 userfolder =
"INBOX";
5379 make_file(frompath,
sizeof(frompath), fromdir, msgnum);
5387 make_file(topath,
sizeof(topath), todir, recipmsgnum);
5388 #ifndef ODBC_STORAGE
5390 COPY(fromdir, msgnum, todir, recipmsgnum, recip->
mailbox, recip->
context, frompath, topath);
5397 STORE(todir, recip->
mailbox, recip->
context, recipmsgnum, chan, recip, fmt, duration, NULL, NULL);
5399 #ifndef ODBC_STORAGE
5415 #if !(defined(IMAP_STORAGE) || defined(ODBC_STORAGE))
5417 static int messagecount(
const char *context,
const char *mailbox,
const char *folder)
5422 static int __has_voicemail(
const char *context,
const char *mailbox,
const char *folder,
int shortcircuit)
5436 context =
"default";
5438 snprintf(fn,
sizeof(fn),
"%s%s/%s/%s", VM_SPOOL_DIR, context, mailbox, folder);
5440 if (!(dir = opendir(fn)))
5443 while ((de = readdir(dir))) {
5444 if (!strncasecmp(de->d_name,
"msg", 3)) {
5448 }
else if (!strncasecmp(de->d_name + 8,
"txt", 3)) {
5470 char tmp[256], *tmp2 = tmp, *box, *
context;
5475 while ((box =
strsep(&tmp2,
",&"))) {
5476 if ((context = strchr(box,
'@')))
5479 context =
"default";
5483 if (!strcmp(folder,
"INBOX") &&
__has_voicemail(context, box,
"Urgent", 1)) {
5491 static int inboxcount2(
const char *mailbox,
int *urgentmsgs,
int *newmsgs,
int *oldmsgs)
5507 if (strchr(mailbox,
',')) {
5508 int tmpnew, tmpold, tmpurgent;
5513 while ((cur =
strsep(&mb,
", "))) {
5515 if (
inboxcount2(cur, urgentmsgs ? &tmpurgent : NULL, newmsgs ? &tmpnew : NULL, oldmsgs ? &tmpold : NULL))
5523 *urgentmsgs += tmpurgent;
5532 if ((context = strchr(tmp,
'@')))
5535 context =
"default";
5550 static int inboxcount(
const char *mailbox,
int *newmsgs,
int *oldmsgs)
5553 int res =
inboxcount2(mailbox, &urgentmsgs, newmsgs, oldmsgs);
5555 *newmsgs += urgentmsgs;
5562 char arguments[255];
5563 char ext_context[256] =
"";
5564 int newvoicemails = 0, oldvoicemails = 0, urgentvoicemails = 0;
5568 snprintf(ext_context,
sizeof(ext_context),
"%s@%s", extension, context);
5580 if (!strncmp(mwi_msg->
cause,
"INV", 3))
5582 else if (!strncmp(mwi_msg->
cause,
"BLK", 3))
5587 ast_debug(1,
"Successfully executed SMDI MWI change for %s\n", extension);
5592 if (
inboxcount2(ext_context, &urgentvoicemails, &newvoicemails, &oldvoicemails)) {
5593 ast_log(
AST_LOG_ERROR,
"Problem in calculating number of voicemail messages available for extension %s\n", extension);
5595 snprintf(arguments,
sizeof(arguments),
"%s %s %s %d %d %d &",
5596 externnotify,
S_OR(context,
"\"\""),
5597 extension, newvoicemails,
5598 oldvoicemails, urgentvoicemails);
5599 ast_debug(1,
"Executing %s\n", arguments);
5612 signed char record_gain;
5629 int newmsgs, oldmsgs;
5631 char urgdir[PATH_MAX];
5633 char txtfile[PATH_MAX];
5634 char tmptxtfile[PATH_MAX];
5643 int sound_duration = 0;
5651 char tmpdir[PATH_MAX];
5653 char prefile[PATH_MAX] =
"";
5654 char tempfile[PATH_MAX] =
"";
5655 char ext_context[256] =
"";
5658 char ecodes[17] =
"#";
5663 const char *category = NULL;
5665 const char *alldtmf =
"0123456789ABCD*#";
5674 if ((context = strchr(ext,
'@'))) {
5676 tmpptr = strchr(context,
'&');
5678 tmpptr = strchr(ext,
'&');
5699 if (!(vmu =
find_user(&svm, context, ext))) {
5706 if (strcmp(vmu->
context,
"default"))
5707 snprintf(ext_context,
sizeof(ext_context),
"%s@%s", ext, vmu->
context);
5717 snprintf(prefile,
sizeof(prefile),
"%s%s/%s/busy", VM_SPOOL_DIR, vmu->
context, ext);
5719 snprintf(prefile,
sizeof(prefile),
"%s%s/%s/unavail", VM_SPOOL_DIR, vmu->
context, ext);
5725 snprintf(tempfile,
sizeof(tempfile),
"%s%s/%s/temp", VM_SPOOL_DIR, vmu->
context, ext);
5737 #ifndef IMAP_STORAGE
5740 snprintf(dir,
sizeof(dir),
"%simap", VM_SPOOL_DIR);
5751 strncat(ecodes,
"0",
sizeof(ecodes) - strlen(ecodes) - 1);
5756 strncat(ecodes,
"0",
sizeof(ecodes) - strlen(ecodes) - 1);
5761 strncat(ecodes,
"0",
sizeof(ecodes) - strlen(ecodes) - 1);
5769 strncat(ecodes,
"*",
sizeof(ecodes) - strlen(ecodes) - 1);
5773 strncat(ecodes,
"*",
sizeof(ecodes) - strlen(ecodes) - 1);
5777 strncat(ecodes,
"*",
sizeof(ecodes) - strlen(ecodes) - 1);
5782 for (code = alldtmf; *code; code++) {
5785 if (strchr(ecodes, e[0]) == NULL
5789 strncat(ecodes, e,
sizeof(ecodes) - strlen(ecodes) - 1);
5799 RETRIEVE(prefile, -1, ext, context);
5804 if (success == -1) {
5806 ast_debug(1,
"Greeting not retrieved from database, but found in file storage. Inserting into database\n");
5811 ast_debug(1,
"%s doesn't exist, doing what we can\n", prefile);
5816 ast_debug(1,
"Hang up during prefile playback\n");
5831 ast_log(
LOG_DEBUG,
"Greetings only VM (maxmsg=0), Skipping voicemail recording\n");
5847 chan->
exten[0] =
'a';
5848 chan->
exten[1] =
'\0';
5864 if (ouseexten || ousemacro) {
5865 chan->
exten[0] =
'o';
5866 chan->
exten[1] =
'\0';
5906 res =
inboxcount(ext_context, &newmsgs, &oldmsgs);
5912 if (!(vms = get_vm_state_by_mailbox(ext, context, 0))) {
5917 if (!(vms = create_vm_state_from_user(vmu))) {
5926 msgnum = newmsgs + oldmsgs;
5927 ast_debug(3,
"Messagecount set to %d\n", msgnum);
5928 snprintf(fn,
sizeof(fn),
"%simap/msg%s%04d", VM_SPOOL_DIR, vmu->
mailbox, msgnum);
5932 if ((res = imap_check_limits(chan, vms, vmu, msgnum))) {
5947 snprintf(tmptxtfile,
sizeof(tmptxtfile),
"%s/XXXXXX", tmpdir);
5948 txtdes = mkstemp(tmptxtfile);
5968 snprintf(priority,
sizeof(priority),
"%d", chan->
priority);
5969 snprintf(origtime,
sizeof(origtime),
"%ld", (
long) time(NULL));
5979 "exten", chan->
exten,
5980 "priority", priority,
5981 "callerchan", chan->
name,
5982 "callerid", callerid,
5984 "origtime", origtime,
5985 "category",
S_OR(category,
""),
5986 "filename", tmptxtfile,
5991 txt = fdopen(txtdes,
"w+");
6000 "; Message Information file\n"
6023 date, (
long) time(NULL),
6024 category ? category :
"");
6034 res =
play_record_review(chan, NULL, tmptxtfile, vmu->
maxsecs, fmt, 1, vmu, &duration, &sound_duration, NULL, options->
record_gain, vms, flag);
6037 fprintf(txt,
"flag=%s\n", flag);
6038 if (sound_duration < vmu->
minsecs) {
6040 ast_verb(3,
"Recording was %d seconds long but needs to be at least %d - abandoning\n", sound_duration, vmu->
minsecs);
6048 fprintf(txt,
"duration=%d\n", duration);
6057 ast_debug(1,
"The recorded media file is gone, so we should remove the .txt file too!\n");
6065 #ifndef IMAP_STORAGE
6071 #ifndef IMAP_STORAGE
6077 snprintf(txtfile,
sizeof(txtfile),
"%s.txt", fn);
6079 rename(tmptxtfile, txtfile);
6089 snprintf(tmpdur,
sizeof(tmpdur),
"%d", duration);
6104 exten =
strsep(&tmpptr,
"&");
6105 cntx = strchr(exten,
'@');
6110 if ((recip =
find_user(&recipu, cntx, exten))) {
6111 copy_message(chan, vmu, 0, msgnum, duration, recip, fmt, dir, flag);
6115 #ifndef IMAP_STORAGE
6124 make_file(sfn,
sizeof(sfn), dir, msgnum);
6126 ast_debug(5,
"Created an Urgent message, moving file from %s to %s.\n", sfn, dfn);
6159 }
else if (res > 0 && res !=
't')
6162 if (sound_duration < vmu->
minsecs)
6174 ast_debug(3,
"*** Checking if we can expunge, expungeonhangup set to %d\n", expungeonhangup);
6175 if (expungeonhangup == 1) {
6177 #ifdef HAVE_IMAP_TK2006
6178 if (LEVELUIDPLUS (vms->mailstream)) {
6179 mail_expunge_full(vms->mailstream, NIL, EX_UID);
6182 mail_expunge(vms->mailstream);
6191 #if !defined(IMAP_STORAGE)
6204 for (x = 0, dest = 0; dest != stopcount && x < vmu->
maxmsg + 10; x++) {
6206 if (
EXISTS(dir, x, sfn, NULL)) {
6239 snprintf(sequence,
sizeof(sequence),
"%ld", vms->msgArray[msg]);
6241 ast_debug(3,
"Copying sequence %s to mailbox %s\n", sequence,
mbox(vmu, box));
6245 mail_setflag(vms->mailstream, sequence,
"\\Seen");
6246 mail_clearflag(vms->mailstream, sequence,
"\\Unseen");
6248 mail_setflag(vms->mailstream, sequence,
"\\Unseen");
6249 mail_clearflag(vms->mailstream, sequence,
"\\Seen");
6256 imap_mailbox_name(mailbox,
sizeof(mailbox), vms, box, 1);
6257 ast_debug(5,
"Checking if folder exists: %s\n", mailbox);
6258 if (mail_create(vms->mailstream, mailbox) == NIL)
6262 res = !mail_copy(vms->mailstream, sequence, (
char *)
mbox(vmu, box));
6271 char ddir[PATH_MAX];
6272 const char *dbox =
mbox(vmu, box);
6283 for (i = 1; i <= x; i++) {
6286 make_file(dfn,
sizeof(dfn), ddir, i - 1);
6287 if (
EXISTS(ddir, i, sfn, NULL)) {
6300 if (strcmp(sfn, dfn)) {
6301 COPY(dir, msg, ddir, x, username, context, sfn, dfn);
6318 unsigned char buf[256];
6350 bytes += ast_adsi_logo(buf);
6394 for (x = 0; x < 5; x++) {
6395 snprintf(num,
sizeof(num),
"%d", x);
6423 ast_debug(1,
"Done downloading scripts...\n");
6431 ast_debug(1,
"Restarting session...\n");
6464 unsigned char buf[256];
6466 unsigned char keys[8];
6471 for (x = 0; x < 8; x++)
6490 unsigned char buf[256];
6492 unsigned char keys[8];
6497 for (x = 0; x < 8; x++)
6512 unsigned char buf[256];
6514 unsigned char keys[8];
6520 for (x = 0; x < 5; x++) {
6542 unsigned char buf[256];
6549 char datetime[21] =
"";
6552 unsigned char keys[8];
6560 snprintf(fn2,
sizeof(fn2),
"%s.txt", vms->
fn);
6561 f = fopen(fn2,
"r");
6564 if (!fgets((
char *) buf,
sizeof(buf), f)) {
6568 char *stringp = NULL;
6569 stringp = (
char *) buf;
6571 val =
strsep(&stringp,
"=");
6573 if (!strcmp((
char *) buf,
"callerid"))
6575 if (!strcmp((
char *) buf,
"origdate"))
6583 for (x = 0; x < 5; x++)
6610 name =
"Unknown Caller";
6625 snprintf(buf1,
sizeof(buf1),
"%s%s", vms->
curbox,
6626 strcasecmp(vms->
curbox,
"INBOX") ?
" Messages" :
"");
6627 snprintf(buf2,
sizeof(buf2),
"Message %d of %d", vms->
curmsg + 1, vms->
lastmsg + 1);
6643 unsigned char buf[256];
6644 unsigned char keys[8];
6652 for (x = 0; x < 5; x++)
6694 unsigned char buf[256] =
"";
6695 char buf1[256] =
"",
buf2[256] =
"";
6697 unsigned char keys[8];
6700 char *newm = (vms->
newmessages == 1) ?
"message" :
"messages";
6701 char *oldm = (vms->
oldmessages == 1) ?
"message" :
"messages";
6705 snprintf(buf1,
sizeof(buf1),
"You have %d new", vms->
newmessages);
6707 strncat(buf1,
" and",
sizeof(buf1) - strlen(buf1) - 1);
6710 snprintf(
buf2,
sizeof(
buf2),
"%s.", newm);
6713 snprintf(buf1,
sizeof(buf1),
"You have %d old", vms->
oldmessages);
6714 snprintf(
buf2,
sizeof(
buf2),
"%s.", oldm);
6716 strcpy(buf1,
"You have no messages.");
6724 for (x = 0; x < 6; x++)
6741 unsigned char buf[256] =
"";
6742 char buf1[256] =
"",
buf2[256] =
"";
6744 unsigned char keys[8];
6747 char *mess = (vms->
lastmsg == 0) ?
"message" :
"messages";
6753 for (x = 0; x < 6; x++)
6762 snprintf(buf1,
sizeof(buf1),
"%s%s has", vms->
curbox,
6763 strcasecmp(vms->
curbox,
"INBOX") ?
" folder" :
"");
6768 strcpy(
buf2,
"no messages.");
6797 unsigned char buf[256];
6823 for (x = start; x < 5; x++) {
6829 snprintf(fn,
sizeof(fn),
"vm-%s",
mbox(NULL, x));
6838 ast_verb(1,
"failed to find %s\n", fn);
6878 while (((res <
'0') || (res >
'9')) &&
6879 (res !=
'#') && (res >= 0) &&
6911 char *context,
signed char record_gain,
long *duration,
struct vm_state *vms,
char *flag)
6914 int retries = 0, prepend_duration = 0, already_recorded = 0;
6915 char msgfile[PATH_MAX], backup[PATH_MAX], backup_textfile[PATH_MAX];
6916 char textfile[PATH_MAX];
6919 #ifndef IMAP_STORAGE
6920 signed char zero_gain = 0;
6922 const char *duration_str;
6925 make_file(msgfile,
sizeof(msgfile), curdir, curmsg);
6926 strcpy(textfile, msgfile);
6927 strcpy(backup, msgfile);
6928 strcpy(backup_textfile, msgfile);
6929 strncat(textfile,
".txt",
sizeof(textfile) - strlen(textfile) - 1);
6930 strncat(backup,
"-bak",
sizeof(backup) - strlen(backup) - 1);
6931 strncat(backup_textfile,
"-bak.txt",
sizeof(backup_textfile) - strlen(backup_textfile) - 1);
6934 *duration = atoi(duration_str);
6939 while ((cmd >= 0) && (cmd !=
't') && (cmd !=
'*')) {
6947 make_file(vms->introfn,
sizeof(vms->introfn), curdir, curmsg);
6948 strncat(vms->introfn,
"intro",
sizeof(vms->introfn));
6951 cmd =
play_record_review(chan, NULL, vms->introfn, vmu->
maxsecs, vm_fmts, 1, vmu, (
int *) duration, NULL, NULL, record_gain, vms, flag);
6960 make_file(msgfile,
sizeof(msgfile), curdir, curmsg);
6961 strcpy(textfile, msgfile);
6962 strncat(textfile,
".txt",
sizeof(textfile) - 1);
6972 #ifndef IMAP_STORAGE
6973 if (already_recorded) {
6975 copy(backup_textfile, textfile);
6979 copy(textfile, backup_textfile);
6982 already_recorded = 1;
6987 cmd =
ast_play_and_prepend(chan, NULL, msgfile, 0, vm_fmts, &prepend_duration, NULL, 1, silencethreshold, maxsilence);
7000 *duration = atoi(duration_str);
7002 if (prepend_duration) {
7005 char duration_buf[12];
7007 *duration += prepend_duration;
7009 snprintf(duration_buf, 11,
"%ld", *duration);
7020 *vms->introfn =
'\0';
7029 already_recorded = 0;
7052 if (prepend_duration)
7053 *duration = prepend_duration;
7055 if (already_recorded && cmd == -1) {
7058 rename(backup_textfile, textfile);
7061 if (cmd ==
't' || cmd ==
'S')
7075 context =
"default";
7105 char todir[PATH_MAX], fn[PATH_MAX], ext_context[PATH_MAX], *stringp;
7106 int newmsgs = 0, oldmsgs = 0, urgentmsgs = 0;
7107 const char *category;
7116 #ifndef IMAP_STORAGE
7119 snprintf(todir,
sizeof(todir),
"%simap", VM_SPOOL_DIR);
7121 make_file(fn,
sizeof(fn), todir, msgnum);
7122 snprintf(ext_context,
sizeof(ext_context),
"%s@%s", vmu->
mailbox, vmu->
context);
7142 if (attach_user_voicemail)
7146 sendmail(myserveremail, vmu, msgnum, vmu->
context, vmu->
mailbox,
mbox(vmu, 0), cidnum, cidname, fn, NULL, fmt, duration, attach_user_voicemail, chan, category, flag);
7148 if (attach_user_voicemail)
7153 sendpage(myserveremail, vmu->
pager, msgnum, vmu->
context, vmu->
mailbox,
mbox(vmu, 0), cidnum, cidname, duration, vmu, category, flag);
7157 DELETE(todir, msgnum, fn, vmu);
7171 vm_imap_delete(NULL, vms->
curmsg, vmu);
7214 char ecodes[16] =
"#";
7215 int res = 0, cmd = 0;
7220 int saved_messages = 0;
7221 int valid_extensions = 0;
7224 char urgent_str[7] =
"";
7225 int prompt_played = 0;
7226 #ifndef IMAP_STORAGE
7227 char msgfile[PATH_MAX], textfile[PATH_MAX], backup[PATH_MAX], backup_textfile[PATH_MAX];
7230 ast_copy_string(urgent_str, urgent ?
"Urgent" :
"",
sizeof(urgent_str));
7233 if (vms == NULL)
return -1;
7238 while (!res && !valid_extensions) {
7239 int use_directory = 0;
7244 while ((cmd >= 0) && !done ){
7276 if (cmd < 0 || cmd ==
't')
7280 if (use_directory) {
7283 char old_context[
sizeof(chan->
context)];
7284 char old_exten[
sizeof(chan->
exten)];
7286 struct ast_app* directory_app;
7289 if (directory_app) {
7290 char vmcontext[256];
7293 memcpy(old_exten, chan->
exten,
sizeof(chan->
exten));
7297 snprintf(vmcontext,
sizeof(vmcontext),
"%s,,v", context ? context :
"default");
7298 res =
pbx_exec(chan, directory_app, vmcontext);
7304 memcpy(chan->
exten, old_exten,
sizeof(chan->
exten));
7314 if (res || prompt_played > 4)
7316 if ((res =
ast_readstring(chan, username,
sizeof(username) - 1, 2000, 10000,
"#") < 0))
7324 s =
strsep(&stringp,
"*");
7326 valid_extensions = 1;
7328 if ((is_new_message == 1 || strcmp(s, sender->
mailbox)) && (receiver =
find_user(NULL, context, s))) {
7333 ast_log(
LOG_ERROR,
"Problem in calculating number of voicemail messages available for extension %s\n", s);
7336 valid_extensions = 0;
7340 if ((newmsgs + oldmsgs) >= capacity) {
7341 ast_log(
LOG_NOTICE,
"Mailbox '%s' is full with capacity of %d, prompting for another extension.\n", s, capacity);
7343 valid_extensions = 0;
7364 valid_extensions = 0;
7369 snprintf(fn,
sizeof(fn),
"%s%s/%s/greet", VM_SPOOL_DIR, receiver->
context, s);
7382 s =
strsep(&stringp,
"*");
7385 if (valid_extensions)
7391 if (is_new_message == 1) {
7394 snprintf(mailbox,
sizeof(mailbox),
"%s@%s", username, context);
7397 memset(&leave_options, 0,
sizeof(leave_options));
7404 int copy_msg_result = 0;
7405 memcpy(&vmstmp, vms,
sizeof(vmstmp));
7409 cmd =
vm_forwardoptions(chan, sender, vmstmp.
curdir, curmsg, vmfmts,
S_OR(context,
"default"), record_gain, &duration, &vmstmp, urgent_str);
7413 int attach_user_voicemail;
7417 dstvms = get_vm_state_by_mailbox(vmtmp->mailbox, vmtmp->context, 0);
7419 dstvms = create_vm_state_from_user(vmtmp);
7422 init_mailstream(dstvms, 0);
7423 if (!dstvms->mailstream) {
7426 copy_msg_result =
STORE(vmstmp.
curdir, vmtmp->mailbox, vmtmp->context, dstvms->
curmsg, chan, vmtmp, fmt, duration, dstvms, urgent_str);
7433 myserveremail = vmtmp->serveremail;
7436 sendmail(myserveremail, vmtmp, todircount, vmtmp->context, vmtmp->mailbox,
7440 vmstmp.
fn, vmstmp.introfn, fmt, duration, attach_user_voicemail, chan,
7443 copy_msg_result =
copy_message(chan, sender, 0, curmsg, duration, vmtmp, fmt, dir, urgent_str);
7453 if (saved_messages > 0 && !copy_msg_result) {
7468 #ifndef IMAP_STORAGE
7474 make_file(msgfile,
sizeof(msgfile), dir, curmsg);
7475 strcpy(textfile, msgfile);
7476 strcpy(backup, msgfile);
7477 strcpy(backup_textfile, msgfile);
7478 strncat(textfile,
".txt",
sizeof(textfile) - strlen(textfile) - 1);
7479 strncat(backup,
"-bak",
sizeof(backup) - strlen(backup) - 1);
7480 strncat(backup_textfile,
"-bak.txt",
sizeof(backup_textfile) - strlen(backup_textfile) - 1);
7483 rename(backup_textfile, textfile);
7488 #ifndef IMAP_STORAGE
7490 make_file(msgfile,
sizeof(msgfile), dir, curmsg);
7491 strcpy(textfile, msgfile);
7492 strcpy(backup_textfile, msgfile);
7493 strncat(textfile,
".txt",
sizeof(textfile) - strlen(textfile) - 1);
7494 strncat(backup_textfile,
"-bak.txt",
sizeof(backup_textfile) - strlen(backup_textfile) - 1);
7495 rename(backup_textfile, textfile);
7505 return res ? res : cmd;
7519 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);
7540 struct vm_zone *the_zone = NULL;
7570 if (time_now.tm_year == time_then.tm_year)
7571 snprintf(temp,
sizeof(temp),
"%d", time_now.tm_yday);
7573 snprintf(temp,
sizeof(temp),
"%d", (time_now.tm_year - time_then.tm_year) * 365 + (time_now.tm_yday - time_then.tm_yday));
7580 }
else if (!strncasecmp(chan->
language,
"de", 2)) {
7582 }
else if (!strncasecmp(chan->
language,
"gr", 2)) {
7584 }
else if (!strncasecmp(chan->
language,
"it", 2)) {
7586 }
else if (!strncasecmp(chan->
language,
"nl", 2)) {
7588 }
else if (!strncasecmp(chan->
language,
"no", 2)) {
7590 }
else if (!strncasecmp(chan->
language,
"pl", 2)) {
7592 }
else if (!strncasecmp(chan->
language,
"pt_BR", 5)) {
7594 }
else if (!strncasecmp(chan->
language,
"se", 2)) {
7596 }
else if (!strncasecmp(chan->
language,
"zh", 2)) {
7598 }
else if (!strncasecmp(chan->
language,
"vi", 2)) {
7615 char *callerid, *
name;
7616 char prefile[PATH_MAX] =
"";
7626 if ((cid == NULL)||(context == NULL))
7630 ast_debug(1,
"VM-CID: composite caller ID received: %s, context: %s\n", cid, context);
7636 ast_debug(1,
"VM-CID: comparing internalcontext: %s\n", cidinternalcontexts[i]);
7637 if ((strcmp(cidinternalcontexts[i], context) == 0))
7640 if (i != MAX_NUM_CID_CONTEXTS){
7642 snprintf(prefile,
sizeof(prefile),
"%s%s/%s/greet", VM_SPOOL_DIR, context, callerid);
7646 ast_verb(3,
"Playing envelope info: CID number '%s' matches mailbox number, playing recorded name\n", callerid);
7651 ast_verb(3,
"Playing envelope info: message from '%s'\n", callerid);
7654 res =
wait_file2(chan, vms,
"vm-from-extension");
7660 ast_debug(1,
"VM-CID: Numeric caller id: (%s)\n", callerid);
7663 res =
wait_file2(chan, vms,
"vm-from-phonenumber");
7668 ast_debug(1,
"VM-CID: From an unknown number\n");
7670 res =
wait_file2(chan, vms,
"vm-unknown-caller");
7681 if (duration == NULL)
7685 durations = atoi(duration);
7686 durationm = (durations / 60);
7688 ast_debug(1,
"VM-Duration: duration is: %d seconds converted to: %d minutes\n", durations, durationm);
7690 if ((!res) && (durationm >= minduration)) {
7694 if (!strncasecmp(chan->
language,
"pl", 2)) {
7695 div_t num = div(durationm, 10);
7697 if (durationm == 1) {
7700 }
else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
7728 char filename[256], *cid;
7729 const char *origtime, *
context, *category, *duration, *flag;
7742 snprintf(filename,
sizeof(filename),
"%s.txt", vms->
fn);
7759 if (!strncasecmp(chan->
language,
"pl", 2)) {
7763 ten = (vms->
curmsg + 1) / 10;
7764 one = (vms->
curmsg + 1) % 10;
7767 snprintf(nextmsg,
sizeof(nextmsg),
"digits/n-%d", vms->
curmsg + 1);
7770 snprintf(nextmsg,
sizeof(nextmsg),
"digits/n-%d", ten * 10);
7774 snprintf(nextmsg,
sizeof(nextmsg),
"digits/n-%d", one);
7783 }
else if (!strncasecmp(chan->
language,
"he", 2)) {
7796 }
else if (!strncasecmp(chan->
language,
"vi", 2)) {
7809 if (!strncasecmp(chan->
language,
"se", 2)) {
7810 res =
wait_file2(chan, vms,
"vm-meddelandet");
7840 if (!strncasecmp(
"macro", context, 5))
7887 static int imap_remove_file(
char *dir,
int msgnum)
7890 char full_fn[PATH_MAX];
7891 char intro[PATH_MAX] = {0,};
7895 snprintf(intro,
sizeof(intro),
"%sintro", fn);
7899 if ((msgnum < 0 && imapgreetings) || msgnum > -1) {
7904 snprintf(full_fn,
sizeof(full_fn),
"%s.txt", fn);
7912 static int imap_delete_old_greeting (
char *dir,
struct vm_state *vms)
7914 char *file, *filename;
7924 ast_log(
AST_LOG_ERROR,
"Failed to procure file name from directory passed. You should never see this.\n");
7929 for (i = 0; i < vms->mailstream->nmsgs; i++) {
7930 mail_fetchstructure(vms->mailstream, i + 1, &body);
7932 if (body->nested.part->next && body->nested.part->next->body.parameter->value) {
7933 attachment =
ast_strdupa(body->nested.part->next->body.parameter->value);
7939 filename =
strsep(&attachment,
".");
7940 if (!strcmp(filename, file)) {
7941 sprintf(arg,
"%d", i + 1);
7942 mail_setflag(vms->mailstream, arg,
"\\DELETED");
7945 mail_expunge(vms->mailstream);
7950 #elif !defined(IMAP_STORAGE)
7953 int count_msg, last_msg;
7967 if (count_msg < 0) {
7993 if (last_msg < -1) {
7995 }
else if (vms->
lastmsg != last_msg) {
7996 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);
8007 int last_msg_idx = 0;
8009 #ifndef IMAP_STORAGE
8010 int res = 0, nummsg;
8019 #ifndef IMAP_STORAGE
8027 if (last_msg_idx != vms->
lastmsg) {
8032 for (x = 0; x < last_msg_idx + 1; x++) {
8041 if (strcmp(vms->
fn, fn2)) {
8075 for (x = vms->
curmsg + 1; x <= nummsg; x++) {
8088 for (x = last_msg_idx - 1; x >= 0; x--) {
8129 if (!strcasecmp(box,
"vm-INBOX") || !strcasecmp(box,
"vm-Old")){
8142 if (!strcasecmp(box,
"vm-INBOX") || !strcasecmp(box,
"vm-Old")) {
8143 if (!strcasecmp(box,
"vm-INBOX"))
8158 if (!strcasecmp(box,
"vm-Family") || !strcasecmp(box,
"vm-Friends") || !strcasecmp(box,
"vm-Work")){
8171 if ( !strncasecmp(chan->
language,
"it", 2) ||
8172 !strncasecmp(chan->
language,
"es", 2) ||
8173 !strncasecmp(chan->
language,
"pt", 2)) {
8176 }
else if (!strncasecmp(chan->
language,
"gr", 2)) {
8178 }
else if (!strncasecmp(chan->
language,
"he", 2)) {
8180 }
else if (!strncasecmp(chan->
language,
"pl", 2)) {
8182 }
else if (!strncasecmp(chan->
language,
"ua", 2)) {
8184 }
else if (!strncasecmp(chan->
language,
"vi", 2)) {
8517 }
else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
8544 }
else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
9095 snprintf(prefile,
sizeof(prefile),
"%s%s/%s/temp", VM_SPOOL_DIR, vmu->
context, vms->
username);
9107 }
else if (!strncasecmp(chan->
language,
"cs", 2)) {
9109 }
else if (!strncasecmp(chan->
language,
"cz", 2)) {
9110 static int deprecation_warning = 0;
9111 if (deprecation_warning++ % 10 == 0) {
9112 ast_log(
LOG_WARNING,
"cz is not a standard language code. Please switch to using cs instead.\n");
9115 }
else if (!strncasecmp(chan->
language,
"de", 2)) {
9117 }
else if (!strncasecmp(chan->
language,
"es", 2)) {
9119 }
else if (!strncasecmp(chan->
language,
"fr", 2)) {
9121 }
else if (!strncasecmp(chan->
language,
"gr", 2)) {
9123 }
else if (!strncasecmp(chan->
language,
"he", 2)) {
9125 }
else if (!strncasecmp(chan->
language,
"it", 2)) {
9127 }
else if (!strncasecmp(chan->
language,
"nl", 2)) {
9129 }
else if (!strncasecmp(chan->
language,
"no", 2)) {
9131 }
else if (!strncasecmp(chan->
language,
"pl", 2)) {
9133 }
else if (!strncasecmp(chan->
language,
"pt_BR", 5)) {
9135 }
else if (!strncasecmp(chan->
language,
"pt", 2)) {
9137 }
else if (!strncasecmp(chan->
language,
"ru", 2)) {
9139 }
else if (!strncasecmp(chan->
language,
"se", 2)) {
9141 }
else if (!strncasecmp(chan->
language,
"ua", 2)) {
9143 }
else if (!strncasecmp(chan->
language,
"vi", 2)) {
9145 }
else if (!strncasecmp(chan->
language,
"zh", 2)) {
9189 if (!res && !skipadvanced)
9212 if (!curmsg_deleted) {
9279 char newpassword[80] =
"";
9280 char newpassword2[80] =
"";
9281 char prefile[PATH_MAX] =
"";
9282 unsigned char buf[256];
9297 snprintf(prefile,
sizeof(prefile),
"%s%s/%s/greet", VM_SPOOL_DIR, vmu->
context, vms->
username);
9299 cmd =
play_record_review(chan,
"vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
9300 if (cmd < 0 || cmd ==
't' || cmd ==
'#')
9307 snprintf(prefile,
sizeof(prefile),
"%s%s/%s/unavail", VM_SPOOL_DIR, vmu->
context, vms->
username);
9309 cmd =
play_record_review(chan,
"vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
9310 if (cmd < 0 || cmd ==
't' || cmd ==
'#')
9314 snprintf(prefile,
sizeof(prefile),
"%s%s/%s/busy", VM_SPOOL_DIR, vmu->
context, vms->
username);
9316 cmd =
play_record_review(chan,
"vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
9317 if (cmd < 0 || cmd ==
't' || cmd ==
'#')
9327 newpassword[1] =
'\0';
9330 newpassword[0] =
'\0';
9331 if (cmd < 0 || cmd ==
't' || cmd ==
'#')
9333 cmd =
ast_readstring(chan, newpassword + strlen(newpassword),
sizeof(newpassword) - 1, 2000, 10000,
"#");
9334 if (cmd < 0 || cmd ==
't' || cmd ==
'#')
9341 newpassword2[1] =
'\0';
9344 newpassword2[0] =
'\0';
9345 if (cmd < 0 || cmd ==
't' || cmd ==
'#')
9347 cmd =
ast_readstring(chan, newpassword2 + strlen(newpassword2),
sizeof(newpassword2) - 1, 2000, 10000,
"#");
9348 if (cmd < 0 || cmd ==
't' || cmd ==
'#')
9350 if (!strcmp(newpassword, newpassword2))
9366 ast_debug(1,
"User %s set password to %s of length %d\n", vms->
username, newpassword, (
int) strlen(newpassword));
9377 char newpassword[80] =
"";
9378 char newpassword2[80] =
"";
9379 char prefile[PATH_MAX] =
"";
9380 unsigned char buf[256];
9392 while ((cmd >= 0) && (cmd !=
't')) {
9397 snprintf(prefile,
sizeof(prefile),
"%s%s/%s/unavail", VM_SPOOL_DIR, vmu->
context, vms->
username);
9398 cmd =
play_record_review(chan,
"vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
9401 snprintf(prefile,
sizeof(prefile),
"%s%s/%s/busy", VM_SPOOL_DIR, vmu->
context, vms->
username);
9402 cmd =
play_record_review(chan,
"vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
9405 snprintf(prefile,
sizeof(prefile),
"%s%s/%s/greet", VM_SPOOL_DIR, vmu->
context, vms->
username);
9406 cmd =
play_record_review(chan,
"vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
9416 newpassword[1] =
'\0';
9419 newpassword[0] =
'\0';
9423 if ((cmd =
ast_readstring(chan, newpassword + strlen(newpassword),
sizeof(newpassword) - 1, 2000, 10000,
"#")) < 0) {
9436 newpassword2[1] =
'\0';
9439 newpassword2[0] =
'\0';
9444 if ((cmd =
ast_readstring(chan, newpassword2 + strlen(newpassword2),
sizeof(newpassword2) - 1, 2000, 10000,
"#")) < 0) {
9448 if (strcmp(newpassword, newpassword2)) {
9464 ast_debug(1,
"User %s set password to %s of length %d\n",
9465 vms->
username, newpassword, (
int) strlen(newpassword));
9473 snprintf(prefile,
sizeof(prefile),
"%s%s/%s/temp", VM_SPOOL_DIR, vmu->
context, vms->
username);
9520 char prefile[PATH_MAX] =
"";
9521 unsigned char buf[256];
9534 snprintf(prefile,
sizeof(prefile),
"%s%s/%s/temp", VM_SPOOL_DIR, vmu->
context, vms->
username);
9535 while ((cmd >= 0) && (cmd !=
't')) {
9540 cmd =
play_record_review(chan,
"vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
9548 cmd =
play_record_review(chan,
"vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL);
9551 DELETE(prefile, -1, prefile, vmu);
9561 "vm-tempgreeting2" :
"vm-tempgreeting");
9590 if (!strcasecmp(vms->
fn,
"INBOX")) {
9618 snprintf(vms->
fn,
sizeof(vms->
fn),
"vm-%s", vms->
curbox);
9644 if (!strcasecmp(vms->
vmbox,
"vm-INBOX") ||!strcasecmp(vms->
vmbox,
"vm-Old")){
9646 snprintf(vms->
fn,
sizeof(vms->
fn),
"vm-%ss", vms->
curbox);
9655 snprintf(vms->
fn,
sizeof(vms->
fn),
"vm-%s", vms->
curbox);
9684 snprintf(vms->
fn,
sizeof(vms->
fn),
"vm-%s", vms->
curbox);
9708 snprintf(vms->
fn,
sizeof(vms->
fn),
"vm-%s", vms->
curbox);
9728 if (!strncasecmp(chan->
language,
"es", 2) ||
9729 !strncasecmp(chan->
language,
"it", 2) ||
9730 !strncasecmp(chan->
language,
"pt", 2) ||
9731 !strncasecmp(chan->
language,
"gr", 2)) {
9733 }
else if (!strncasecmp(chan->
language,
"he", 2)) {
9735 }
else if (!strncasecmp(chan->
language,
"vi", 2)) {
9737 }
else if (!strncasecmp(chan->
language,
"zh", 2)) {
9746 int skipuser,
int max_logins,
int silent)
9748 int useadsi = 0, valid = 0, logretries = 0;
9754 if (!skipuser && useadsi)
9763 while (!valid && (logretries < max_logins)) {
9765 if (!skipuser &&
ast_readstring(chan, mailbox, mailbox_size - 1, 2000, 10000,
"#") < 0) {
9773 ast_verb(3,
"Username not entered\n");
9776 }
else if (mailbox[0] ==
'*') {
9778 ast_verb(4,
"Mailbox begins with '*', attempting jump to extension 'a'\n");
9783 ast_verb(4,
"Jump to extension 'a' failed; setting mailbox to NULL\n");
9791 char fullusername[80] =
"";
9793 strncat(fullusername, mailbox,
sizeof(fullusername) - 1 - strlen(fullusername));
9797 ast_debug(1,
"Before find user for mailbox %s\n", mailbox);
9798 vmu =
find_user(&vmus, context, mailbox);
9807 if (
ast_readstring(chan, password,
sizeof(password) - 1, 2000, 10000,
"#") < 0) {
9810 }
else if (password[0] ==
'*') {
9812 ast_verb(4,
"Password begins with '*', attempting jump to extension 'a'\n");
9818 ast_verb(4,
"Jump to extension 'a' failed; setting mailbox and user to NULL\n");
9827 if (passptr[0] ==
'-') passptr++;
9829 if (vmu && !strcmp(passptr, password))
9832 ast_verb(3,
"Incorrect password '%s' for user '%s' (context = %s)\n", password, mailbox, context ? context :
"default");
9838 if (skipuser || logretries >= max_logins) {
9855 if (!valid && (logretries >= max_logins)) {
9860 if (vmu && !skipuser) {
9874 char prefixstr[80] =
"";
9875 char ext_context[256]=
"";
9881 char *context = NULL;
9884 signed char record_gain = 0;
9886 int play_folder = 0;
9893 memset(&vms, 0,
sizeof(vms));
9897 memset(&vmus, 0,
sizeof(vmus));
9917 if (
args.argc == 2) {
9923 if (sscanf(opts[OPT_ARG_RECORDGAIN],
"%30d", &gain) != 1) {
9924 ast_log(
AST_LOG_WARNING,
"Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
9927 record_gain = (
signed char) gain;
9937 if (isdigit(opts[OPT_ARG_PLAYFOLDER][0])) {
9938 if (sscanf(opts[OPT_ARG_PLAYFOLDER],
"%30d", &play_folder) != 1) {
9947 if (play_folder > 9 || play_folder < 0) {
9949 "Invalid value '%s' provided for folder autoplay option. Defaulting to 'INBOX'\n",
9950 opts[OPT_ARG_PLAYFOLDER]);
9956 while (*(
args.argv0)) {
9957 if (*(
args.argv0) ==
's')
9959 else if (*(
args.argv0) ==
'p')
9970 if ((context = strchr(
args.argv0,
'@')))
9987 ast_debug(1,
"After vm_authenticate\n");
10017 #ifdef IMAP_STORAGE
10018 pthread_once(&ts_vmstate.once, ts_vmstate.key_init);
10019 pthread_setspecific(ts_vmstate.key, &vms);
10021 vms.interactive = 1;
10025 vmstate_insert(&vms);
10026 init_vm_state(&vms);
10100 cmd =
vm_newuser(chan, vmu, &vms, vmfmts, record_gain);
10101 if ((cmd ==
't') || (cmd ==
'#')) {
10106 }
else if (cmd < 0) {
10113 #ifdef IMAP_STORAGE
10114 ast_debug(3,
"Checking quotas: comparing %u to %u\n", vms.quota_usage, vms.quota_limit);
10115 if (vms.quota_limit && vms.quota_usage >= vms.quota_limit) {
10116 ast_debug(1,
"*** QUOTA EXCEEDED!!\n");
10136 while ((cmd > -1) && (cmd !=
't') && (cmd !=
'#')) {
10155 }
else if (cmd > 0) {
10161 if (cmd != 11) in_urgent = 0;
10182 while ((cmd > -1) && (cmd !=
't') && (cmd !=
'#')) {
10198 ast_verb(3,
"Callback Requested\n");
10240 cmd =
forward_message(chan, context, &vms, vmu, vmfmts, 1, record_gain, 0);
10311 ast_debug(1,
"No more new messages, opened INBOX and got %d Urgent messages\n", vms.
lastmsg + 1);
10342 ast_debug(1,
"No more urgent messages, opened INBOX and got %d new messages\n", vms.
lastmsg + 1);
10361 if (play_folder == 0) {
10368 else if (play_folder == 1)
10372 if (play_folder == 0) {
10379 else if (play_folder == 1)
10395 if (in_urgent == 1) {
10404 ast_debug(1,
"No more urgent messages, opened INBOX and got %d new messages\n", vms.
lastmsg + 1);
10416 #ifdef IMAP_STORAGE
10423 cmd =
forward_message(chan, context, &vms, vmu, vmfmts, 0, record_gain, in_urgent);
10442 ast_debug(1,
"No more urgent messages, opened INBOX and got %d new messages\n", vms.
lastmsg + 1);
10467 }
else if (cmd > 0) {
10468 box = cmd = cmd -
'0';
10473 #ifndef IMAP_STORAGE
10485 snprintf(vms.
fn,
sizeof(vms.
fn),
"vm-%s",
mbox(vmu, box));
10518 ast_debug(1,
"No more urgent messages, opened INBOX and got %d new messages\n", vms.
lastmsg + 1);
10532 if (!strncasecmp(chan->
language,
"he", 2)) {
10545 cmd =
vm_options(chan, vmu, &vms, vmfmts, record_gain);
10555 if ((cmd ==
't') || (cmd ==
'#')) {
10582 int new = 0, old = 0, urgent = 0;
10583 snprintf(ext_context,
sizeof(ext_context),
"%s@%s", vms.
username, vmu->
context);
10590 #ifdef IMAP_STORAGE
10592 ast_debug(3,
"*** Checking if we can expunge, deleted set to %d, expungeonhangup set to %d\n", deleted, expungeonhangup);
10593 if (vmu && deleted == 1 && expungeonhangup == 1 && vms.mailstream != NULL) {
10595 #ifdef HAVE_IMAP_TK2006
10596 if (LEVELUIDPLUS (vms.mailstream)) {
10597 mail_expunge_full(vms.mailstream, NIL, EX_UID);
10600 mail_expunge(vms.mailstream);
10606 vmstate_delete(&vms);
10612 #ifdef IMAP_STORAGE
10613 pthread_setspecific(ts_vmstate.key, NULL);
10630 memset(&leave_options, 0,
sizeof(leave_options));
10638 if (
args.argc == 2) {
10646 ast_log(
AST_LOG_WARNING,
"Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
10654 leave_options.
exitcontext = opts[OPT_ARG_DTMFEXIT];
10659 res =
ast_app_getdata(chan,
"vm-whichbox", temp,
sizeof(temp) - 1, 0);
10691 ast_log(
LOG_WARNING,
"Mailbox %s in context %s begins with '*' character. The '*' character,"
10692 "\n\twhen it is the first character in a mailbox or password, is used to jump to a"
10693 "\n\tpredefined extension 'a'. A mailbox or password beginning with '*' is not valid"
10694 "\n\tand will be ignored.\n", box, context);
10700 if (strcasecmp(vmu->
context, context)) {
10701 ast_log(
LOG_WARNING,
"\nIt has been detected that you have defined mailbox '%s' in separate\
10702 \n\tcontexts and that you have the 'searchcontexts' option on. This type of\
10703 \n\tconfiguration creates an ambiguity that you likely do not want. Please\
10704 \n\tamend your voicemail.conf file to avoid this situation.\n", box);
10709 if (!strcasecmp(context, vmu->
context) && !strcasecmp(box, vmu->
mailbox)) {
10710 ast_log(
LOG_WARNING,
"Ignoring duplicated mailbox %s in context %s\n", box, context);
10733 char *mailbox_full;
10734 int new = 0, old = 0, urgent = 0;
10735 char secretfn[PATH_MAX] =
"";
10745 if ((s =
strsep(&stringp,
","))) {
10748 "\n\tmust be reset in voicemail.conf.\n", box);
10753 if (stringp && (s =
strsep(&stringp,
","))) {
10756 if (stringp && (s =
strsep(&stringp,
","))) {
10759 if (stringp && (s =
strsep(&stringp,
","))) {
10762 if (stringp && (s =
strsep(&stringp,
","))) {
10768 snprintf(secretfn,
sizeof(secretfn),
"%s%s/%s/secret.conf", VM_SPOOL_DIR, vmu->
context, vmu->
mailbox);
10772 mailbox_full =
ast_alloca(strlen(box) + strlen(context) + 1);
10773 strcpy(mailbox_full, box);
10774 strcat(mailbox_full,
"@");
10775 strcat(mailbox_full, context);
10788 static const char options_string[] =
"attach=yes|attachfmt=wav49|"
10789 "serveremail=someguy@digium.com|tz=central|delete=yes|saycid=yes|"
10790 "sendvoicemail=yes|review=yes|tempgreetwarn=yes|messagewrap=yes|operator=yes|"
10791 "envelope=yes|moveheard=yes|sayduration=yes|saydurationm=5|forcename=yes|"
10792 "forcegreetings=yes|callback=somecontext|dialout=somecontext2|"
10793 "exitcontext=somecontext3|minsecs=10|maxsecs=100|nextaftercmd=yes|"
10794 "backupdeleted=50|volgain=1.3|passwordlocation=spooldir|emailbody="
10795 "Dear ${VM_NAME}:\n\n\tYou were just left a ${VM_DUR} long message|emailsubject="
10796 "[PBX]: New message \\\\${VM_MSGNUM}\\\\ in mailbox ${VM_MAILBOX}";
10797 #ifdef IMAP_STORAGE
10798 static const char option_string2[] =
"imapuser=imapuser|imappassword=imappasswd|"
10799 "imapfolder=INBOX|imapvmshareid=6000";
10804 info->name =
"vmuser";
10805 info->category =
"/apps/app_voicemail/";
10806 info->summary =
"Vmuser unit test";
10807 info->description =
10808 "This tests passing all supported parameters to apply_options, the voicemail user config parser";
10826 if (strcasecmp(vmu->
attachfmt,
"wav49")) {
10830 if (strcasecmp(vmu->
serveremail,
"someguy@digium.com")) {
10834 if (!vmu->
emailsubject || strcasecmp(vmu->
emailsubject,
"[PBX]: New message \\${VM_MSGNUM}\\ in mailbox ${VM_MAILBOX}")) {
10838 if (!vmu->
emailbody || strcasecmp(vmu->
emailbody,
"Dear ${VM_NAME}:\n\n\tYou were just left a ${VM_DUR} long message")) {
10842 if (strcasecmp(vmu->
zonetag,
"central")) {
10898 if (strcasecmp(vmu->
callback,
"somecontext")) {
10902 if (strcasecmp(vmu->
dialout,
"somecontext2")) {
10906 if (strcasecmp(vmu->
exit,
"somecontext3")) {
10934 #ifdef IMAP_STORAGE
10937 if (strcasecmp(vmu->imapuser,
"imapuser")) {
10941 if (strcasecmp(vmu->imappassword,
"imappasswd")) {
10945 if (strcasecmp(vmu->imapfolder,
"INBOX")) {
10949 if (strcasecmp(vmu->imapvmshareid,
"6000")) {
10967 static int dep_warning = 0;
10974 if (!dep_warning) {
10976 ast_log(
AST_LOG_WARNING,
"MailboxExists is deprecated. Please use ${MAILBOX_EXISTS(%s)} instead.\n", (
char *) data);
10983 if (
args.options) {
10986 if ((context = strchr(
args.mbox,
'@'))) {
11010 ast_log(
LOG_ERROR,
"MAILBOX_EXISTS requires an argument (<mailbox>[@<context>])\n");
11019 .
name =
"MAILBOX_EXISTS",
11027 char *options = NULL;
11028 int silent = 0, skipuser = 0;
11034 options =
strsep(&s,
",");
11038 context =
strsep(&s,
"");
11046 silent = (strchr(options,
's')) != NULL;
11049 if (!
vm_authenticate(chan, mailbox,
sizeof(mailbox), &vmus, context, NULL, skipuser, 3, silent)) {
11054 }
else if (mailbox[0] ==
'*') {
11067 const char *cat = NULL;
11076 "=============================================================\n"
11077 "=== Configured Voicemail Users ==============================\n"
11078 "=============================================================\n"
11084 "=== Mailbox ...\n"
11090 "=== ---------------------------------------------------------\n"
11095 "=============================================================\n"
11108 const char *context =
"";
11114 return (state == 0) ?
ast_strdup(
"for") : NULL;
11115 wordlen = strlen(word);
11117 if (!strncasecmp(word, vmu->
context, wordlen)) {
11118 if (context && strcmp(context, vmu->
context) && ++which > state)
11131 #define HVSU_OUTPUT_FORMAT "%-10s %-5s %-25s %-10s %6s\n"
11132 const char *context = NULL;
11133 int users_counter = 0;
11137 e->
command =
"voicemail show users";
11139 "Usage: voicemail show users [for <context>]\n"
11140 " Lists all mailboxes currently set up\n";
11148 if (a->
argc == 5) {
11149 if (strcmp(a->
argv[3],
"for"))
11151 context = a->
argv[4];
11156 ast_cli(a->
fd,
"You must specify a specific context to show users from realtime!\n");
11164 ast_cli(a->
fd,
"There are no voicemail users currently defined\n");
11173 if (!strcmp(context, vmu->
context)) {
11181 ast_cli(a->
fd,
"No such voicemail context \"%s\"\n", context);
11187 int newmsgs = 0, oldmsgs = 0;
11188 char count[12], tmp[256] =
"";
11190 if (!context || !strcmp(context, vmu->
context)) {
11193 snprintf(count,
sizeof(count),
"%d", newmsgs);
11199 ast_cli(a->
fd,
"%d voicemail users configured.\n", users_counter);
11206 struct vm_zone *zone;
11207 #define HVSZ_OUTPUT_FORMAT "%-15s %-20s %-45s\n"
11212 e->
command =
"voicemail show zones";
11214 "Usage: voicemail show zones\n"
11215 " Lists zone message formats\n";
11231 ast_cli(a->
fd,
"There are no voicemail zones currently defined\n");
11244 e->
command =
"voicemail reload";
11246 "Usage: voicemail reload\n"
11247 " Reload voicemail configuration\n";
11256 ast_cli(a->
fd,
"Reloading voicemail configuration...\n");
11268 #ifdef IMAP_STORAGE
11269 #define DATA_EXPORT_VM_USERS(USER) \
11270 USER(ast_vm_user, context, AST_DATA_STRING) \
11271 USER(ast_vm_user, mailbox, AST_DATA_STRING) \
11272 USER(ast_vm_user, password, AST_DATA_PASSWORD) \
11273 USER(ast_vm_user, fullname, AST_DATA_STRING) \
11274 USER(ast_vm_user, email, AST_DATA_STRING) \
11275 USER(ast_vm_user, emailsubject, AST_DATA_STRING) \
11276 USER(ast_vm_user, emailbody, AST_DATA_STRING) \
11277 USER(ast_vm_user, pager, AST_DATA_STRING) \
11278 USER(ast_vm_user, serveremail, AST_DATA_STRING) \
11279 USER(ast_vm_user, language, AST_DATA_STRING) \
11280 USER(ast_vm_user, zonetag, AST_DATA_STRING) \
11281 USER(ast_vm_user, callback, AST_DATA_STRING) \
11282 USER(ast_vm_user, dialout, AST_DATA_STRING) \
11283 USER(ast_vm_user, uniqueid, AST_DATA_STRING) \
11284 USER(ast_vm_user, exit, AST_DATA_STRING) \
11285 USER(ast_vm_user, attachfmt, AST_DATA_STRING) \
11286 USER(ast_vm_user, flags, AST_DATA_UNSIGNED_INTEGER) \
11287 USER(ast_vm_user, saydurationm, AST_DATA_INTEGER) \
11288 USER(ast_vm_user, maxmsg, AST_DATA_INTEGER) \
11289 USER(ast_vm_user, maxdeletedmsg, AST_DATA_INTEGER) \
11290 USER(ast_vm_user, maxsecs, AST_DATA_INTEGER) \
11291 USER(ast_vm_user, imapuser, AST_DATA_STRING) \
11292 USER(ast_vm_user, imappassword, AST_DATA_STRING) \
11293 USER(ast_vm_user, imapvmshareid, AST_DATA_STRING) \
11294 USER(ast_vm_user, volgain, AST_DATA_DOUBLE)
11296 #define DATA_EXPORT_VM_USERS(USER) \
11297 USER(ast_vm_user, context, AST_DATA_STRING) \
11298 USER(ast_vm_user, mailbox, AST_DATA_STRING) \
11299 USER(ast_vm_user, password, AST_DATA_PASSWORD) \
11300 USER(ast_vm_user, fullname, AST_DATA_STRING) \
11301 USER(ast_vm_user, email, AST_DATA_STRING) \
11302 USER(ast_vm_user, emailsubject, AST_DATA_STRING) \
11303 USER(ast_vm_user, emailbody, AST_DATA_STRING) \
11304 USER(ast_vm_user, pager, AST_DATA_STRING) \
11305 USER(ast_vm_user, serveremail, AST_DATA_STRING) \
11306 USER(ast_vm_user, language, AST_DATA_STRING) \
11307 USER(ast_vm_user, zonetag, AST_DATA_STRING) \
11308 USER(ast_vm_user, callback, AST_DATA_STRING) \
11309 USER(ast_vm_user, dialout, AST_DATA_STRING) \
11310 USER(ast_vm_user, uniqueid, AST_DATA_STRING) \
11311 USER(ast_vm_user, exit, AST_DATA_STRING) \
11312 USER(ast_vm_user, attachfmt, AST_DATA_STRING) \
11313 USER(ast_vm_user, flags, AST_DATA_UNSIGNED_INTEGER) \
11314 USER(ast_vm_user, saydurationm, AST_DATA_INTEGER) \
11315 USER(ast_vm_user, maxmsg, AST_DATA_INTEGER) \
11316 USER(ast_vm_user, maxdeletedmsg, AST_DATA_INTEGER) \
11317 USER(ast_vm_user, maxsecs, AST_DATA_INTEGER) \
11318 USER(ast_vm_user, volgain, AST_DATA_DOUBLE)
11323 #define DATA_EXPORT_VM_ZONES(ZONE) \
11324 ZONE(vm_zone, name, AST_DATA_STRING) \
11325 ZONE(vm_zone, timezone, AST_DATA_STRING) \
11326 ZONE(vm_zone, msg_format, AST_DATA_STRING)
11340 struct ast_data *data_user, *data_zone;
11342 struct vm_zone *zone = NULL;
11343 int urgentmsg = 0, newmsg = 0, oldmsg = 0;
11344 char ext_context[256] =
"";
11366 snprintf(ext_context,
sizeof(ext_context),
"%s@%s", user->
mailbox, user->
context);
11367 inboxcount2(ext_context, &urgentmsg, &newmsg, &oldmsg);
11404 AST_DATA_ENTRY(
"asterisk/application/voicemail/list", &vm_users_data_provider)
11409 int new = 0, old = 0, urgent = 0;
11411 inboxcount2(mwi_sub->mailbox, &urgent, &
new, &old);
11413 if (urgent != mwi_sub->old_urgent ||
new != mwi_sub->old_new || old != mwi_sub->old_old) {
11414 mwi_sub->old_urgent = urgent;
11415 mwi_sub->old_new =
new;
11416 mwi_sub->old_old = old;
11437 while (poll_thread_run) {
11438 struct timespec ts = { 0, };
11439 struct timeval wait;
11442 ts.tv_sec = wait.tv_sec;
11443 ts.tv_nsec = wait.tv_usec * 1000;
11449 if (!poll_thread_run)
11466 uint32_t *uniqueid = datap;
11470 if (mwi_sub->uniqueid == *uniqueid) {
11491 len =
sizeof(*mwi_sub);
11496 len += strlen(p->
context) + 1;
11503 strcpy(mwi_sub->mailbox, p->
mailbox);
11506 strcat(mwi_sub->mailbox,
"@");
11507 strcat(mwi_sub->mailbox, p->
context);
11556 if ((mwist =
ast_calloc(1, (
sizeof(*mwist)))) == NULL) {
11583 poll_thread_run = 1;
11592 poll_thread_run = 0;
11596 mwi_sub_sub = NULL;
11599 if (mwi_unsub_sub) {
11601 mwi_unsub_sub = NULL;
11608 pthread_join(poll_thread, NULL);
11618 char actionid[128] =
"";
11621 snprintf(actionid,
sizeof(actionid),
"ActionID: %s\r\n",
id);
11626 astman_send_ack(s, m,
"There are no voicemail users currently defined.");
11636 #ifdef IMAP_STORAGE
11644 "Event: VoicemailUserEntry\r\n"
11645 "VMContext: %s\r\n"
11646 "VoiceMailbox: %s\r\n"
11650 "ServerEmail: %s\r\n"
11651 "MailCommand: %s\r\n"
11657 "ExitContext: %s\r\n"
11658 "SayDurationMinimum: %d\r\n"
11659 "SayEnvelope: %s\r\n"
11661 "AttachMessage: %s\r\n"
11662 "AttachmentFormat: %s\r\n"
11663 "DeleteMessage: %s\r\n"
11664 "VolumeGain: %.2f\r\n"
11665 "CanReview: %s\r\n"
11666 "CallOperator: %s\r\n"
11667 "MaxMessageCount: %d\r\n"
11668 "MaxMessageLength: %d\r\n"
11669 "NewMessageCount: %d\r\n"
11670 #ifdef IMAP_STORAGE
11671 "OldMessageCount: %d\r\n"
11700 #ifdef IMAP_STORAGE
11701 new, old, vmu->imapuser
11707 astman_append(s,
"Event: VoicemailUserEntryComplete\r\n%s\r\n", actionid);
11729 struct vm_zone *zcur;
11746 for (current = (
char *) value; *current; current++) {
11747 if (*current ==
'\\') {
11753 switch (*current) {
11761 #ifdef IMAP_STORAGE
11762 if (!str->used || str->str[str->used - 1] !=
'\r') {
11796 ast_log(
LOG_ERROR,
"Config file users.conf is in an invalid format. Avoiding.\n");
11811 ast_log(
LOG_ERROR,
"Config file users.conf is in an invalid format. Avoiding.\n");
11824 #ifdef TEST_FRAMEWORK
11839 char *q, *stringp, *tmp;
11841 unsigned int tmpadsi[4];
11842 char secretfn[PATH_MAX] =
"";
11844 #ifdef IMAP_STORAGE
11862 memset(ext_pass_cmd, 0,
sizeof(ext_pass_cmd));
11863 memset(ext_pass_check_cmd, 0,
sizeof(ext_pass_check_cmd));
11882 sscanf(val,
"%30lf", &volgain);
11884 #ifdef ODBC_STORAGE
11885 strcpy(odbc_database,
"asterisk");
11889 strcpy(odbc_table,
"voicemessages");
11901 maxsilence = atoi(val);
11902 if (maxsilence > 0)
11903 maxsilence *= 1000;
11909 maxmsg = atoi(val);
11922 if (sscanf(val,
"%30d", &x) == 1)
11929 if (maxdeletedmsg < 0) {
11959 ast_copy_string(ext_pass_check_cmd, val,
sizeof(ext_pass_check_cmd));
11963 #ifdef IMAP_STORAGE
11991 expungeonhangup = 0;
11993 expungeonhangup = 1;
11995 expungeonhangup = 1;
12025 mail_parameters(NIL, SET_READTIMEOUT, (
void *) (atol(val)));
12027 mail_parameters(NIL, SET_READTIMEOUT, (
void *) 60L);
12031 mail_parameters(NIL, SET_WRITETIMEOUT, (
void *) (atol(val)));
12033 mail_parameters(NIL, SET_WRITETIMEOUT, (
void *) 60L);
12037 mail_parameters(NIL, SET_OPENTIMEOUT, (
void *) (atol(val)));
12039 mail_parameters(NIL, SET_OPENTIMEOUT, (
void *) 60L);
12043 mail_parameters(NIL, SET_CLOSETIMEOUT, (
void *) (atol(val)));
12045 mail_parameters(NIL, SET_CLOSETIMEOUT, (
void *) 60L);
12054 ast_debug(1,
"found externnotify: %s\n", externnotify);
12056 externnotify[0] =
'\0';
12061 ast_debug(1,
"Enabled SMDI voicemail notification\n");
12065 ast_debug(1,
"No SMDI interface set, trying default (/dev/ttyS0)\n");
12069 ast_log(
AST_LOG_ERROR,
"No valid SMDI interface specfied, disabling SMDI voicemail notification\n");
12076 silencethreshold = atoi(val);
12084 if (sscanf(val,
"%30d", &x) == 1) {
12090 static int maxmessage_deprecate = 0;
12091 if (maxmessage_deprecate == 0) {
12092 maxmessage_deprecate = 1;
12095 if (sscanf(val,
"%30d", &x) == 1) {
12104 if (sscanf(val,
"%30d", &x) == 1) {
12106 if (maxsilence / 1000 >= vmminsecs) {
12113 static int maxmessage_deprecate = 0;
12114 if (maxmessage_deprecate == 0) {
12115 maxmessage_deprecate = 1;
12118 if (sscanf(val,
"%30d", &x) == 1) {
12120 if (maxsilence / 1000 >= vmminsecs) {
12135 ast_log(
LOG_ERROR,
"Error processing format string, defaulting to format 'wav'\n");
12143 if (sscanf(val,
"%30d", &x) == 1) {
12151 if (sscanf(val,
"%30d", &x) == 1) {
12160 if (sscanf(val,
"%30d", &x) == 1) {
12169 if (sscanf(val,
"%30d", &x) == 1) {
12187 ast_debug(1,
"VM_CID Internal context string: %s\n", val);
12191 q =
strsep(&stringp,
",");
12192 while ((*q ==
' ')||(*q ==
'\t'))
12194 ast_copy_string(cidinternalcontexts[x], q,
sizeof(cidinternalcontexts[x]));
12195 ast_debug(1,
"VM_CID Internal context %d: %s\n", x, cidinternalcontexts[x]);
12197 cidinternalcontexts[x][0] =
'\0';
12202 ast_debug(1,
"VM Review Option disabled globally\n");
12209 ast_debug(1,
"VM Temporary Greeting Reminder Option disabled globally\n");
12212 ast_debug(1,
"VM Temporary Greeting Reminder Option enabled globally\n");
12216 ast_debug(1,
"VM next message wrap disabled globally\n");
12222 ast_debug(1,
"VM Operator break disabled globally\n");
12228 ast_debug(1,
"VM CID Info before msg disabled globally\n");
12234 ast_debug(1,
"Send Voicemail msg disabled globally\n");
12240 ast_debug(1,
"ENVELOPE before msg enabled globally\n");
12246 ast_debug(1,
"Move Heard enabled globally\n");
12252 ast_debug(1,
"Autoset of Urgent flag on forwarded Urgent messages disabled globally\n");
12258 ast_debug(1,
"Duration info before msg enabled globally\n");
12263 saydurationminfo = 2;
12265 if (sscanf(val,
"%30d", &x) == 1) {
12266 saydurationminfo = x;
12273 ast_debug(1,
"We are not going to skip to the next msg after save/delete\n");
12280 ast_debug(1,
"found dialout context: %s\n", dialcontext);
12282 dialcontext[0] =
'\0';
12287 ast_debug(1,
"found callback context: %s\n", callcontext);
12289 callcontext[0] =
'\0';
12294 ast_debug(1,
"found operator context: %s\n", exitcontext);
12296 exitcontext[0] =
'\0';
12305 ast_copy_string(vm_invalid_password, val,
sizeof(vm_invalid_password));
12309 ast_copy_string(vm_reenterpassword, val,
sizeof(vm_reenterpassword));
12316 ast_copy_string(vm_prepend_timeout, val,
sizeof(vm_prepend_timeout));
12320 ast_copy_string(listen_control_forward_key, val,
sizeof(listen_control_forward_key));
12322 ast_copy_string(listen_control_reverse_key, val,
sizeof(listen_control_reverse_key));
12324 ast_copy_string(listen_control_pause_key, val,
sizeof(listen_control_pause_key));
12326 ast_copy_string(listen_control_restart_key, val,
sizeof(listen_control_restart_key));
12328 ast_copy_string(listen_control_stop_key, val,
sizeof(listen_control_stop_key));
12335 val =
"voicemail.conf";
12337 if (!(strcmp(val,
"spooldir"))) {
12345 if (sscanf(val,
"%30u", &poll_freq) != 1) {
12351 poll_mailboxes = 0;
12355 memset(fromstring, 0,
sizeof(fromstring));
12356 memset(pagerfromstring, 0,
sizeof(pagerfromstring));
12357 strcpy(charset,
"ISO-8859-1");
12362 if (emailsubject) {
12364 emailsubject = NULL;
12370 if (pagersubject) {
12372 pagersubject = NULL;
12383 sscanf(val,
"%2x%2x%2x%2x", &tmpadsi[0], &tmpadsi[1], &tmpadsi[2], &tmpadsi[3]);
12384 for (x = 0; x < 4; x++) {
12385 memcpy(&adsifdn[x], &tmpadsi[x], 1);
12389 sscanf(val,
"%2x%2x%2x%2x", &tmpadsi[0], &tmpadsi[1], &tmpadsi[2], &tmpadsi[3]);
12390 for (x = 0; x < 4; x++) {
12391 memcpy(&adsisec[x], &tmpadsi[x], 1);
12396 adsiver = atoi(val);
12421 if (!strcasecmp(cat,
"general")) {
12436 snprintf(secretfn,
sizeof(secretfn),
"%s%s/%s/secret.conf", VM_SPOOL_DIR, current->
context, current->
mailbox);
12446 if (strcasecmp(cat,
"general")) {
12448 if (strcasecmp(cat,
"zonemessages")) {
12461 tzone =
strsep(&msg_format,
"|,");
12502 char dir[PATH_MAX];
12503 snprintf(dir,
sizeof(dir),
"%s%s/%s/greet", VM_SPOOL_DIR, context, mailbox);
12504 ast_debug(2,
"About to try retrieving name file %s\n", dir);
12505 RETRIEVE(dir, -1, mailbox, context);
12527 ast_log(
LOG_NOTICE,
"Failed reading voicemail password from %s, using secret from config file\n", secretfn);
12575 if ((context = strchr(args_copy,
'@'))) {
12578 context =
"default";
12581 if ((res =
sayname(chan, args_copy, context) < 0)) {
12582 ast_debug(3,
"Greeting not found for '%s@%s', falling back to mailbox number.\n", args_copy, context);
12592 #ifdef TEST_FRAMEWORK
12605 char dir[PATH_MAX];
12606 char dir2[PATH_MAX];
12607 static const char TEST_CONTEXT[] =
"very_long_unique_context_so_that_nobody_will_ever_have_the_same_one_configured_3141592653";
12608 static const char TEST_EXTENSION[] =
"1234";
12614 .
write = fake_write,
12620 info->name =
"vmsayname_exec";
12621 info->category =
"/apps/app_voicemail/";
12622 info->summary =
"Vmsayname unit test";
12623 info->description =
12624 "This tests passing various parameters to vmsayname";
12631 NULL, NULL, 0, 0,
"TestChannel1"))) {
12632 goto exit_vmsayname_test;
12641 test_channel1->
tech = &fake_tech;
12644 snprintf(dir,
sizeof(dir),
"%s@%s", TEST_EXTENSION, TEST_CONTEXT);
12646 snprintf(dir,
sizeof(dir),
"%s%s/%s/greet", VM_SPOOL_DIR, TEST_CONTEXT, TEST_EXTENSION);
12648 ast_test_status_update(test,
"This should not happen, most likely means clean up from previous test failed\n");
12650 goto exit_vmsayname_test;
12653 if ((res =
create_dirpath(dir,
sizeof(dir), TEST_CONTEXT, TEST_EXTENSION,
""))) {
12655 goto exit_vmsayname_test;
12658 snprintf(dir2,
sizeof(dir2),
"%s%s/%s/greet.gsm", VM_SPOOL_DIR, TEST_CONTEXT, TEST_EXTENSION);
12660 if ((res = symlink(dir, dir2))) {
12662 goto exit_vmsayname_test;
12665 snprintf(dir,
sizeof(dir),
"%s@%s", TEST_EXTENSION, TEST_CONTEXT);
12670 snprintf(dir2,
sizeof(dir2),
"%s%s/%s", VM_SPOOL_DIR, TEST_CONTEXT, TEST_EXTENSION);
12672 snprintf(dir2,
sizeof(dir2),
"%s%s", VM_SPOOL_DIR, TEST_CONTEXT);
12677 exit_vmsayname_test:
12679 if (test_channel1) {
12692 #ifdef IMAP_STORAGE
12701 const char origweasels[] =
"tt-weasels";
12702 const char testcontext[] =
"test";
12703 const char testmailbox[] =
"00000000";
12704 const char testspec[] =
"00000000@test";
12706 int new, old, urgent;
12707 const char *folders[3] = {
"Old",
"Urgent",
"INBOX" };
12708 const int folder2mbox[3] = { 1, 11, 0 };
12709 const int expected_results[3][12] = {
12711 { 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0 },
12712 { 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1 },
12713 { 1, 1, 1, 1, 0, 2, 1, 1, 1, 1, 1, 2 },
12718 info->name =
"test_voicemail_msgcount";
12719 info->category =
"/apps/app_voicemail/";
12720 info->summary =
"Test Voicemail status checks";
12721 info->description =
12722 "Verify that message counts are correct when retrieved through the public API";
12729 snprintf(syscmd,
sizeof(syscmd),
"rm -rf \"%s%s/%s\"", VM_SPOOL_DIR, testcontext, testmailbox);
12732 syserr > 0 ? strerror(syserr) :
"unable to fork()");
12736 #ifdef IMAP_STORAGE
12743 if (!(vmu =
find_user(&svm, testcontext, testmailbox)) &&
12747 #ifdef IMAP_STORAGE
12754 memset(&vms, 0,
sizeof(vms));
12757 for (i = 0; i < 3; i++) {
12758 create_dirpath(tmp[i].dir,
sizeof(tmp[i].dir), testcontext, testmailbox, folders[i]);
12759 make_file(tmp[i].file,
sizeof(tmp[i].file), tmp[i].dir, 0);
12760 snprintf(tmp[i].txtfile,
sizeof(tmp[i].txtfile),
"%s.txt", tmp[i].file);
12763 snprintf(syscmd,
sizeof(syscmd),
"cp \"%s/sounds/en/%s.gsm\" \"%s/%s/%s/%s/msg0000.gsm\"",
ast_config_AST_DATA_DIR, origweasels,
12764 VM_SPOOL_DIR, testcontext, testmailbox, folders[i]);
12767 syserr > 0 ? strerror(syserr) :
"unable to fork()");
12769 #ifdef IMAP_STORAGE
12776 if ((txt = fopen(tmp[i].txtfile,
"w+"))) {
12777 fprintf(txt,
"; just a stub\n[message]\nflag=%s\n", strcmp(folders[i],
"Urgent") ?
"" :
"Urgent");
12785 STORE(tmp[i].dir, testmailbox, testcontext, 0, chan, vmu,
"gsm", 600, &vms, strcmp(folders[i],
"Urgent") ?
"" :
"Urgent");
12788 for (j = 0; j < 3; j++) {
12797 new = old = urgent = 0;
12801 }
else if (old != expected_results[i][3 + 0] ||
new != expected_results[i][3 + 2]) {
12803 testspec, old, expected_results[i][3 + 0],
new, expected_results[i][3 + 2]);
12807 new = old = urgent = 0;
12811 }
else if (old != expected_results[i][6 + 0] ||
12812 urgent != expected_results[i][6 + 1] ||
12813 new != expected_results[i][6 + 2] ) {
12814 ast_test_status_update(test,
"inboxcount2(%s) returned old=%d (expected %d), urgent=%d (expected %d), and new=%d (expected %d)\n",
12815 testspec, old, expected_results[i][6 + 0], urgent, expected_results[i][6 + 1],
new, expected_results[i][6 + 2]);
12819 new = old = urgent = 0;
12820 for (j = 0; j < 3; j++) {
12821 if (
ast_app_messagecount(testcontext, testmailbox, folders[j]) != expected_results[i][9 + j]) {
12823 testspec, folders[j],
ast_app_messagecount(testcontext, testmailbox, folders[j]), expected_results[i][9 + j]);
12829 for (i = 0; i < 3; i++) {
12833 DELETE(tmp[i].dir, 0, tmp[i].file, vmu);
12844 #ifdef IMAP_STORAGE
12849 snprintf(syscmd,
sizeof(syscmd),
"rm -rf \"%s%s/%s\"", VM_SPOOL_DIR, testcontext, testmailbox);
12852 syserr > 0 ? strerror(syserr) :
"unable to fork()");
12861 char testcontext[] =
"test";
12862 char testmailbox[] =
"00000000";
12863 char from[] =
"test@example.net", cidnum[] =
"1234", cidname[] =
"Mark Spencer", format[] =
"gsm";
12864 char attach[256], attach2[256];
12865 char buf[256] =
"";
12873 enum { INT, FLAGVAL, STATIC, STRPTR }
type;
12880 {
"plain jane config", STATIC, vmus.
password, .u.strval =
"1234" },
12881 {
"emailsubject", STRPTR, vmus.
emailsubject, .u.strval =
"Oogly boogly\xf8koogly with what appears to be UTF-8" },
12882 {
"emailbody", STRPTR, vmus.
emailbody, .u.strval =
"This is a test\n\twith multiple\nlines\nwithin\n" },
12883 {
"serveremail", STATIC, vmus.
serveremail, .u.strval =
"\"\xf8Something\xe8that\xd8seems to have UTF-8 chars\" <test@example.net>" },
12884 {
"attachment flag", FLAGVAL, &vmus.
flags, .u.intval =
VM_ATTACH },
12885 {
"attach2", STRPTR, attach2, .u.strval =
"" },
12886 {
"attach", STRPTR, attach, .u.strval =
"" },
12892 info->name =
"test_voicemail_notify_endl";
12893 info->category =
"/apps/app_voicemail/";
12894 info->summary =
"Test Voicemail notification end-of-line";
12895 info->description =
12896 "Verify that notification emails use a consistent end-of-line character";
12905 if (!(vmu =
find_user(&vmus, testcontext, testmailbox)) &&
12911 if (vmu != &vmus && !(vmu =
find_user(&vmus, testcontext, testmailbox))) {
12918 #ifdef IMAP_STORAGE
12923 for (which = 0; which <
ARRAY_LEN(test_items); which++) {
12926 if (ftruncate(fileno(file), 0)) {
12933 if (test_items[which].
type == INT) {
12934 *((
int *) test_items[which].location) = test_items[which].u.intval;
12935 }
else if (test_items[which].
type == FLAGVAL) {
12941 }
else if (test_items[which].
type == STATIC) {
12942 strcpy(test_items[which].location, test_items[which].u.strval);
12943 }
else if (test_items[which].
type == STRPTR) {
12944 test_items[which].location = test_items[which].u.strval;
12947 make_email_file(file, from, vmu, 0, testcontext, testmailbox,
"INBOX", cidnum, cidname, attach, attach2, format, 999, 1, chan, NULL, 0, NULL);
12949 while (fgets(buf,
sizeof(buf), file)) {
12951 #ifdef IMAP_STORAGE
12952 buf[strlen(buf) - 2] !=
'\r'
12954 buf[strlen(buf) - 2] ==
'\r'
12956 || buf[strlen(buf) - 1] !=
'\n') {
12970 char config_filename[32] =
"/tmp/voicemail.conf.XXXXXX";
12977 info->name =
"test_voicemail_load_config";
12978 info->category =
"/apps/app_voicemail/";
12979 info->summary =
"Test loading Voicemail config";
12980 info->description =
12981 "Verify that configuration is loaded consistently. "
12982 "This is to test regressions of ASTERISK-18838 where it was noticed that "
12983 "some options were loaded after the mailboxes were instantiated, causing "
12984 "those options not to be set correctly.";
12991 if ((fd = mkstemp(config_filename)) < 0) {
12994 if (!(file = fdopen(fd,
"w"))) {
12996 unlink(config_filename);
12999 fputs(
"[general]\ncallback=somecontext\nlocale=de_DE.UTF-8\ntz=european\n[test]", file);
13000 fputs(
"00000001 => 9999,Mr. Test,,,callback=othercontext|locale=nl_NL.UTF-8|tz=central\n", file);
13001 fputs(
"00000002 => 9999,Mrs. Test\n", file);
13009 load_config_from_memory(1, cfg, NULL);
13012 #define CHECK(u, attr, value) else if (strcmp(u->attr, value)) { \
13013 ast_test_status_update(test, "mailbox %s should have %s '%s', but has '%s'\n", \
13014 u->mailbox, #attr, value, u->attr); res = AST_TEST_FAIL; break; }
13018 if (!strcmp(vmu->
mailbox,
"00000001")) {
13020 CHECK(vmu, callback,
"othercontext")
13021 CHECK(vmu, locale, "nl_NL.UTF-8")
13022 CHECK(vmu, zonetag, "central")
13023 }
else if (!strcmp(vmu->mailbox, "00000002")) {
13025 CHECK(vmu, callback,
"somecontext")
13026 CHECK(vmu, locale, "de_DE.UTF-8")
13027 CHECK(vmu, zonetag, "european")
13038 unlink(config_filename);
13061 #ifdef TEST_FRAMEWORK
13070 ao2_ref(inprocess_container, -1);
13087 my_umask = umask(0);
13111 #ifdef TEST_FRAMEWORK
13135 char destination[80] =
"";
13139 ast_verb(3,
"Destination number will be entered manually\n");
13140 while (retries < 3 && cmd !=
't') {
13141 destination[1] =
'\0';
13150 destination[0] = cmd;
13159 ast_verb(3,
"User hit '*' to cancel outgoing call\n");
13162 if ((cmd =
ast_readstring(chan, destination + strlen(destination),
sizeof(destination) - 1, 6000, 10000,
"#")) < 0)
13169 if (retries >= 3) {
13180 if (destination[strlen(destination) -1 ] ==
'*')
13208 char filename[PATH_MAX];
13210 const char *origtime, *
context;
13221 snprintf(filename,
sizeof(filename),
"%s.txt", vms->
fn);
13238 if (!strncasecmp(
"macro", context, 5))
13256 while ((res > -1) && (res !=
't')) {
13280 ast_verb(3,
"Caller can not specify callback number - no dialout context available\n");
13302 ast_verb(3,
"Confirm CID number '%s' is number to use for callback\n", num);
13338 else if (res ==
'*')
13350 ast_verb(3,
"No CID number available, no reply sent\n");
13360 snprintf(mailbox,
sizeof(mailbox),
"%s@%s", num, vmu->
context);
13362 ast_verb(3,
"Leaving voicemail for '%s' in context '%s'\n", num, vmu->
context);
13364 memset(&leave_options, 0,
sizeof(leave_options));
13373 ast_verb(3,
"No mailbox number '%s' in context '%s', no reply sent\n", num, vmu->
context);
13387 #ifndef IMAP_STORAGE
13390 vms->
heard[msg] = 1;
13398 int outsidecaller,
struct ast_vm_user *vmu,
int *duration,
int *sound_duration,
const char *unlockdir,
13404 int max_attempts = 3;
13407 int msg_exists = 0;
13408 signed char zero_gain = 0;
13409 char tempfile[PATH_MAX];
13411 char *canceldtmf =
"";
13412 int canceleddtmf = 0;
13417 if (duration == NULL) {
13422 if (!outsidecaller)
13423 snprintf(tempfile,
sizeof(tempfile),
"%s.tmp", recordfile);
13429 while ((cmd >= 0) && (cmd !=
't')) {
13438 ast_verb(3,
"Saving message as is\n");
13439 if (!outsidecaller)
13442 if (!outsidecaller) {
13452 ast_verb(3,
"Reviewing the message\n");
13459 ast_verb(3,
"Re-recording the message\n");
13461 ast_verb(3,
"Recording the message\n");
13463 if (recorded && outsidecaller) {
13473 cmd =
ast_play_and_record_full(chan, playfile, tempfile, maxtime, fmt, duration, sound_duration, silencethreshold, maxsilence, unlockdir, acceptdtmf, canceldtmf);
13474 if (strchr(canceldtmf, cmd)) {
13482 if (!outsidecaller) {
13490 }
else if (cmd ==
'*') {
13493 }
else if (vmu->review && sound_duration && (*sound_duration < 5)) {
13495 ast_verb(3,
"Message too short\n");
13499 }
else if (vmu->review && (cmd == 2 && sound_duration && *sound_duration < (maxsilence + 3))) {
13501 ast_verb(3,
"Nothing recorded\n");
13515 if (outsidecaller) {
13520 strcpy(flag,
"Urgent");
13549 if (outsidecaller) {
13561 if (msg_exists || recorded) {
13569 }
else if (cmd ==
'4') {
13572 strcpy(flag,
"Urgent");
13578 DELETE(tempfile, -1, tempfile, vmu);
13591 if (!cmd && outsidecaller) {
13618 if (attempts > max_attempts) {
13623 if (!outsidecaller && (cmd == -1 || cmd ==
't')) {
13628 if (cmd !=
't' && outsidecaller)
13642 .nonoptreq =
"res_adsi,res_smdi",
int ast_filecopy(const char *oldname, const char *newname, const char *fmt)
Copies a file.
#define AST_THREADSTORAGE(name)
Define a thread storage variable.
int ast_hangup(struct ast_channel *chan)
Hang up a channel.
static int saydurationminfo
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)
#define ast_channel_lock(chan)
static int vm_intro_nl(struct ast_channel *chan, struct vm_state *vms)
static char exten[AST_MAX_EXTENSION]
static char userscontext[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 int resequence_mailbox(struct ast_vm_user *vmu, char *dir, int stopcount)
#define AST_CLI_DEFINE(fn, txt,...)
static char * vm_check_password_shell(char *command, char *buf, size_t len)
char * str
Subscriber phone number (Malloced)
static void adsi_status(struct ast_channel *chan, struct vm_state *vms)
#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.
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 void free_vm_zones(void)
Free the zones structure.
static char ext_pass_cmd[128]
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 const char * substitute_escapes(const char *value)
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)
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 int load_config(int reload)
The data tree to be returned by the callbacks and managed by functions local to this file...
static void apply_options_full(struct ast_vm_user *retval, struct ast_variable *var)
Loads the options specific to a voicemail user.
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.
char * strsep(char **str, const char *delims)
struct ast_app * pbx_findapp(const char *app)
Look up an application.
static FILE * vm_mkftemp(char *template)
#define DEFAULT_LISTEN_CONTROL_REVERSE_KEY
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 MAX_NUM_CID_CONTEXTS
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized...
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.
int pbx_exec(struct ast_channel *c, struct ast_app *app, const char *data)
Execute an application.
static void rename_file(char *sfn, char *dfn)
Renames a message in a mailbox folder.
enum ast_event_type ast_event_get_type(const struct ast_event *event)
Get the type for an event.
static int vm_play_folder_name(struct ast_channel *chan, char *mbox)
static unsigned char adsifdn[4]
static int vm_instructions_en(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int skipadvanced, int in_urgent)
static int manager_list_voicemail_users(struct mansession *s, const struct message *m)
Manager list voicemail users command.
int ast_adsi_data_mode(unsigned char *buf)
Puts CPE in data mode.
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)
static void free_vm_users(void)
Free the users structure.
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
static int vm_instructions_zh(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int skipadvanced, int in_urgent)
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
#define ast_channel_unref(c)
Decrease channel reference count.
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 create_dirpath(char *dest, int len, const char *context, const char *ext, const char *folder)
basically mkdir -p $dest/$context/$ext/$folder
#define ast_set2_flag(p, value, flag)
#define ast_test_flag(p, flag)
static char pagerdateformat[32]
int ast_unload_realtime(const char *family)
Release any resources cached for a realtime family.
static int adsi_logo(unsigned char *buf)
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...
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)
#define SMDI_MWI_WAIT_TIMEOUT
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]
static int inprocess_cmp_fn(void *obj, void *arg, int flags)
static int handle_subscribe(void *datap)
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.
#define ast_set_flag(p, flag)
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.
int ast_event_queue_and_cache(struct ast_event *event)
Queue and cache an event.
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.
void ast_event_report_subs(const struct ast_event_sub *sub)
Report current subscriptions to a subscription subscriber.
descriptor for a cli entry.
static int sayname(struct ast_channel *chan, const char *mailbox, const char *context)
int ast_update2_realtime(const char *family,...) attribute_sentinel
Update realtime configuration.
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
static struct ast_data_handler vm_users_data_provider
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category)
Goes through variables.
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.
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]
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 int vm_intro_de(struct ast_channel *chan, struct vm_state *vms)
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.
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).
static void adsi_status2(struct ast_channel *chan, struct vm_state *vms)
static void copy_plain_file(char *frompath, char *topath)
Copies a voicemail information (envelope) file.
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.
#define DATA_EXPORT_VM_USERS(USER)
This entries are for multiple registers.
Structure for variables, used for configurations and for channel variables.
static unsigned char adsisec[4]
static int vm_intro_pt(struct ast_channel *chan, struct vm_state *vms)
static int count_messages(struct ast_vm_user *vmu, char *dir)
Find all .txt files - even if they are not in sequence from 0000.
#define DEFAULT_LISTEN_CONTROL_FORWARD_KEY
int ast_adsi_set_keys(unsigned char *buf, unsigned char *keys)
Set which soft keys should be displayed.
static struct ast_data_entry vm_data_providers[]
#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)
static int vm_intro_it(struct ast_channel *chan, struct vm_state *vms)
static int actual_load_config(int reload, struct ast_config *cfg, struct ast_config *ucfg)
static int vm_box_exists(struct ast_channel *chan, const char *data)
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)
Configuration File Parser.
int ast_adsi_download_disconnect(unsigned char *buf)
Disconnects (and hopefully saves) a downloaded script.
char * str
Subscriber name (Malloced)
static void adsi_login(struct ast_channel *chan)
static pthread_t poll_thread
static int close_mailbox(struct vm_state *vms, struct ast_vm_user *vmu)
int ast_config_text_file_save(const char *filename, const struct ast_config *cfg, const char *generator)
struct ast_variable * ast_load_realtime(const char *family,...) attribute_sentinel
Retrieve realtime configuration.
static char listen_control_reverse_key[12]
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
static struct ast_threadstorage buf2
static int copy(char *infile, char *outfile)
Utility function to copy a file.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
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.
Number of Used by: AST_EVENT_MWI Payload type: UINT.
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
#define ast_mutex_lock(a)
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 ...
unsigned char iobuf[BASEMAXINLINE]
static int get_folder_by_name(const char *name)
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
#define ast_copy_flags(dest, src, flagz)
#define ast_str_alloca(init_len)
static int vm_allocate_dh(struct vm_state *vms, struct ast_vm_user *vmu, int count_msg)
static int unload_module(void)
const char * ast_config_option(struct ast_config *cfg, const char *cat, const char *var)
Retrieve a configuration variable within the configuration set.
static int check_mime(const char *str)
Check if the string would need encoding within the MIME standard, to avoid confusing certain mail sof...
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 ast_cond_t poll_cond
static char externnotify[160]
static int inprocess_count(const char *context, const char *mailbox, int delta)
static int handle_unsubscribe(void *datap)
static int inbuf(struct baseio *bio, FILE *fi)
utility used by inchar(), for base_encode()
static char * emailsubject
Definitions to aid in the use of thread local storage.
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 vm_intro_en(struct ast_channel *chan, struct vm_state *vms)
static int input(yyscan_t yyscanner)
static int inboxcount2(const char *mailbox, int *urgentmsgs, int *newmsgs, int *oldmsgs)
#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
int ast_unregister_application(const char *app)
Unregister an application.
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
#define ast_cond_signal(cond)
static struct ast_smdi_interface * smdi_iface
static char fromstring[100]
#define ast_verb(level,...)
void ast_config_destroy(struct ast_config *config)
Destroys a config.
void ast_unreplace_sigchld(void)
Restore the SIGCHLD handler.
static int vm_intro_no(struct ast_channel *chan, struct vm_state *vms)
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.
static void poll_subscribed_mailbox(struct mwi_sub *mwi_sub)
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 void adsi_message(struct ast_channel *chan, struct vm_state *vms)
static int get_date(char *s, int len)
Gets the current date and time, as formatted string.
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
String fields in structures.
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
pthread_cond_t ast_cond_t
static const char * mbox(struct ast_vm_user *vmu, int id)
char cause[SMDI_MWI_FAIL_CAUSE_LEN+1]
#define ast_manager_event(chan, category, event, contents,...)
static int invent_message(struct ast_channel *chan, char *context, char *ext, int busy, char *ecodes)
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...
struct ast_category * ast_category_new(const char *name, const char *in_file, int lineno)
Create a category structure.
int ast_smdi_mwi_set(struct ast_smdi_interface *iface, const char *mailbox)
Set the MWI indicator for a mailbox.
static int messagecount(const char *context, const char *mailbox, const char *folder)
#define ADSI_DIR_FROM_LEFT
Custom localtime functions for multiple timezones.
static void adsi_begin(struct ast_channel *chan, int *useadsi)
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
#define DEFAULT_LISTEN_CONTROL_PAUSE_KEY
struct ast_party_id id
Caller party ID.
static void run_externnotify(char *context, char *extension, const char *flag)
static char pagerfromstring[100]
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.
static void vm_change_password(struct ast_vm_user *vmu, const char *newpassword)
The handler for the change password option.
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
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.
static int vm_intro_multilang(struct ast_channel *chan, struct vm_state *vms, const char message_gender[])
int ast_get_time_t(const char *src, time_t *dst, time_t _default, int *consumed)
get values from config variables.
static int passwordlocation
static char exitcontext[AST_MAX_CONTEXT]
static int wait_file2(struct ast_channel *chan, struct vm_state *vms, char *file)
#define ast_debug(level,...)
Log a DEBUG message.
static char * sayname_app
int ast_adsi_set_line(unsigned char *buf, int page, int line)
Sets the current line and page.
static int acf_mailbox_exists(struct ast_channel *chan, const char *cmd, char *args, char *buf, size_t len)
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.
static int inprocess_hash_fn(const void *obj, const int flags)
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 char * complete_voicemail_show_users(const char *line, const char *word, int pos, int state)
static int vm_intro_fr(struct ast_channel *chan, struct vm_state *vms)
int ast_say_counted_noun(struct ast_channel *chan, int num, const char *noun)
static struct ast_custom_function mailbox_exists_acf
static int vmsayname_exec(struct ast_channel *chan, const char *data)
int ast_build_string(char **buffer, size_t *space, const char *fmt,...)
Build a string in a buffer, designed to be called repeatedly.
char * ast_callerid_merge(char *buf, int bufsiz, const char *name, const char *num, const char *unknown)
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 int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms)
General Asterisk PBX channel definitions.
int ast_destroy_realtime(const char *family, const char *keyfield, const char *lookup,...) attribute_sentinel
Destroy realtime configuration.
static char dialcontext[AST_MAX_CONTEXT]
static int quote(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
static const char *const mailbox_folders[]
#define ast_test_status_update(a, b, c...)
static int vm_execmain(struct ast_channel *chan, const char *data)
#define ast_config_load(filename, flags)
Load a config file.
static struct ast_flags globalflags
static int change_password_realtime(struct ast_vm_user *vmu, const char *password)
Performs a change of the voicemail passowrd in the realtime engine.
#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
#define DEFAULT_LISTEN_CONTROL_STOP_KEY
#define AST_PTHREADT_NULL
static force_inline int attribute_pure ast_strlen_zero(const char *s)
struct sla_ringing_trunk * last
Data structure associated with a custom dialplan function.
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.
static int play_message_duration(struct ast_channel *chan, struct vm_state *vms, const char *duration, int minduration)
struct ast_data * ast_data_add_node(struct ast_data *root, const char *childname)
Add a container child.
static int silencethreshold
static void * mb_poll_thread(void *data)
char mailbox[AST_MAX_EXTENSION]
#define AST_MAX_EXTENSION
#define AST_RWLIST_TRAVERSE
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)
#define ast_data_unregister(path)
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
static char vm_reenterpassword[80]
static void mwi_sub_event_cb(const struct ast_event *event, void *userdata)
char * ast_category_browse(struct ast_config *config, const char *prev)
Goes through categories.
#define ao2_ref(o, delta)
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
char context[AST_MAX_CONTEXT]
long int ast_random(void)
static char cidinternalcontexts[MAX_NUM_CID_CONTEXTS][64]
static void free_zone(struct vm_zone *z)
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 int vm_intro_se(struct ast_channel *chan, struct vm_state *vms)
static int check_password(struct ast_vm_user *vmu, char *password)
Check that password meets minimum required length.
static int say_and_wait(struct ast_channel *chan, int num, const char *language)
#define COPY(a, b, c, d, e, f, g, h)
static void mwi_sub_destroy(struct mwi_sub *mwi_sub)
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 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)
static ast_mutex_t poll_lock
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 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.
#define DELETE(a, b, c, d)
static int write_password_to_file(const char *secretfn, const char *password)
#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.
static char VM_SPOOL_DIR[PATH_MAX]
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
#define ast_data_register_multiple(data_entries, entries)
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 void free_user(struct ast_vm_user *vmu)
static int vm_delete(char *file)
Removes the voicemail sound and information file.
#define PWDCHANGE_INTERNAL
static int wait_file(struct ast_channel *chan, struct vm_state *vms, char *file)
Structure to describe a channel "technology", ie a channel driver See for examples: ...
static void apply_options(struct ast_vm_user *vmu, const char *options)
Destructively Parse options and apply.
Core PBX routines and definitions.
static char vm_mismatch[80]
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
static char vm_pls_try_again[80]
#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.
static struct ast_taskprocessor * mwi_subscription_tps
#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 char vm_invalid_password[80]
static int get_folder2(struct ast_channel *chan, char *fn, int start)
plays a prompt and waits for a keypress.
#define ast_test_suite_event_notify(s, f,...)
static void apply_option(struct ast_vm_user *vmu, const char *var, const char *value)
Sets a a specific property value.
static int vm_intro(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms)
const char * ast_config_AST_DATA_DIR
#define DEFAULT_POLL_FREQ
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
#define HVSU_OUTPUT_FORMAT
#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 int vm_intro_cs(struct ast_channel *chan, struct vm_state *vms)
static char callcontext[AST_MAX_CONTEXT]
static void adsi_password(struct ast_channel *chan)
static void mwi_unsub_event_cb(const struct ast_event *event, void *userdata)
#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.
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.
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.
static char ext_pass_check_cmd[128]
static int vm_play_folder_name_gr(struct ast_channel *chan, char *box)
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 vm_play_folder_name_ua(struct ast_channel *chan, char *box)
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
#define RENAME(a, b, c, d, e, f, g, h)
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.
void ast_data_remove_node(struct ast_data *root, struct ast_data *child)
Remove a node that was added using ast_data_add_.
static unsigned int poll_mailboxes
static char listen_control_restart_key[12]
#define AST_TEST_UNREGISTER(cb)
void ast_variable_append(struct ast_category *category, struct ast_variable *variable)
static int vm_users_data_provider_get(const struct ast_data_search *search, struct ast_data *data_root)
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
enum ast_channel_state _state
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 void poll_subscribed_mailboxes(void)
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.
static void adsi_folders(struct ast_channel *chan, int start, char *label)
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
static int vm_users_data_provider_get_helper(const struct ast_data_search *search, struct ast_data *data_root, struct ast_vm_user *user)
const ast_string_field name
static int vm_intro_vi(struct ast_channel *chan, struct vm_state *vms)
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 int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_options *options)
Prompts the user and records a voicemail to a mailbox.
#define ao2_alloc(data_size, destructor_fn)
static int ochar(struct baseio *bio, int c, FILE *so)
utility used by base_encode()
int ast_goto_if_exists(struct ast_channel *chan, const char *context, const char *exten, int priority)
#define VOICEMAIL_DIR_MODE
static void adsi_goodbye(struct ast_channel *chan)
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.
static int vm_instructions(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int skipadvanced, int in_urgent)
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.
#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 AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
#define ao2_find(arg1, arg2, arg3)
#define ast_channel_unlock(chan)
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.
static void parse(struct mgcp_request *req)
static char emaildateformat[32]
#define ast_pthread_create(a, b, c, d)
char macrocontext[AST_MAX_CONTEXT]
struct ast_config * ast_config_new(void)
Create a new base configuration structure.
int ast_adsi_end_download(struct ast_channel *chan)
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 int inchar(struct baseio *bio, FILE *fi)
utility used by base_encode()
static int load_module(void)
void ast_close_fds_above_n(int n)
Common routine for child processes, to close all fds prior to exec(2)
static char vm_passchanged[80]
SMDI support for Asterisk.
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 base_encode(char *filename, FILE *so)
Performs a base 64 encode algorithm on the contents of a File.
static struct ast_cli_entry cli_voicemail[]
#define STORE(a, b, c, d, e, f, g, h, i, j)
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 char listen_control_pause_key[12]
if(yyss+yystacksize-1<=yyssp)
structure to hold users read from users.conf
static void * cleanup(void *unused)
static int vm_intro_es(struct ast_channel *chan, struct vm_state *vms)
Structure used to handle boolean flags.
static char listen_control_forward_key[12]
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.
Options for leaving voicemail with the voicemail() application.
static void read_password_from_file(const char *secretfn, char *password, int passwordlen)
static int vm_intro_pl(struct ast_channel *chan, struct vm_state *vms)
static int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu, int box)
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 vm_intro_pt_BR(struct ast_channel *chan, struct vm_state *vms)
#define RETRIEVE(a, b, c, d)
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
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...
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
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
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.
A ast_taskprocessor structure is a singleton by name.
int ast_say_number(struct ast_channel *chan, int num, const char *ints, const char *lang, const char *options)
says a number
static struct ast_event_sub * mwi_unsub_sub
Standard Command Line Interface.
struct ast_event * ast_event_new(enum ast_event_type event_type,...)
Create a new event.
static int has_voicemail(const char *mailbox, const char *folder)
Determines if the given folder has messages.
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.
static void start_poll_thread(void)
#define ao2_container_alloc(arg1, arg2, arg3)
static int vm_intro_zh(struct ast_channel *chan, struct vm_state *vms)
static int vm_play_folder_name_pl(struct ast_channel *chan, char *box)
#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.
static struct ast_app_option vm_app_options[128]
ast_app: A registered application
static struct ast_vm_user * find_or_create(const char *context, const char *box)
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is "false"...
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...
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
#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.
static int vm_options(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain)
int ast_fileexists(const char *filename, const char *fmt, const char *preflang)
Checks for the existence of a given file.
static char * handle_voicemail_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Reload voicemail configuration from the CLI.
#define EXISTS(a, b, c, d)
int ast_answer(struct ast_channel *chan)
Answer a channel.
static int vm_browse_messages_he(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
static char * pagersubject
static int dialout(struct ast_channel *chan, struct ast_vm_user *vmu, char *num, char *outgoing_context)
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
static char * show_users_realtime(int fd, const char *context)
static int __has_voicemail(const char *context, const char *mailbox, const char *folder, int shortcircuit)
static int append_mailbox(const char *context, const char *box, const char *data)
void ast_smdi_mwi_message_destroy(struct ast_smdi_mwi_message *msg)
ast_smdi_mwi_message destructor.
static int inboxcount(const char *mailbox, int *newmsgs, int *oldmsgs)
static void vm_change_password_shell(struct ast_vm_user *vmu, char *newpassword)
Data structure associated with a single frame of data.
#define AST_DATA_STRUCTURE(__struct, __name)
#define VMSTATE_MAX_MSG_ARRAY
#define AST_TEST_DEFINE(hdr)
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 char vm_password[80]
static int adsi_load_vmail(struct ast_channel *chan, int *useadsi)
static int play_message_category(struct ast_channel *chan, const char *category)
Unique ID Used by: AST_EVENT_SUB, AST_EVENT_UNSUB Payload type: UINT.
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 ASTERISK_USERNAME
#define VOICEMAIL_FILE_MODE
int ast_filerename(const char *oldname, const char *newname, const char *fmt)
Renames a file.
#define PWDCHANGE_EXTERNAL
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.
static struct ast_event_sub * mwi_sub_sub
static int vm_newuser(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain)
static int is_valid_dtmf(const char *key)
Determines if a DTMF key entered is valid.
#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.
struct ast_variable * next
static int vm_exec(struct ast_channel *chan, const char *data)
int ast_adsi_input_control(unsigned char *buf, int page, int line, int display, int format, int just)
Set input information.
#define HVSZ_OUTPUT_FORMAT
#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.
#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)
#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.
#define ast_mutex_destroy(a)
static unsigned char poll_thread_run
int ast_adsi_unload_session(struct ast_channel *chan)
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.
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()
Say numbers and dates (maybe words one day too)
static void adsi_delete(struct ast_channel *chan, struct vm_state *vms)
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.
static char vm_newpassword[80]
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.
Asterisk module definitions.
const char * ast_config_AST_VAR_DIR
static void delete_file(struct phoneprov_file *file)
static snd_pcm_format_t format
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.
static int vmauthenticate(struct ast_channel *chan, const char *data)
static int play_message_callerid(struct ast_channel *chan, struct vm_state *vms, char *cid, const char *context, int callback)
struct ast_event_sub * ast_event_unsubscribe(struct ast_event_sub *event_sub)
Un-subscribe from events.
static char serveremail[80]
static int save_to_folder(struct ast_vm_user *vmu, struct vm_state *vms, int msg, int box)
unsigned char valid
TRUE if the number information is valid/present.
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 ...
#define ast_cond_timedwait(cond, mutex, time)
static int valid_config(const struct ast_config *cfg)
Check if configuration file is valid.
static char listen_control_stop_key[12]
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.
#define AST_RWLIST_TRAVERSE_SAFE_END
const ast_string_field language
uint32_t version
Structure version.
char exten[AST_MAX_EXTENSION]
#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.
struct ast_variable * ast_variable_new(const char *name, const char *value, const char *filename)
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)
Structure for mutex and tracking information.
An SMDI message waiting indicator message.
static char mailbox[AST_MAX_EXTENSION]
The structure of the node handler.
int ast_manager_unregister(char *action)
Unregister a registered manager command.
#define DATA_EXPORT_VM_ZONES(ZONE)
static int reset_user_pw(const char *context, const char *mailbox, const char *newpass)
Resets a user password to a specified password.
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
struct ast_config * ast_load_realtime_multientry(const char *family,...) attribute_sentinel
Retrieve realtime configuration.
#define DEFAULT_LISTEN_CONTROL_RESTART_KEY
#define AST_APP_OPTION(option, flagno)
Declares an application option that does not accept an argument.
#define CONFIG_STATUS_FILEUNCHANGED
static unsigned int poll_freq
struct ao2_container * inprocess_container
#define ast_mutex_unlock(a)
static void queue_mwi_event(const char *box, int urgent, int new, int old)
static void stop_poll_thread(void)
static char prefix[MAX_PREFIX]
static void populate_defaults(struct ast_vm_user *vmu)
Sets default voicemail system options to a voicemail user.
static int vm_intro_gr(struct ast_channel *chan, struct vm_state *vms)
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 char vm_prepend_timeout[80]
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.
static int vm_intro_he(struct ast_channel *chan, struct vm_state *vms)
static int play_message_datetime(struct ast_channel *chan, struct ast_vm_user *vmu, const char *origtime, const char *filename)
int ast_check_realtime(const char *family)
Check if realtime engine is configured for family.
struct ast_party_number number
Subscriber phone number.