55 #ifdef USE_SYSTEM_IMAP 56 #include <imap/c-client.h> 57 #include <imap/imap4r1.h> 58 #include <imap/linkage.h> 59 #elif defined (USE_SYSTEM_CCLIENT) 60 #include <c-client/c-client.h> 61 #include <c-client/imap4r1.h> 62 #include <c-client/linkage.h> 76 #if defined(__FreeBSD__) || defined(__OpenBSD__) 442 static char imapserver[48] =
"localhost";
443 static char imapport[8] =
"143";
444 static char imapflags[128];
445 static char imapfolder[64] =
"INBOX";
446 static char imapparentfolder[64];
447 static char greetingfolder[64] =
"INBOX";
448 static char authuser[32];
449 static char authpassword[42];
450 static int imapversion = 1;
452 static int expungeonhangup = 1;
453 static int imapgreetings;
454 static int imap_poll_logout;
455 static char delimiter;
466 static int init_mailstream(
struct vm_state *vms,
int box);
467 static void write_file(
char *filename,
char *buffer,
unsigned long len);
468 static char *get_header_by_tag(
char *
header,
char *tag,
char *
buf,
size_t len);
469 static void vm_imap_delete(
char *
file,
int msgnum,
struct ast_vm_user *vmu);
470 static char *get_user_by_mailbox(
char *
mailbox,
char *
buf,
size_t len);
471 static struct vm_state *get_vm_state_by_imapuser(
const char *
user,
int interactive);
472 static struct vm_state *get_vm_state_by_mailbox(
const char *
mailbox,
const char *
context,
int interactive);
474 static void vmstate_insert(
struct vm_state *vms);
475 static void vmstate_delete(
struct vm_state *vms);
476 static void set_update(MAILSTREAM * stream);
477 static void init_vm_state(
struct vm_state *vms);
478 static int save_body(BODY *body,
struct vm_state *vms,
char *section,
char *
format,
int is_intro);
479 static void get_mailbox_delimiter(
struct vm_state *vms, MAILSTREAM *stream);
480 static void mm_parsequota (MAILSTREAM *stream,
unsigned char *msg, QUOTALIST *pquota);
481 static void imap_mailbox_name(
char *spec,
size_t len,
struct vm_state *vms,
int box,
int target);
482 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,
const char *msg_id);
483 static void vm_imap_update_msg_id(
char *dir,
int msgnum,
const char *msg_id,
struct ast_vm_user *vmu,
struct ast_config *msg_cfg,
int folder);
484 static void update_messages_by_imapuser(
const char *
user,
unsigned long number);
487 static int imap_remove_file (
char *dir,
int msgnum);
488 static int imap_retrieve_file (
const char *dir,
const int msgnum,
const char *
mailbox,
const char *
context);
489 static int imap_delete_old_greeting (
char *dir,
struct vm_state *vms);
492 static void imap_logout(
const char *mailbox_id);
503 #define SMDI_MWI_WAIT_TIMEOUT 1000 505 #define COMMAND_TIMEOUT 5000 507 #define VOICEMAIL_DIR_MODE 0777 508 #define VOICEMAIL_FILE_MODE 0666 509 #define CHUNKSIZE 65536 511 #define VOICEMAIL_CONFIG "voicemail.conf" 512 #define ASTERISK_USERNAME "asterisk" 517 #define DEFAULT_LISTEN_CONTROL_FORWARD_KEY "#" 518 #define DEFAULT_LISTEN_CONTROL_REVERSE_KEY "*" 519 #define DEFAULT_LISTEN_CONTROL_PAUSE_KEY "0" 520 #define DEFAULT_LISTEN_CONTROL_RESTART_KEY "2" 521 #define DEFAULT_LISTEN_CONTROL_STOP_KEY "13456789" 522 #define VALID_DTMF "1234567890*#" 526 #define SENDMAIL "/usr/sbin/sendmail -t" 528 #define INTRO "vm-intro" 530 #define MAX_MAIL_BODY_CONTENT_SIZE 134217728L // 128 Mbyte 533 #define MAXMSGLIMIT 9999 535 #define MINPASSWORD 0 537 #define BASELINELEN 72 538 #define BASEMAXINLINE 256 545 #define MAX_DATETIME_FORMAT 512 546 #define MAX_NUM_CID_CONTEXTS 10 548 #define VM_REVIEW (1 << 0) 549 #define VM_OPERATOR (1 << 1) 550 #define VM_SAYCID (1 << 2) 551 #define VM_SVMAIL (1 << 3) 552 #define VM_ENVELOPE (1 << 4) 553 #define VM_SAYDURATION (1 << 5) 554 #define VM_SKIPAFTERCMD (1 << 6) 555 #define VM_FORCENAME (1 << 7) 556 #define VM_FORCEGREET (1 << 8) 557 #define VM_PBXSKIP (1 << 9) 558 #define VM_DIRECFORWARD (1 << 10) 559 #define VM_ATTACH (1 << 11) 560 #define VM_DELETE (1 << 12) 561 #define VM_ALLOCED (1 << 13) 562 #define VM_SEARCH (1 << 14) 563 #define VM_TEMPGREETWARN (1 << 15) 564 #define VM_MOVEHEARD (1 << 16) 565 #define VM_MESSAGEWRAP (1 << 17) 566 #define VM_FWDURGAUTO (1 << 18) 567 #define ERROR_LOCK_PATH -100 568 #define ERROR_MAX_MSGS -101 569 #define OPERATOR_EXIT 300 643 #ifdef TEST_FRAMEWORK 748 #define MAX_VM_MBOX_ID_LEN (AST_MAX_EXTENSION) 749 #define MAX_VM_CONTEXT_LEN (AST_MAX_CONTEXT) 751 #define MAX_VM_MAILBOX_LEN (MAX_VM_MBOX_ID_LEN + MAX_VM_CONTEXT_LEN) 786 char imappassword[80];
788 char imapvmshareid[80];
800 char msg_format[512];
803 #define VMSTATE_MAX_MSG_ARRAY 256 828 unsigned msg_array_max;
829 MAILSTREAM *mailstream;
839 unsigned int quota_limit;
840 unsigned int quota_usage;
846 static char odbc_database[80] =
"asterisk";
847 static char odbc_table[80] =
"voicemessages";
848 #define RETRIEVE(a,b,c,d) retrieve_file(a,b) 849 #define DISPOSE(a,b) remove_file(a,b) 850 #define STORE(a,b,c,d,e,f,g,h,i,j,k) store_file(a,b,c,d) 851 #define EXISTS(a,b,c,d) (message_exists(a,b)) 852 #define RENAME(a,b,c,d,e,f,g,h) (rename_file(a,b,c,d,e,f)) 853 #define COPY(a,b,c,d,e,f,g,h) (copy_file(a,b,c,d,e,f)) 854 #define DELETE(a,b,c,d) (delete_file(a,b)) 855 #define UPDATE_MSG_ID(a, b, c, d, e, f) (odbc_update_msg_id((a), (b), (c))) 858 #define DISPOSE(a,b) (imap_remove_file(a,b)) 859 #define STORE(a,b,c,d,e,f,g,h,i,j,k) (imap_store_file(a,b,c,d,e,f,g,h,i,j,k)) 860 #define RETRIEVE(a,b,c,d) imap_retrieve_file(a,b,c,d) 861 #define EXISTS(a,b,c,d) (ast_fileexists(c,NULL,d) > 0) 862 #define RENAME(a,b,c,d,e,f,g,h) (rename_file(g,h)); 863 #define COPY(a,b,c,d,e,f,g,h) (copy_file(g,h)); 864 #define DELETE(a,b,c,d) (vm_imap_delete(a,b,d)) 865 #define UPDATE_MSG_ID(a, b, c, d, e, f) (vm_imap_update_msg_id((a), (b), (c), (d), (e), (f))) 867 #define RETRIEVE(a,b,c,d) 869 #define STORE(a,b,c,d,e,f,g,h,i,j,k) 870 #define EXISTS(a,b,c,d) (ast_fileexists(c,NULL,d) > 0) 871 #define RENAME(a,b,c,d,e,f,g,h) (rename_file(g,h)); 872 #define COPY(a,b,c,d,e,f,g,h) (copy_plain_file(g,h)); 873 #define DELETE(a,b,c,d) (vm_delete(c)) 874 #define UPDATE_MSG_ID(a, b, c, d, e, f) 885 #define PWDCHANGE_INTERNAL (1 << 1) 886 #define PWDCHANGE_EXTERNAL (1 << 2) 890 #define tdesc "Comedian Mail (Voicemail System) with ODBC Storage" 893 # define tdesc "Comedian Mail (Voicemail System) with IMAP Storage" 895 # define tdesc "Comedian Mail (Voicemail System)" 943 #define DEFAULT_POLL_FREQ 30 966 #define MAPPING_BUCKETS 511 1024 static unsigned char adsifdn[4] =
"\x00\x00\x00\x0F";
1025 static unsigned char adsisec[4] =
"\x9B\xDB\xF7\xAC";
1036 char *fmt,
int outsidecaller,
struct ast_vm_user *vmu,
int *duration,
int *sound_duration,
const char *unlockdir,
1037 signed char record_gain,
struct vm_state *vms,
char *
flag,
const char *msg_id,
int forwardintro);
1041 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,
const char *msg_id);
1072 static int vm_msg_forward(
const char *
from_mailbox,
const char *from_context,
const char *from_folder,
const char *to_mailbox,
const char *to_context,
const char *to_folder,
size_t num_msgs,
const char *msg_ids[],
int delete_old);
1073 static int vm_msg_move(
const char *
mailbox,
const char *
context,
size_t num_msgs,
const char *oldfolder,
const char *old_msg_ids[],
const char *newfolder);
1077 #ifdef TEST_FRAMEWORK 1099 *context = mailbox_id;
1100 *mailbox =
strsep(context,
"@");
1105 *context =
"default";
1127 if (strcmp(i->
mailbox, j->mailbox)) {
1135 int context_len = strlen(context) + 1;
1136 int mailbox_len = strlen(mailbox) + 1;
1142 if ((i =
ao2_find(inprocess_container, arg, 0))) {
1151 if (!(i =
ao2_alloc(
sizeof(*i) + context_len + mailbox_len,
NULL))) {
1165 #if !(defined(ODBC_STORAGE) || defined(IMAP_STORAGE)) 1178 for (; *
input; input++) {
1183 if (bufptr == buf + buflen - 1) {
1209 if (saydurationminfo) {
1226 if (maxdeletedmsg) {
1237 ast_copy_string(vmu->imapfolder, imapfolder,
sizeof(vmu->imapfolder));
1238 ast_copy_string(vmu->imapserver, imapserver,
sizeof(vmu->imapserver));
1255 if (!strcasecmp(var,
"attach")) {
1257 }
else if (!strcasecmp(var,
"attachfmt")) {
1259 }
else if (!strcasecmp(var,
"serveremail")) {
1261 }
else if (!strcasecmp(var,
"fromstring")) {
1263 }
else if (!strcasecmp(var,
"emailbody")) {
1266 }
else if (!strcasecmp(var,
"emailsubject")) {
1269 }
else if (!strcasecmp(var,
"language")) {
1271 }
else if (!strcasecmp(var,
"tz")) {
1273 }
else if (!strcasecmp(var,
"locale")) {
1276 }
else if (!strcasecmp(var,
"imapuser")) {
1278 vmu->imapversion = imapversion;
1279 }
else if (!strcasecmp(var,
"imapserver")) {
1281 vmu->imapversion = imapversion;
1282 }
else if (!strcasecmp(var,
"imapport")) {
1284 vmu->imapversion = imapversion;
1285 }
else if (!strcasecmp(var,
"imapflags")) {
1287 vmu->imapversion = imapversion;
1288 }
else if (!strcasecmp(var,
"imappassword") || !strcasecmp(var,
"imapsecret")) {
1290 vmu->imapversion = imapversion;
1291 }
else if (!strcasecmp(var,
"imapfolder")) {
1293 vmu->imapversion = imapversion;
1294 }
else if (!strcasecmp(var,
"imapvmshareid")) {
1295 ast_copy_string(vmu->imapvmshareid, value,
sizeof(vmu->imapvmshareid));
1296 vmu->imapversion = imapversion;
1298 }
else if (!strcasecmp(var,
"delete") || !strcasecmp(var,
"deletevoicemail")) {
1300 }
else if (!strcasecmp(var,
"saycid")){
1302 }
else if (!strcasecmp(var,
"sendvoicemail")){
1304 }
else if (!strcasecmp(var,
"review")){
1306 }
else if (!strcasecmp(var,
"tempgreetwarn")){
1308 }
else if (!strcasecmp(var,
"messagewrap")){
1310 }
else if (!strcasecmp(var,
"operator")) {
1312 }
else if (!strcasecmp(var,
"envelope")){
1314 }
else if (!strcasecmp(var,
"moveheard")){
1316 }
else if (!strcasecmp(var,
"sayduration")){
1318 }
else if (!strcasecmp(var,
"saydurationm")){
1319 if (sscanf(value,
"%30d", &x) == 1) {
1324 }
else if (!strcasecmp(var,
"forcename")){
1326 }
else if (!strcasecmp(var,
"forcegreetings")){
1328 }
else if (!strcasecmp(var,
"callback")) {
1330 }
else if (!strcasecmp(var,
"dialout")) {
1332 }
else if (!strcasecmp(var,
"exitcontext")) {
1334 }
else if (!strcasecmp(var,
"minsecs")) {
1335 if (sscanf(value,
"%30d", &x) == 1 && x >= 0) {
1338 ast_log(
LOG_WARNING,
"Invalid min message length of %s. Using global value %d\n", value, vmminsecs);
1341 }
else if (!strcasecmp(var,
"maxmessage") || !strcasecmp(var,
"maxsecs")) {
1349 if (!strcasecmp(var,
"maxmessage"))
1350 ast_log(
AST_LOG_WARNING,
"Option 'maxmessage' has been deprecated in favor of 'maxsecs'. Please make that change in your voicemail config.\n");
1351 }
else if (!strcasecmp(var,
"maxmsg")) {
1352 vmu->
maxmsg = atoi(value);
1361 }
else if (!strcasecmp(var,
"nextaftercmd")) {
1363 }
else if (!strcasecmp(var,
"backupdeleted")) {
1364 if (sscanf(value,
"%30d", &x) == 1)
1372 ast_log(
AST_LOG_WARNING,
"Invalid number of deleted messages saved per mailbox backupdeleted=%s. Using default value %d\n", value,
MAXMSG);
1378 }
else if (!strcasecmp(var,
"volgain")) {
1379 sscanf(value,
"%30lf", &vmu->
volgain);
1380 }
else if (!strcasecmp(var,
"passwordlocation")) {
1381 if (!strcasecmp(value,
"spooldir")) {
1386 }
else if (!strcasecmp(var,
"options")) {
1393 int fds[2], pid = 0;
1395 memset(buf, 0, len);
1398 snprintf(buf, len,
"FAILURE: Pipe failed: %s", strerror(
errno));
1407 snprintf(buf, len,
"FAILURE: Fork failed");
1411 if (read(fds[0], buf, len) < 0) {
1423 dup2(fds[1], STDOUT_FILENO);
1429 execv(arg.v[0], arg.v);
1430 printf(
"FAILURE: %s", strerror(
errno));
1447 if (strlen(password) < minpassword)
1453 char cmd[255],
buf[255];
1455 ast_debug(1,
"Verify password policies for %s\n", password);
1457 snprintf(cmd,
sizeof(cmd),
"%s %s %s %s %s", ext_pass_check_cmd, vmu->
mailbox, vmu->
context, vmu->
password, password);
1460 if (!strncasecmp(buf,
"VALID", 5)) {
1461 ast_debug(3,
"Passed password check: '%s'\n", buf);
1463 }
else if (!strncasecmp(buf,
"FAILURE", 7)) {
1488 if (!strcmp(vmu->
password, password)) {
1493 if (strlen(password) > 10) {
1513 while ((s =
strsep(&stringp,
"|"))) {
1515 if ((var =
strsep(&value,
"=")) && value) {
1528 for (;
var; var = var->
next) {
1529 if (!strcasecmp(var->
name,
"vmsecret")) {
1531 }
else if (!strcasecmp(var->
name,
"secret") || !strcasecmp(var->
name,
"password")) {
1535 "\n\tmust be reset in voicemail.conf.\n", retval->
mailbox);
1540 }
else if (!strcasecmp(var->
name,
"uniqueid")) {
1542 }
else if (!strcasecmp(var->
name,
"pager")) {
1544 }
else if (!strcasecmp(var->
name,
"email")) {
1547 }
else if (!strcasecmp(var->
name,
"fullname")) {
1549 }
else if (!strcasecmp(var->
name,
"context")) {
1551 }
else if (!strcasecmp(var->
name,
"emailsubject")) {
1554 }
else if (!strcasecmp(var->
name,
"emailbody")) {
1558 }
else if (!strcasecmp(var->
name,
"imapuser")) {
1560 retval->imapversion = imapversion;
1561 }
else if (!strcasecmp(var->
name,
"imapserver")) {
1563 retval->imapversion = imapversion;
1564 }
else if (!strcasecmp(var->
name,
"imapport")) {
1566 retval->imapversion = imapversion;
1567 }
else if (!strcasecmp(var->
name,
"imapflags")) {
1569 retval->imapversion = imapversion;
1570 }
else if (!strcasecmp(var->
name,
"imappassword") || !strcasecmp(var->
name,
"imapsecret")) {
1572 retval->imapversion = imapversion;
1573 }
else if (!strcasecmp(var->
name,
"imapfolder")) {
1575 retval->imapversion = imapversion;
1576 }
else if (!strcasecmp(var->
name,
"imapvmshareid")) {
1578 retval->imapversion = imapversion;
1597 for (i = 0; i < strlen(key); ++i) {
1622 if ((retval = (ivm ? ivm :
ast_calloc(1,
sizeof(*retval))))) {
1624 memset(retval, 0,
sizeof(*retval));
1665 context =
"default";
1669 if (cur->imapversion != imapversion) {
1675 if (context && (!strcasecmp(context, cur->context)) && (!strcasecmp(mailbox, cur->mailbox)))
1680 if ((vmu = (ivm ? ivm :
ast_calloc(1,
sizeof(*vmu))))) {
1707 char *search_mailbox =
NULL;
1708 char *search_context =
NULL;
1712 vmu =
find_user(ivm, search_mailbox, search_context);
1729 static int reset_user_pw(
const char *context,
const char *mailbox,
const char *newpass)
1736 if ((!context || !strcasecmp(context, cur->
context)) &&
1737 (!strcasecmp(mailbox, cur->
mailbox)))
1768 char *category =
NULL;
1780 snprintf(secretfn,
sizeof(secretfn),
"%s%s/%s/secret.conf", VM_SPOOL_DIR, vmu->
context, vmu->
mailbox);
1783 ast_verb(4,
"Writing voicemail password to file %s succeeded\n", secretfn);
1788 ast_verb(4,
"Writing voicemail password to file %s failed, falling back to config file\n", secretfn);
1794 if (!strcasecmp(category, vmu->
context)) {
1801 value = strstr(tmp,
",");
1804 sprintf(
new,
"%s", newpassword);
1806 new =
ast_malloc((strlen(value) + strlen(newpassword) + 1));
1807 sprintf(
new,
"%s%s", newpassword, value);
1821 ast_test_suite_event_notify(
"PASSWORDCHANGED",
"Message: voicemail.conf updated with new password\r\nPasswordSource: voicemail.conf");
1838 ast_debug(4,
"users.conf: %s\n", category);
1839 if (!strcasecmp(category, vmu->
mailbox)) {
1840 char new[strlen(newpassword) + 1];
1842 ast_debug(3,
"looks like we need to make vmsecret!\n");
1848 sprintf(
new,
"%s", newpassword);
1850 ast_debug(4,
"failed to get category!\n");
1879 snprintf(buf,
sizeof(buf),
"%s %s %s %s", ext_pass_cmd, vmu->
context, vmu->
mailbox, newpassword);
1880 ast_debug(1,
"External password: %s\n",buf);
1902 static int make_dir(
char *dest,
int len,
const char *context,
const char *
ext,
const char *folder)
1904 return snprintf(dest, len,
"%s%s/%s/%s", VM_SPOOL_DIR, context, ext, folder);
1919 static int make_file(
char *dest,
const int len,
const char *dir,
const int num)
1921 return snprintf(dest, len,
"%s/msg%04d", dir, num);
1928 int pfd = mkstemp(
template);
1931 p = fdopen(pfd,
"w+");
1953 make_dir(dest, len, context, ext, folder);
1964 if (vmu &&
id == 0) {
1965 return vmu->imapfolder;
1968 return (
id >= 0 &&
id <
ARRAY_LEN(mailbox_folders)) ? mailbox_folders[
id] :
"Unknown";
1981 for (i = 0; i <
ARRAY_LEN(mailbox_folders); i++) {
1982 if (strcasecmp(name, mailbox_folders[i]) == 0) {
2023 int arraysize = (vmu->
maxmsg > count_msg ? vmu->
maxmsg : count_msg);
2036 if (arraysize > 0) {
2054 static void vm_imap_delete(
char *
file,
int msgnum,
struct ast_vm_user *vmu)
2058 unsigned long messageNum;
2061 if (msgnum < 0 && !imapgreetings) {
2066 if (!(vms = get_vm_state_by_mailbox(vmu->
mailbox, vmu->
context, 1)) && !(vms = get_vm_state_by_mailbox(vmu->
mailbox, vmu->
context, 0))) {
2067 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);
2072 imap_delete_old_greeting(file, vms);
2078 messageNum = vms->msgArray[msgnum];
2079 if (messageNum == 0) {
2080 ast_log(
LOG_WARNING,
"msgnum %d, mailbox message %lu is zero.\n", msgnum, messageNum);
2083 ast_debug(3,
"deleting msgnum %d, which is mailbox message %lu\n", msgnum, messageNum);
2085 snprintf (arg,
sizeof(arg),
"%lu", messageNum);
2087 mail_setflag (vms->mailstream, arg,
"\\DELETED");
2088 mail_expunge(vms->mailstream);
2092 static void vm_imap_update_msg_id(
char *dir,
int msgnum,
const char *msg_id,
struct ast_vm_user *vmu,
struct ast_config *msg_cfg,
int folder)
2099 const char *duration_str;
2143 sscanf(duration_str,
"%30d", &duration);
2154 if (!imap_store_file(dir, vmu->
mailbox, vmu->
context, msgnum, chan, vmu, vmfmts,
2159 vm_imap_delete(dir, msgnum, vmu);
2165 static int imap_retrieve_greeting(
const char *dir,
const int msgnum,
struct ast_vm_user *vmu)
2168 char *
file, *filename;
2178 if (msgnum > -1 || !imapgreetings) {
2185 ast_debug(1,
"Failed to procure file name from directory passed.\n");
2191 if (!(vms_p = get_vm_state_by_mailbox(vmu->
mailbox, vmu->
context, 1)) &&
2192 !(vms_p = get_vm_state_by_mailbox(vmu->
mailbox, vmu->
context, 0))) {
2197 if (!(vms_p = create_vm_state_from_user(vmu))) {
2204 *vms_p->introfn =
'\0';
2218 for (i = 0; i < vms_p->mailstream->nmsgs; i++) {
2219 mail_fetchstructure(vms_p->mailstream, i + 1, &body);
2221 if (body->nested.part && body->nested.part->next && body->nested.part->next->body.parameter->value) {
2222 char *attachment = body->nested.part->next->body.parameter->value;
2223 char copy[strlen(attachment) + 1];
2225 strcpy(copy, attachment);
2228 filename =
strsep(&attachment,
".");
2229 if (!strcmp(filename, file)) {
2231 vms_p->msgArray[vms_p->
curmsg] = i + 1;
2233 save_body(body, vms_p,
"2", attachment, 0);
2244 if (curr_mbox != -1) {
2246 if (init_mailstream(vms_p, curr_mbox) || !vms_p->mailstream) {
2255 static int imap_retrieve_file(
const char *dir,
const int msgnum,
const char *mailbox,
const char *context)
2258 char *header_content;
2259 char *attachedfilefmt;
2263 FILE *text_file_ptr;
2274 if (imapgreetings) {
2275 res = imap_retrieve_greeting(dir, msgnum, vmu);
2286 if (!(vms = get_vm_state_by_mailbox(vmu->
mailbox, vmu->
context, 1)) && !(vms = get_vm_state_by_mailbox(vmu->
mailbox, vmu->
context, 0))) {
2301 if (curr_mbox < 0) {
2302 ast_debug(3,
"Mailbox folder curbox not set, defaulting to Inbox\n");
2305 init_mailstream(vms, curr_mbox);
2306 if (!vms->mailstream) {
2313 snprintf(vms->introfn,
sizeof(vms->introfn),
"%sintro", vms->
fn);
2321 ast_debug(3,
"Before mail_fetchheaders, curmsg is: %d, imap messages is %lu\n", msgnum, vms->msgArray[msgnum]);
2322 if (vms->msgArray[msgnum] == 0) {
2330 header_content = mail_fetchheader (vms->mailstream, vms->msgArray[msgnum]);
2334 ast_log(
LOG_ERROR,
"Could not fetch header for message number %ld\n", vms->msgArray[msgnum]);
2340 mail_fetchstructure(vms->mailstream, vms->msgArray[msgnum], &body);
2344 if (body->nested.part && body->nested.part->next && body->nested.part->next->body.parameter->value) {
2345 attachedfilefmt =
ast_strdupa(body->nested.part->next->body.parameter->value);
2354 strsep(&attachedfilefmt,
".");
2355 if (!attachedfilefmt) {
2356 ast_log(
LOG_ERROR,
"File format could not be obtained from IMAP message attachment\n");
2361 save_body(body, vms,
"2", attachedfilefmt, 0);
2362 if (save_body(body, vms,
"3", attachedfilefmt, 1)) {
2363 *vms->introfn =
'\0';
2367 snprintf(text_file,
sizeof(text_file),
"%s.%s", vms->
fn,
"txt");
2369 if (!(text_file_ptr = fopen(text_file,
"w"))) {
2374 fprintf(text_file_ptr,
"%s\n",
"[message]");
2376 if (get_header_by_tag(header_content,
"X-Asterisk-VM-Caller-ID-Name:", buf,
sizeof(buf))) {
2377 fprintf(text_file_ptr,
"callerid=\"%s\" ",
S_OR(buf,
""));
2379 if (get_header_by_tag(header_content,
"X-Asterisk-VM-Caller-ID-Num:", buf,
sizeof(buf))) {
2380 fprintf(text_file_ptr,
"<%s>\n",
S_OR(buf,
""));
2382 if (get_header_by_tag(header_content,
"X-Asterisk-VM-Context:", buf,
sizeof(buf))) {
2383 fprintf(text_file_ptr,
"context=%s\n",
S_OR(buf,
""));
2385 if (get_header_by_tag(header_content,
"X-Asterisk-VM-Orig-time:", buf,
sizeof(buf))) {
2386 fprintf(text_file_ptr,
"origtime=%s\n",
S_OR(buf,
""));
2388 if (get_header_by_tag(header_content,
"X-Asterisk-VM-Duration:", buf,
sizeof(buf))) {
2389 fprintf(text_file_ptr,
"duration=%s\n",
S_OR(buf,
""));
2391 if (get_header_by_tag(header_content,
"X-Asterisk-VM-Category:", buf,
sizeof(buf))) {
2392 fprintf(text_file_ptr,
"category=%s\n",
S_OR(buf,
""));
2394 if (get_header_by_tag(header_content,
"X-Asterisk-VM-Flag:", buf,
sizeof(buf))) {
2395 fprintf(text_file_ptr,
"flag=%s\n",
S_OR(buf,
""));
2397 if (get_header_by_tag(header_content,
"X-Asterisk-VM-Message-ID:", buf,
sizeof(buf))) {
2398 fprintf(text_file_ptr,
"msg_id=%s\n",
S_OR(buf,
""));
2400 fclose(text_file_ptr);
2407 static int folder_int(
const char *folder)
2413 if (!strcasecmp(folder, imapfolder)) {
2415 }
else if (!strcasecmp(folder,
"Old")) {
2417 }
else if (!strcasecmp(folder,
"Work")) {
2419 }
else if (!strcasecmp(folder,
"Family")) {
2421 }
else if (!strcasecmp(folder,
"Friends")) {
2423 }
else if (!strcasecmp(folder,
"Cust1")) {
2425 }
else if (!strcasecmp(folder,
"Cust2")) {
2427 }
else if (!strcasecmp(folder,
"Cust3")) {
2429 }
else if (!strcasecmp(folder,
"Cust4")) {
2431 }
else if (!strcasecmp(folder,
"Cust5")) {
2433 }
else if (!strcasecmp(folder,
"Urgent")) {
2440 static int __messagecount(
const char *context,
const char *mailbox,
const char *folder)
2448 int fold = folder_int(folder);
2461 memset(&vmus, 0,
sizeof(vmus));
2462 vmu =
find_user(&vmus, context, mailbox);
2469 if (vmu->imapuser[0] ==
'\0') {
2477 if (vmu->imapuser[0] ==
'\0') {
2484 vms_p = get_vm_state_by_imapuser(vmu->imapuser, 1);
2486 vms_p = get_vm_state_by_mailbox(mailbox, context, 1);
2489 ast_debug(3,
"Returning before search - user is logged in\n");
2501 vms_p = get_vm_state_by_imapuser(vmu->imapuser, 0);
2503 vms_p = get_vm_state_by_mailbox(mailbox, context, 0);
2507 vms_p = create_vm_state_from_user(vmu);
2509 ret = init_mailstream(vms_p, fold);
2510 if (!vms_p->mailstream) {
2517 pgm = mail_newsearchpgm ();
2518 hdr = mail_newsearchheader (
"X-Asterisk-VM-Extension", (
char *)(!
ast_strlen_zero(vmu->imapvmshareid) ? vmu->imapvmshareid : mailbox));
2519 hdr->next = mail_newsearchheader(
"X-Asterisk-VM-Context", (
char *)
S_OR(context,
"default"));
2545 vms_p->vmArrayIndex = 0;
2546 mail_search_full (vms_p->mailstream,
NULL, pgm, NIL);
2547 if (fold == 0 && urgent == 0)
2551 if (fold == 0 && urgent == 1)
2554 mail_free_searchpgm(&pgm);
2558 return vms_p->vmArrayIndex;
2561 mail_ping(vms_p->mailstream);
2571 check_quota(vms, vmu->imapfolder);
2572 if (vms->quota_limit && vms->quota_usage >= vms->quota_limit) {
2573 ast_debug(1,
"*** QUOTA EXCEEDED!! %u >= %u\n", vms->quota_usage, vms->quota_limit);
2583 ast_log(
LOG_WARNING,
"Unable to leave message since we will exceed the maximum number of messages allowed (%u >= %u)\n", msgnum, vmu->
maxmsg);
2602 static int messagecount(
const char *mailbox_id,
const char *folder)
2613 return __messagecount(context, mailbox,
"INBOX") + __messagecount(context, mailbox,
"Urgent");
2615 return __messagecount(context, mailbox, folder);
2619 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,
const char *msg_id)
2627 char tmp[80] =
"/tmp/astmail-XXXXXX";
2633 char *imap_flags = NIL;
2637 snprintf(mailbox,
sizeof(mailbox),
"%s@%s", vmu->
mailbox, vmu->
context);
2642 if(!imapgreetings) {
2649 if (imap_check_limits(chan, vms, vmu, msgcount)) {
2655 ast_debug(3,
"Setting message flag \\\\FLAGGED.\n");
2656 imap_flags =
"\\FLAGGED";
2672 snprintf(introfn,
sizeof(introfn),
"%sintro", fn);
2687 if (!strcmp(fmt,
"wav49"))
2689 ast_debug(3,
"Storing file '%s', format '%s'\n", fn, fmt);
2702 if (msgnum < 0 && imapgreetings) {
2707 imap_delete_old_greeting(fn, vms);
2713 fn, introfn, fmt, duration, 1, chan, NULL, 1, flag, msg_id);
2721 *(vmu->
email) =
'\0';
2724 if (fread(buf, 1, len, p) !=
len) {
2730 ((
char *) buf)[
len] =
'\0';
2731 INIT(&str, mail_string, buf, len);
2732 ret = init_mailstream(vms, box);
2734 imap_mailbox_name(mailbox,
sizeof(mailbox), vms, box, 1);
2736 if(!mail_append_full(vms->mailstream, mailbox, imap_flags, NIL, &str))
2752 *(vmu->
email) =
'\0';
2771 static int inboxcount2(
const char *mailbox_context,
int *urgentmsgs,
int *newmsgs,
int *oldmsgs)
2785 ast_debug(3,
"Mailbox is set to %s\n", mailbox_context);
2791 context = strchr(tmp,
'@');
2792 if (strchr(mailbox_context,
',')) {
2793 int tmpnew, tmpold, tmpurgent;
2796 while ((cur =
strsep(&mb,
", "))) {
2798 if (
inboxcount2(cur, urgentmsgs ? &tmpurgent :
NULL, newmsgs ? &tmpnew : NULL, oldmsgs ? &tmpold : NULL))
2806 *urgentmsgs += tmpurgent;
2817 context =
"default";
2818 mailboxnc = (
char *) mailbox_context;
2827 if ((*newmsgs = __messagecount(context, mailboxnc, vmu->imapfolder)) < 0) {
2834 if ((*oldmsgs = __messagecount(context, mailboxnc,
"Old")) < 0) {
2839 if ((*urgentmsgs = __messagecount(context, mailboxnc,
"Urgent")) < 0) {
2856 static int has_voicemail(
const char *mailbox,
const char *folder)
2861 if (strchr(tmp2,
',') || strchr(tmp2,
'&')) {
2862 while ((box =
strsep(&tmp2,
",&"))) {
2870 if ((context = strchr(tmp,
'@'))) {
2873 context =
"default";
2875 return __messagecount(context, tmp, folder) ? 1 : 0;
2896 char messagestring[10];
2897 if (msgnum >= recip->
maxmsg) {
2901 if (!(sendvms = get_vm_state_by_imapuser(vmu->imapuser, 0))) {
2905 if (!get_vm_state_by_imapuser(recip->imapuser, 0)) {
2909 snprintf(messagestring,
sizeof(messagestring),
"%ld", sendvms->msgArray[msgnum]);
2911 if ((mail_copy(sendvms->mailstream, messagestring, (
char *)
mbox(vmu, imbox)) == T)) {
2920 static void imap_mailbox_name(
char *spec,
size_t len,
struct vm_state *vms,
int box,
int use_folder)
2923 size_t left =
sizeof(
tmp);
2956 snprintf(spec, len,
"%s%s", tmp, use_folder? vms->imapfolder:
"INBOX");
2958 snprintf(spec, len,
"%s%s", tmp, greetingfolder);
2962 snprintf(spec, len,
"%s%s%c%s", tmp, imapparentfolder, delimiter,
mbox(
NULL, box));
2964 snprintf(spec, len,
"%s%s", tmp,
mbox(
NULL, box));
2969 static int init_mailstream(
struct vm_state *vms,
int box)
2971 MAILSTREAM *stream = NIL;
2979 ast_debug(3,
"vm_state user is:%s\n", vms->imapuser);
2980 if (vms->mailstream == NIL || !vms->mailstream) {
2983 stream = vms->mailstream;
2988 if (delimiter ==
'\0') {
2990 #ifdef USE_SYSTEM_IMAP 2991 #include <imap/linkage.c> 2992 #elif defined(USE_SYSTEM_CCLIENT) 2993 #include <c-client/linkage.c> 2995 #include "linkage.c" 2998 imap_mailbox_name(tmp,
sizeof(tmp), vms, 0, 1);
3001 stream = mail_open (stream, tmp, debug ? OP_DEBUG : NIL);
3004 if (stream == NIL) {
3008 get_mailbox_delimiter(vms, stream);
3010 for (cp = vms->imapfolder; *cp; cp++)
3015 imap_mailbox_name(tmp,
sizeof(tmp), vms, box, 1);
3016 ast_debug(3,
"Before mail_open, server: %s, box:%d\n", tmp, box);
3019 vms->mailstream = mail_open (stream, tmp, debug ? OP_DEBUG : NIL);
3021 if (vms->mailstream && !mail_status(vms->mailstream, tmp, SA_UIDNEXT)) {
3022 mail_create(vms->mailstream, tmp);
3026 if (vms->mailstream == NIL) {
3046 ast_copy_string(vms->imapfolder, vmu->imapfolder,
sizeof(vms->imapfolder));
3047 ast_copy_string(vms->imapserver, vmu->imapserver,
sizeof(vms->imapserver));
3049 ast_copy_string(vms->imapflags, vmu->imapflags,
sizeof(vms->imapflags));
3050 vms->imapversion = vmu->imapversion;
3051 ast_debug(3,
"Before init_mailstream, user is %s\n", vmu->imapuser);
3053 if (init_mailstream(vms, box) || !vms->mailstream) {
3062 ast_debug(3,
"Mailbox name set to: %s, about to check quotas\n",
mbox(vmu, box));
3063 check_quota(vms, (
char *)
mbox(vmu, box));
3067 pgm = mail_newsearchpgm();
3070 hdr = mail_newsearchheader(
"X-Asterisk-VM-Extension", (!
ast_strlen_zero(vmu->imapvmshareid) ? vmu->imapvmshareid : vmu->
mailbox));
3071 hdr->next = mail_newsearchheader(
"X-Asterisk-VM-Context", vmu->
context);
3082 }
else if (box ==
NEW_FOLDER && urgent == 0) {
3092 ast_debug(3,
"Before mail_search_full, user is %s\n", vmu->imapuser);
3094 vms->vmArrayIndex = 0;
3095 mail_search_full (vms->mailstream,
NULL, pgm, NIL);
3096 vms->
lastmsg = vms->vmArrayIndex - 1;
3097 mail_free_searchpgm(&pgm);
3103 ast_log(
LOG_WARNING,
"The code expects the old messages to be checked first, fix the code.\n");
3114 static void write_file(
char *filename,
char *buffer,
unsigned long len)
3118 if (!filename || !buffer) {
3122 if (!(output = fopen(filename,
"w"))) {
3127 if (fwrite(buffer, len, 1, output) != 1) {
3128 if (ferror(output)) {
3135 static void update_messages_by_imapuser(
const char *
user,
unsigned long number)
3137 struct vm_state *vms = get_vm_state_by_imapuser(user, 1);
3139 if (!vms && !(vms = get_vm_state_by_imapuser(user, 0))) {
3143 ast_debug(3,
"saving mailbox message number %lu as message %d. Interactive set to %d\n", number, vms->vmArrayIndex, vms->interactive);
3146 if (vms->vmArrayIndex >= vms->msg_array_max) {
3147 long *new_mem =
ast_realloc(vms->msgArray, 2 * vms->msg_array_max *
sizeof(
long));
3151 vms->msgArray = new_mem;
3152 vms->msg_array_max *= 2;
3155 vms->msgArray[vms->vmArrayIndex++] = number;
3158 void mm_searched(MAILSTREAM *stream,
unsigned long number)
3160 char *mailbox = stream->mailbox,
buf[1024] =
"", *
user;
3162 if (!(user = get_user_by_mailbox(mailbox,
buf,
sizeof(
buf))))
3165 update_messages_by_imapuser(user, number);
3168 static struct ast_vm_user *find_user_realtime_imapuser(
const char *imapuser)
3193 void mm_exists(MAILSTREAM * stream,
unsigned long number)
3196 ast_debug(4,
"Entering EXISTS callback for message %ld\n", number);
3197 if (number == 0)
return;
3202 void mm_expunged(MAILSTREAM * stream,
unsigned long number)
3205 ast_debug(4,
"Entering EXPUNGE callback for message %ld\n", number);
3206 if (number == 0)
return;
3211 void mm_flags(MAILSTREAM * stream,
unsigned long number)
3214 ast_debug(4,
"Entering FLAGS callback for message %ld\n", number);
3215 if (number == 0)
return;
3220 void mm_notify(MAILSTREAM * stream,
char *
string,
long errflg)
3222 ast_debug(5,
"Entering NOTIFY callback, errflag is %ld, string is %s\n", errflg,
string);
3223 mm_log (
string, errflg);
3227 void mm_list(MAILSTREAM * stream,
int delim,
char *mailbox,
long attributes)
3229 if (delimiter ==
'\0') {
3233 ast_debug(5,
"Delimiter set to %c and mailbox %s\n", delim, mailbox);
3234 if (attributes & LATT_NOINFERIORS)
3236 if (attributes & LATT_NOSELECT)
3238 if (attributes & LATT_MARKED)
3240 if (attributes & LATT_UNMARKED)
3245 void mm_lsub(MAILSTREAM * stream,
int delim,
char *mailbox,
long attributes)
3247 ast_debug(5,
"Delimiter set to %c and mailbox %s\n", delim, mailbox);
3248 if (attributes & LATT_NOINFERIORS)
3250 if (attributes & LATT_NOSELECT)
3252 if (attributes & LATT_MARKED)
3254 if (attributes & LATT_UNMARKED)
3259 void mm_status(MAILSTREAM * stream,
char *mailbox, MAILSTATUS *
status)
3268 if (status->flags & SA_MESSAGES) {
3271 if (status->flags & SA_RECENT) {
3274 if (status->flags & SA_UNSEEN) {
3277 if (status->flags & SA_UIDVALIDITY) {
3278 ast_str_append(&str, 0,
", %lu UID validity", status->uidvalidity);
3280 if (status->flags & SA_UIDNEXT) {
3289 void mm_log(
char *
string,
long errflg)
3291 switch ((
short) errflg) {
3293 ast_debug(1,
"IMAP Info: %s\n",
string);
3306 void mm_dlog(
char *
string)
3312 void mm_login(NETMBX * mb,
char *user,
char *pwd,
long trial)
3316 ast_debug(4,
"Entering callback mm_login\n");
3325 if (!strcasecmp(mb->user, vmu->imapuser)) {
3331 if ((vmu = find_user_realtime_imapuser(mb->user))) {
3340 void mm_critical(MAILSTREAM * stream)
3345 void mm_nocritical(MAILSTREAM * stream)
3350 long mm_diskerror(MAILSTREAM * stream,
long errcode,
long serious)
3352 kill (getpid (), SIGSTOP);
3357 void mm_fatal(
char *
string)
3363 static void mm_parsequota(MAILSTREAM *stream,
unsigned char *msg, QUOTALIST *pquota)
3366 char *mailbox = stream->mailbox, *
user;
3367 char buf[1024] =
"";
3368 unsigned long usage = 0, limit = 0;
3371 usage = pquota->usage;
3372 limit = pquota->limit;
3373 pquota = pquota->next;
3376 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)))) {
3381 ast_debug(3,
"User %s usage is %lu, limit is %lu\n", user, usage, limit);
3383 vms->quota_usage =
usage;
3384 vms->quota_limit = limit;
3387 static char *get_header_by_tag(
char *
header,
char *tag,
char *
buf,
size_t len)
3389 char *start, *eol_pnt;
3395 taglen = strlen(tag) + 1;
3403 memset(buf, 0, len);
3406 if ((eol_pnt = strchr(buf,
'\r')) || (eol_pnt = strchr(buf,
'\n')))
3411 static char *get_user_by_mailbox(
char *mailbox,
char *buf,
size_t len)
3413 char *start, *eol_pnt, *
quote;
3418 if (!(start = strstr(mailbox,
"/user=")))
3423 if (!(quote = strchr(buf,
'"'))) {
3424 if ((eol_pnt = strchr(buf,
'/')) || (eol_pnt = strchr(buf,
'}'))) {
3429 if ((eol_pnt = strchr(quote + 1,
'"'))) {
3440 pthread_once(&ts_vmstate.once, ts_vmstate.key_init);
3441 if ((vms_p = pthread_getspecific(ts_vmstate.key)) && !strcmp(vms_p->imapuser, vmu->imapuser) && !strcmp(vms_p->
username, vmu->
mailbox)) {
3444 ast_debug(5,
"Adding new vmstate for %s\n", vmu->imapuser);
3446 if (!(vms_p =
ast_calloc(1,
sizeof(*vms_p))))
3448 ast_copy_string(vms_p->imapuser, vmu->imapuser,
sizeof(vms_p->imapuser));
3449 ast_copy_string(vms_p->imapfolder, vmu->imapfolder,
sizeof(vms_p->imapfolder));
3450 ast_copy_string(vms_p->imapserver, vmu->imapserver,
sizeof(vms_p->imapserver));
3451 ast_copy_string(vms_p->imapport, vmu->imapport,
sizeof(vms_p->imapport));
3452 ast_copy_string(vms_p->imapflags, vmu->imapflags,
sizeof(vms_p->imapflags));
3455 vms_p->mailstream = NIL;
3456 vms_p->imapversion = vmu->imapversion;
3457 ast_debug(5,
"Copied %s to %s\n", vmu->imapuser, vms_p->imapuser);
3461 init_vm_state(vms_p);
3462 vmstate_insert(vms_p);
3466 static struct vm_state *get_vm_state_by_imapuser(
const char *user,
int interactive)
3468 struct vmstate *vlist =
NULL;
3472 pthread_once(&ts_vmstate.once, ts_vmstate.key_init);
3473 if ((vms = pthread_getspecific(ts_vmstate.key)) && !strcmp(vms->imapuser, user)) {
3481 ast_debug(3,
"error: vms is NULL for %s\n", user);
3484 if (vlist->vms->imapversion != imapversion) {
3488 if (!strcmp(vlist->vms->imapuser, user) && (interactive == 2 || vlist->vms->interactive == interactive)) {
3495 ast_debug(3,
"%s not found in vmstates\n", user);
3500 static struct vm_state *get_vm_state_by_mailbox(
const char *mailbox,
const char *context,
int interactive)
3503 struct vmstate *vlist =
NULL;
3504 const char *local_context =
S_OR(context,
"default");
3508 pthread_once(&ts_vmstate.once, ts_vmstate.key_init);
3509 if ((vms = pthread_getspecific(ts_vmstate.key)) &&
3510 !strcmp(vms->
username,mailbox) && !strcmp(vms->
context, local_context)) {
3518 ast_debug(3,
"error: vms is NULL for %s\n", mailbox);
3521 if (vlist->vms->imapversion != imapversion) {
3525 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);
3527 if (!strcmp(vlist->vms->username, mailbox) && !strcmp(vlist->vms->context, local_context) && vlist->vms->interactive == interactive) {
3535 ast_debug(3,
"%s not found in vmstates\n", mailbox);
3540 static void vmstate_insert(
struct vm_state *vms)
3548 if (vms->interactive == 1) {
3554 vms->vmArrayIndex = altvms->vmArrayIndex;
3559 vms->persist_vms = altvms;
3561 #ifdef REALLY_FAST_EVEN_IF_IT_MEANS_RESOURCE_LEAKS 3562 vms->mailstream = altvms->mailstream;
3564 vms->mailstream = NIL;
3575 ast_debug(3,
"Inserting vm_state for user:%s, mailbox %s\n", vms->imapuser, vms->
username);
3582 static void vmstate_delete(
struct vm_state *vms)
3584 struct vmstate *vc =
NULL;
3589 if (vms->interactive == 1 && (altvms = vms->persist_vms)) {
3593 altvms->updated = 1;
3594 vms->mailstream = mail_close(vms->mailstream);
3600 ast_debug(3,
"Removing vm_state for user:%s, mailbox %s\n", vms->imapuser, vms->
username);
3604 if (vc->vms == vms) {
3615 vc->vms->msgArray =
NULL;
3616 vc->vms->msg_array_max = 0;
3624 static void set_update(MAILSTREAM * stream)
3627 char *mailbox = stream->mailbox, *
user;
3628 char buf[1024] =
"";
3630 if (!(user = get_user_by_mailbox(mailbox, buf,
sizeof(buf))) || !(vms = get_vm_state_by_imapuser(user, 0))) {
3636 ast_debug(3,
"User %s mailbox set for update.\n", user);
3641 static void init_vm_state(
struct vm_state *vms)
3644 vms->msgArray =
ast_calloc(vms->msg_array_max,
sizeof(
long));
3645 if (!vms->msgArray) {
3647 vms->msg_array_max = 0;
3649 vms->vmArrayIndex = 0;
3653 static int save_body(BODY *body,
struct vm_state *vms,
char *section,
char *
format,
int is_intro)
3657 char *
fn = is_intro ? vms->introfn : vms->
fn;
3658 unsigned long len = 0;
3659 unsigned long newlen = 0;
3662 if (!body || body == NIL)
3666 body_content = mail_fetchbody(vms->mailstream, vms->msgArray[vms->
curmsg], section, &len);
3670 "Msgno %ld, section %s. The body's content size %ld is huge (max %ld). User:%s, mailbox %s\n",
3674 if (body_content != NIL && len) {
3675 snprintf(filename,
sizeof(filename),
"%s.%s", fn, format);
3677 body_decoded = rfc822_base64((
unsigned char *) body_content, len, &newlen);
3679 if (!newlen || !body_decoded) {
3682 write_file(filename, (
char *) body_decoded, newlen);
3684 ast_debug(5,
"Body of message is NULL.\n");
3698 static void get_mailbox_delimiter(
struct vm_state *vms, MAILSTREAM *stream) {
3700 snprintf(tmp,
sizeof(tmp),
"{%s}",
S_OR(vms->imapserver, imapserver));
3701 mail_list(stream, tmp,
"*");
3711 static void check_quota(
struct vm_state *vms,
char *mailbox) {
3713 mail_parameters(
NULL, SET_QUOTA, (
void *) mm_parsequota);
3714 ast_debug(3,
"Mailbox name set to: %s, about to check quotas\n", mailbox);
3715 if (vms && vms->mailstream !=
NULL) {
3716 imap_getquotaroot(vms->mailstream, mailbox);
3739 #define MSG_ID_LEN 256 3751 struct generic_prepare_struct {
3759 struct generic_prepare_struct *gps = data;
3763 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->
con, &stmt);
3764 if (!SQL_SUCCEEDED(res)) {
3769 if (!SQL_SUCCEEDED(res)) {
3771 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
3774 for (i = 0; i < gps->argc; i++)
3775 SQLBindParameter(stmt, i + 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(gps->argv[i]), 0, gps->argv[i], 0,
NULL);
3780 static void odbc_update_msg_id(
char *dir,
int msg_num,
char *msg_id)
3785 char msg_num_str[20];
3786 char *argv[] = { msg_id, dir, msg_num_str };
3787 struct generic_prepare_struct gps = { .sql = sql, .argc = 3, .argv = argv };
3791 ast_log(
LOG_WARNING,
"Unable to update message ID for message %d in %s\n", msg_num, dir);
3795 snprintf(msg_num_str,
sizeof(msg_num_str),
"%d", msg_num);
3796 snprintf(sql,
sizeof(sql),
"UPDATE %s SET msg_id=? WHERE dir=? AND msgnum=?", odbc_table);
3801 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
3821 static int retrieve_file(
char *dir,
int msgnum)
3827 void *fdm = MAP_FAILED;
3828 SQLSMALLINT colcount = 0;
3835 SQLSMALLINT datatype;
3836 SQLSMALLINT decimaldigits;
3837 SQLSMALLINT nullable;
3846 char *argv[] = { dir, msgnums };
3847 struct generic_prepare_struct gps = { .sql = sql, .argc = 2, .argv = argv };
3857 c = strchr(fmt,
'|');
3860 if (!strcasecmp(fmt,
"wav49"))
3863 snprintf(msgnums,
sizeof(msgnums),
"%d", msgnum);
3870 snprintf(full_fn,
sizeof(full_fn),
"%s.txt", fn);
3872 if (!(f = fopen(full_fn,
"w+"))) {
3877 snprintf(full_fn,
sizeof(full_fn),
"%s.%s", fn, fmt);
3878 snprintf(sql,
sizeof(sql),
"SELECT * FROM %s WHERE dir=? AND msgnum=?", odbc_table);
3886 res = SQLFetch(stmt);
3887 if (!SQL_SUCCEEDED(res)) {
3888 if (res != SQL_NO_DATA) {
3891 goto bail_with_handle;
3897 goto bail_with_handle;
3900 res = SQLNumResultCols(stmt, &colcount);
3901 if (!SQL_SUCCEEDED(res)) {
3903 goto bail_with_handle;
3906 fprintf(f,
"[message]\n");
3907 for (x = 0; x < colcount; x++) {
3910 collen =
sizeof(coltitle);
3911 res = SQLDescribeCol(stmt, x + 1, (
unsigned char *) coltitle,
sizeof(coltitle), &collen,
3912 &datatype, &colsize, &decimaldigits, &nullable);
3913 if (!SQL_SUCCEEDED(res)) {
3915 goto bail_with_handle;
3917 if (!strcasecmp(coltitle,
"recording")) {
3919 res = SQLGetData(stmt, x + 1, SQL_BINARY, rowdata, 0, &colsize2);
3923 lseek(fd, fdlen - 1, SEEK_SET);
3924 if (write(fd, tmp, 1) != 1) {
3930 for (offset = 0; offset < colsize2; offset +=
CHUNKSIZE) {
3931 if ((fdm = mmap(
NULL,
CHUNKSIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset)) == MAP_FAILED) {
3933 goto bail_with_handle;
3935 res = SQLGetData(stmt, x + 1, SQL_BINARY, fdm,
CHUNKSIZE,
NULL);
3937 if (!SQL_SUCCEEDED(res)) {
3940 goto bail_with_handle;
3943 if (truncate(full_fn, fdlen) < 0) {
3948 res = SQLGetData(stmt, x + 1, SQL_CHAR, rowdata,
sizeof(rowdata),
NULL);
3949 if (res == SQL_NULL_DATA && !strcasecmp(coltitle,
"msg_id")) {
3953 snprintf(rowdata,
sizeof(rowdata),
"%s", msg_id);
3954 }
else if (res == SQL_NULL_DATA && !strcasecmp(coltitle,
"category")) {
3956 ast_debug(3,
"Ignoring null category column in ODBC voicemail retrieve_file.\n");
3958 }
else if (!SQL_SUCCEEDED(res)) {
3960 goto bail_with_handle;
3962 if (strcasecmp(coltitle,
"msgnum") && strcasecmp(coltitle,
"dir")) {
3963 fprintf(f,
"%s=%s\n", coltitle, rowdata);
3969 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
3983 odbc_update_msg_id(dir, msgnum, msg_id);
4007 char *argv[] = { dir };
4008 struct generic_prepare_struct gps = { .sql = sql, .argc = 1, .argv = argv };
4017 snprintf(sql,
sizeof(sql),
"SELECT msgnum FROM %s WHERE dir=? order by msgnum desc", odbc_table);
4025 res = SQLFetch(stmt);
4026 if (!SQL_SUCCEEDED(res)) {
4027 if (res == SQL_NO_DATA) {
4028 ast_log(
AST_LOG_DEBUG,
"Directory '%s' has no messages and therefore no index was retrieved.\n", dir);
4032 goto bail_with_handle;
4035 res = SQLGetData(stmt, 1, SQL_CHAR, rowdata,
sizeof(rowdata),
NULL);
4036 if (!SQL_SUCCEEDED(res)) {
4038 goto bail_with_handle;
4041 if (sscanf(rowdata,
"%30d", &x) != 1) {
4046 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
4063 static int message_exists(
char *dir,
int msgnum)
4071 char *argv[] = { dir, msgnums };
4072 struct generic_prepare_struct gps = { .sql = sql, .argc = 2, .argv = argv };
4081 snprintf(msgnums,
sizeof(msgnums),
"%d", msgnum);
4082 snprintf(sql,
sizeof(sql),
"SELECT COUNT(*) FROM %s WHERE dir=? AND msgnum=?", odbc_table);
4089 res = SQLFetch(stmt);
4090 if (!SQL_SUCCEEDED(res)) {
4092 goto bail_with_handle;
4095 res = SQLGetData(stmt, 1, SQL_CHAR, rowdata,
sizeof(rowdata),
NULL);
4096 if (!SQL_SUCCEEDED(res)) {
4098 goto bail_with_handle;
4101 if (sscanf(rowdata,
"%30d", &x) != 1) {
4106 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
4129 char *argv[] = { dir };
4130 struct generic_prepare_struct gps = { .sql = sql, .argc = 1, .argv = argv };
4139 snprintf(sql,
sizeof(sql),
"SELECT COUNT(*) FROM %s WHERE dir=?", odbc_table);
4146 res = SQLFetch(stmt);
4147 if (!SQL_SUCCEEDED(res)) {
4149 goto bail_with_handle;
4152 res = SQLGetData(stmt, 1, SQL_CHAR, rowdata,
sizeof(rowdata),
NULL);
4153 if (!SQL_SUCCEEDED(res)) {
4155 goto bail_with_handle;
4158 if (sscanf(rowdata,
"%30d", &x) != 1) {
4163 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
4180 static void delete_file(
const char *sdir,
int smsg)
4185 char *argv[] = {
NULL, msgnums };
4186 struct generic_prepare_struct gps = { .sql = sql, .argc = 2, .argv = argv };
4197 snprintf(msgnums,
sizeof(msgnums),
"%d", smsg);
4198 snprintf(sql,
sizeof(sql),
"DELETE FROM %s WHERE dir=? AND msgnum=?", odbc_table);
4203 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
4221 static void copy_file(
char *sdir,
int smsg,
char *ddir,
int dmsg,
char *dmailboxuser,
char *dmailboxcontext)
4229 char *argv[] = { ddir, msgnumd, msg_id, dmailboxuser, dmailboxcontext, sdir, msgnums };
4230 struct generic_prepare_struct gps = { .sql = sql, .argc = 7, .argv = argv };
4240 snprintf(msgnums,
sizeof(msgnums),
"%d", smsg);
4241 snprintf(msgnumd,
sizeof(msgnumd),
"%d", dmsg);
4242 snprintf(sql,
sizeof(sql),
"INSERT INTO %s (dir, msgnum, msg_id, 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);
4245 ast_log(
AST_LOG_WARNING,
"SQL Execute error!\n[%s] (You probably don't have MySQL 4.1 or later installed)\n\n", sql);
4247 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
4253 struct insert_data {
4256 const char *msgnums;
4261 const char *macrocontext;
4262 const char *callerid;
4263 const char *origtime;
4264 const char *duration;
4265 const char *mailboxuser;
4266 const char *mailboxcontext;
4267 const char *category;
4272 static SQLHSTMT insert_data_cb(
struct odbc_obj *obj,
void *vdata)
4274 struct insert_data *data = vdata;
4278 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->
con, &stmt);
4279 if (!SQL_SUCCEEDED(res)) {
4284 SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->dir), 0, (
void *) data->dir, 0,
NULL);
4285 SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->msgnums), 0, (
void *) data->msgnums, 0,
NULL);
4286 SQLBindParameter(stmt, 3, SQL_PARAM_INPUT, SQL_C_BINARY, SQL_LONGVARBINARY, data->datalen, 0, (
void *) data->data, data->datalen, &data->indlen);
4287 SQLBindParameter(stmt, 4, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->context), 0, (
void *) data->context, 0,
NULL);
4288 SQLBindParameter(stmt, 5, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->macrocontext), 0, (
void *) data->macrocontext, 0,
NULL);
4289 SQLBindParameter(stmt, 6, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->callerid), 0, (
void *) data->callerid, 0,
NULL);
4290 SQLBindParameter(stmt, 7, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->origtime), 0, (
void *) data->origtime, 0,
NULL);
4291 SQLBindParameter(stmt, 8, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->duration), 0, (
void *) data->duration, 0,
NULL);
4292 SQLBindParameter(stmt, 9, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->mailboxuser), 0, (
void *) data->mailboxuser, 0,
NULL);
4293 SQLBindParameter(stmt, 10, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->mailboxcontext), 0, (
void *) data->mailboxcontext, 0,
NULL);
4294 SQLBindParameter(stmt, 11, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->flag), 0, (
void *) data->flag, 0,
NULL);
4295 SQLBindParameter(stmt, 12, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->msg_id), 0, (
void *) data->msg_id, 0,
NULL);
4297 SQLBindParameter(stmt, 13, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->category), 0, (
void *) data->category, 0,
NULL);
4300 if (!SQL_SUCCEEDED(res)) {
4302 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
4322 static int store_file(
const char *dir,
const char *mailboxuser,
const char *mailboxcontext,
int msgnum)
4326 void *fdm = MAP_FAILED;
4337 struct insert_data idata = { .sql = sql, .msgnums = msgnums, .dir = dir, .mailboxuser = mailboxuser, .mailboxcontext = mailboxcontext,
4338 .context =
"", .macrocontext =
"", .callerid =
"", .origtime =
"", .duration =
"", .category =
"", .flag =
"", .msg_id =
"" };
4351 c = strchr(fmt,
'|');
4354 if (!strcasecmp(fmt,
"wav49"))
4356 snprintf(msgnums,
sizeof(msgnums),
"%d", msgnum);
4361 snprintf(full_fn,
sizeof(full_fn),
"%s.txt", fn);
4363 snprintf(full_fn,
sizeof(full_fn),
"%s.%s", fn, fmt);
4364 fd = open(full_fn, O_RDWR);
4375 idata.macrocontext =
"";
4378 idata.callerid =
"";
4381 idata.origtime =
"";
4384 idata.duration =
"";
4387 idata.category =
"";
4396 fdlen = lseek(fd, 0, SEEK_END);
4397 if (fdlen < 0 || lseek(fd, 0, SEEK_SET) < 0) {
4402 fdm = mmap(
NULL, fdlen, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
4403 if (fdm == MAP_FAILED) {
4409 idata.datalen = idata.indlen = fdlen;
4412 snprintf(sql,
sizeof(sql),
"INSERT INTO %s (dir,msgnum,recording,context,macrocontext,callerid,origtime,duration,mailboxuser,mailboxcontext,flag,msg_id,category) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)", odbc_table);
4414 snprintf(sql,
sizeof(sql),
"INSERT INTO %s (dir,msgnum,recording,context,macrocontext,callerid,origtime,duration,mailboxuser,mailboxcontext,flag,msg_id) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)", odbc_table);
4417 idata.origtime =
"0";
4421 idata.duration =
"0";
4425 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
4436 if (fdm != MAP_FAILED)
4456 static void rename_file(
char *sdir,
int smsg,
char *mailboxuser,
char *mailboxcontext,
char *ddir,
int dmsg)
4463 char *argv[] = { ddir, msgnumd, mailboxuser, mailboxcontext, sdir, msgnums };
4464 struct generic_prepare_struct gps = { .sql = sql, .argc = 6, .argv = argv };
4474 snprintf(msgnums,
sizeof(msgnums),
"%d", smsg);
4475 snprintf(msgnumd,
sizeof(msgnumd),
"%d", dmsg);
4476 snprintf(sql,
sizeof(sql),
"UPDATE %s SET dir=?, msgnum=?, mailboxuser=?, mailboxcontext=? WHERE dir=? AND msgnum=?", odbc_table);
4481 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
4497 static int remove_file(
char *dir,
int msgnum)
4504 snprintf(msgnums,
sizeof(msgnums),
"%d", msgnum);
4509 snprintf(full_fn,
sizeof(full_fn),
"%s.txt", fn);
4514 #ifndef IMAP_STORAGE 4529 struct dirent *vment =
NULL;
4534 if ((vmdir = opendir(dir))) {
4535 while ((vment = readdir(vmdir))) {
4536 if (strlen(vment->d_name) > 7 && !strncmp(vment->d_name + 7,
".txt", 4)) {
4559 snprintf(stxt,
sizeof(stxt),
"%s.txt", sfn);
4560 snprintf(dtxt,
sizeof(dtxt),
"%s.txt", dfn);
4583 struct dirent *msgdirent;
4592 if (!(msgdir = opendir(dir))) {
4596 while ((msgdirent = readdir(msgdir))) {
4597 if (sscanf(msgdirent->d_name,
"msg%30d.%3s", &msgdirint, extension) == 2 && !strcmp(extension,
"txt") && msgdirint <
MAXMSGLIMIT) {
4600 ast_debug(4,
"%s map[%d] = %d, count = %d\n", dir, msgdirint, map[msgdirint], stopcount);
4605 for (x = 0; x < vmu->
maxmsg; x++) {
4608 }
else if (map[x] == 0 && !stopcount) {
4618 #ifndef IMAP_STORAGE 4629 static int copy(
char *infile,
char *outfile)
4637 #ifdef HARDLINK_WHEN_POSSIBLE 4639 if (!link(infile, outfile)) {
4644 if ((ifd = open(infile, O_RDONLY)) < 0) {
4658 len = read(ifd, buf,
sizeof(buf));
4669 wrlen = write(ofd, buf, len);
4670 if (
errno == ENOMEM ||
errno == ENOSPC || wrlen != len) {
4698 const char *origmailbox =
"", *context =
"", *macrocontext =
"", *
exten =
"";
4699 const char *
priority =
"", *callerchan =
"", *callerid =
"", *origdate =
"";
4700 const char *origtime =
"", *category =
"", *duration =
"";
4703 snprintf(frompath2,
sizeof(frompath2),
"%s.txt", frompath);
4704 snprintf(topath2,
sizeof(topath2),
"%s.txt", topath);
4709 for (tmp = var;
tmp; tmp = tmp->
next) {
4710 if (!strcasecmp(tmp->
name,
"origmailbox")) {
4711 origmailbox = tmp->
value;
4712 }
else if (!strcasecmp(tmp->
name,
"context")) {
4713 context = tmp->
value;
4714 }
else if (!strcasecmp(tmp->
name,
"macrocontext")) {
4715 macrocontext = tmp->
value;
4716 }
else if (!strcasecmp(tmp->
name,
"exten")) {
4718 }
else if (!strcasecmp(tmp->
name,
"priority")) {
4719 priority = tmp->
value;
4720 }
else if (!strcasecmp(tmp->
name,
"callerchan")) {
4721 callerchan = tmp->
value;
4722 }
else if (!strcasecmp(tmp->
name,
"callerid")) {
4723 callerid = tmp->
value;
4724 }
else if (!strcasecmp(tmp->
name,
"origdate")) {
4725 origdate = tmp->
value;
4726 }
else if (!strcasecmp(tmp->
name,
"origtime")) {
4727 origtime = tmp->
value;
4728 }
else if (!strcasecmp(tmp->
name,
"category")) {
4729 category = tmp->
value;
4730 }
else if (!strcasecmp(tmp->
name,
"duration")) {
4731 duration = tmp->
value;
4734 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);
4736 copy(frompath2, topath2);
4754 txtsize = (strlen(file) + 5)*
sizeof(
char);
4762 snprintf(txt, txtsize,
"%s.txt", file);
4797 if (!
inbuf(bio, fi))
4810 if (fputs(
ENDL, so) == EOF) {
4817 if (putc(((
unsigned char) c), so) == EOF) {
4837 static const unsigned char dtable[] = {
'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
'I',
'J',
'K',
4838 'L',
'M',
'N',
'O',
'P',
'Q',
'R',
'S',
'T',
'U',
'V',
'W',
'X',
'Y',
'Z',
'a',
'b',
'c',
'd',
'e',
'f',
4839 'g',
'h',
'i',
'j',
'k',
'l',
'm',
'n',
'o',
'p',
'q',
'r',
's',
't',
'u',
'v',
'w',
'x',
'y',
'z',
'0',
4840 '1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'+',
'/'};
4845 memset(&bio, 0,
sizeof(bio));
4848 if (!(fi = fopen(filename,
"rb"))) {
4854 unsigned char igroup[3], ogroup[4];
4857 memset(igroup, 0,
sizeof(igroup));
4859 for (n = 0; n < 3; n++) {
4860 if ((c =
inchar(&bio, fi)) == EOF) {
4865 igroup[n] = (
unsigned char) c;
4869 ogroup[0]= dtable[igroup[0] >> 2];
4870 ogroup[1]= dtable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)];
4871 ogroup[2]= dtable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)];
4872 ogroup[3]= dtable[igroup[2] & 0x3F];
4881 for (i = 0; i < 4; i++)
4882 ochar(&bio, ogroup[i], so);
4888 if (fputs(
ENDL, so) == EOF) {
4895 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)
4899 char fromdir[256], fromfile[256];
4901 const char *origcallerid, *origtime;
4902 char origcidname[80], origcidnum[80], origdate[80];
4909 snprintf(num,
sizeof(num),
"%d", msgnum);
4923 make_file(fromfile,
sizeof(fromfile), fromdir, msgnum - 1);
4924 if (strlen(fromfile) <
sizeof(fromfile) - 5) {
4925 strcat(fromfile,
".txt");
4928 ast_debug(1,
"Config load for message text file '%s' failed\n", fromfile);
4934 ast_callerid_split(origcallerid, origcidname,
sizeof(origcidname), origcidnum,
sizeof(origcidnum));
4939 if ((origtime =
ast_variable_retrieve(msg_cfg,
"message",
"origtime")) && sscanf(origtime,
"%30d", &inttime) == 1) {
4940 struct timeval tv = { inttime, };
4963 for (ptr = from; *ptr; ptr++) {
4964 if (*ptr ==
'"' || *ptr ==
'\\') {
5004 for (; *
str; str++) {
5005 if (*str > 126 || *str < 32 || strchr(
"()<>@,:;/\"[]?.=", *str)) {
5032 int first_section = 1;
5036 for (; *start; start++) {
5037 int need_encoding = 0;
5038 if (*start < 33 || *start > 126 || strchr(
"()<>@,:;/\"[]?.=_", *start)) {
5041 if ((first_section && need_encoding && preamble +
ast_str_strlen(tmp) > 70) ||
5042 (first_section && !need_encoding && preamble +
ast_str_strlen(tmp) > 72) ||
5044 (!first_section && !need_encoding &&
ast_str_strlen(tmp) > 72)) {
5050 if (need_encoding && *start ==
' ') {
5052 }
else if (need_encoding) {
5091 const char *fromfolder,
5098 int attach_user_voicemail,
5100 const char *category,
5111 char enc_cidnum[256] =
"", enc_cidname[256] =
"";
5113 char *greeting_attachment;
5119 if (!str1 || !str2) {
5131 gethostname(host,
sizeof(host) - 1);
5133 if (strchr(srcemail,
'@')) {
5136 snprintf(who,
sizeof(who),
"%s@%s", srcemail, host);
5139 greeting_attachment = strrchr(
ast_strdupa(attach),
'/');
5140 if (greeting_attachment) {
5141 *greeting_attachment++ =
'\0';
5144 snprintf(dur,
sizeof(dur),
"%d:%02d", duration / 60, duration % 60);
5146 fprintf(p,
"Date: %s" ENDL, date);
5156 prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, enc_cidnum, enc_cidname, dur, date, category, flag);
5178 fprintf(p,
"From: Asterisk PBX <%s>" ENDL, who);
5184 while ((email =
strsep(&emailsbuf,
"|"))) {
5185 char *next = emailsbuf;
5203 fprintf(p,
"Subject: New greeting '%s' on %s." ENDL, greeting_attachment, date);
5208 prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
5231 fprintf(p,
"Subject: New message %d in mailbox %s" ENDL, msgnum + 1, mailbox);
5233 fprintf(p,
"Subject: New %s message %d in mailbox %s" ENDL, flag, msgnum + 1, mailbox);
5237 fprintf(p,
"Subject: [PBX]: New message %d in mailbox %s" ENDL, msgnum + 1, mailbox);
5239 fprintf(p,
"Subject: [PBX]: New %s message %d in mailbox %s" ENDL, flag, msgnum + 1, mailbox);
5243 fprintf(p,
"Message-ID: <Asterisk-%d-%u-%s-%d@%s>" ENDL, msgnum + 1,
5244 (
unsigned int)
ast_random(), mailbox, (
int) getpid(), host);
5247 fprintf(p,
"X-Asterisk-VM-Message-Num: %d" ENDL, msgnum + 1);
5249 fprintf(p,
"X-Asterisk-VM-Server-Name: %s" ENDL, fromstring);
5250 fprintf(p,
"X-Asterisk-VM-Context: %s" ENDL, context);
5252 fprintf(p,
"X-Asterisk-VM-Extension: %s" ENDL, (!
ast_strlen_zero(vmu->imapvmshareid) ? vmu->imapvmshareid : mailbox));
5254 fprintf(p,
"X-Asterisk-VM-Extension: %s" ENDL, mailbox);
5257 fprintf(p,
"X-Asterisk-VM-Flag: %s" ENDL,
S_OR(flag,
""));
5259 fprintf(p,
"X-Asterisk-VM-Caller-ID-Num: %s" ENDL, enc_cidnum);
5260 fprintf(p,
"X-Asterisk-VM-Caller-ID-Name: %s" ENDL, enc_cidname);
5261 fprintf(p,
"X-Asterisk-VM-Duration: %d" ENDL, duration);
5263 fprintf(p,
"X-Asterisk-VM-Category: %s" ENDL, category);
5265 fprintf(p,
"X-Asterisk-VM-Category: " ENDL);
5267 fprintf(p,
"X-Asterisk-VM-Message-Type: %s" ENDL, msgnum > -1 ?
"Message" : greeting_attachment);
5268 fprintf(p,
"X-Asterisk-VM-Orig-date: %s" ENDL, date);
5269 fprintf(p,
"X-Asterisk-VM-Orig-time: %ld" ENDL, (
long) time(
NULL));
5270 fprintf(p,
"X-Asterisk-VM-Message-ID: %s" ENDL, msg_id);
5273 fprintf(p,
"X-Asterisk-CallerID: %s" ENDL, enc_cidnum);
5276 fprintf(p,
"X-Asterisk-CallerIDName: %s" ENDL, enc_cidname);
5278 fprintf(p,
"MIME-Version: 1.0" ENDL);
5279 if (attach_user_voicemail) {
5281 snprintf(bound,
sizeof(bound),
"----voicemail_%d%s%d%u", msgnum + 1, mailbox,
5282 (
int) getpid(), (
unsigned int)
ast_random());
5284 fprintf(p,
"Content-Type: multipart/mixed; boundary=\"%s\"" ENDL, bound);
5285 fprintf(p,
ENDL ENDL "This is a multi-part message in MIME format." ENDL ENDL);
5286 fprintf(p,
"--%s" ENDL, bound);
5288 fprintf(p,
"Content-Type: text/plain; charset=%s" ENDL "Content-Transfer-Encoding: 8bit" ENDL ENDL, charset);
5290 fprintf(p,
"This message is to let you know that your greeting '%s' was changed on %s." ENDL
5291 "Please do not delete this message, lest your greeting vanish with it." ENDL ENDL,
5292 greeting_attachment, date);
5293 }
else if (emailbody || vmu->
emailbody) {
5297 prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
5305 if ((next = strchr(line,
'\n'))) {
5308 fprintf(p,
"%s" ENDL, line);
5320 if (strcmp(vmu->
mailbox, mailbox)) {
5325 char fromdir[256], fromfile[256], origdate[80] =
"", origcallerid[80] =
"";
5329 make_file(fromfile,
sizeof(fromfile), fromdir, msgnum);
5330 if (strlen(fromfile) <
sizeof(fromfile) - 5) {
5331 strcat(fromfile,
".txt");
5340 if ((v =
ast_variable_retrieve(msg_cfg,
"message",
"origtime")) && sscanf(v,
"%30d", &inttime) == 1) {
5341 struct timeval tv = { inttime, };
5346 fprintf(p,
"Dear %s:" ENDL ENDL
"\tJust wanted to let you know you were just forwarded" 5347 " a %s long message (number %d)" ENDL
"in mailbox %s from %s, on %s" ENDL
5348 "(originally sent by %s on %s)" ENDL
"so you might want to check it when you get a" 5349 " chance. Thanks!" ENDL ENDL
"\t\t\t\t--Asterisk" ENDL ENDL, vmu->
fullname, dur,
5350 msgnum + 1, mailbox, (cidname ? cidname : (cidnum ? cidnum :
"an unknown caller")),
5351 date, origcallerid, origdate);
5358 fprintf(p,
"Dear %s:" ENDL ENDL
"\tJust wanted to let you know you were just left a " 5359 "%s long message (number %d)" ENDL
"in mailbox %s from %s, on %s so you might" ENDL
5360 "want to check it when you get a chance. Thanks!" ENDL ENDL
"\t\t\t\t--Asterisk" 5361 ENDL ENDL, vmu->
fullname, dur, msgnum + 1, mailbox,
5362 (cidname ? cidname : (cidnum ? cidnum :
"an unknown caller")), date);
5366 if (imap || attach_user_voicemail) {
5368 snprintf(filename,
sizeof(filename),
"msg%04d.%s", msgnum, format);
5369 ast_debug(5,
"creating second attachment filename %s\n", filename);
5370 add_email_attachment(p, vmu, format, attach, greeting_attachment, mailbox, bound, filename, 0, msgnum);
5371 snprintf(filename,
sizeof(filename),
"msgintro%04d.%s", msgnum, format);
5372 ast_debug(5,
"creating attachment filename %s\n", filename);
5373 add_email_attachment(p, vmu, format, attach2, greeting_attachment, mailbox, bound, filename, 1, msgnum);
5375 snprintf(filename,
sizeof(filename),
"msg%04d.%s", msgnum, format);
5376 ast_debug(5,
"creating attachment filename %s, no second attachment.\n", filename);
5377 add_email_attachment(p, vmu, format, attach, greeting_attachment, mailbox, bound, filename, 1, msgnum);
5388 char *file_to_delete =
NULL, *dir_to_delete =
NULL;
5392 char altformat[80] =
"";
5396 char *mime_type = (!strcasecmp(format,
"ogg")) ?
"application/" :
"audio/x-";
5399 snprintf(fname,
sizeof(fname),
"%s.%s", attach, format);
5402 c = strchr(altformat,
'|');
5407 snprintf(altfname,
sizeof(altfname),
"%s.%s", attach, altformat);
5421 res = snprintf(sox_gain_tmpdir,
sizeof(sox_gain_tmpdir),
"%s/vm-gain-XXXXXX", tmpdir);
5422 if (res >=
sizeof(sox_gain_tmpdir)) {
5423 ast_log(
LOG_ERROR,
"Failed to create temporary directory path %s: Out of buffer space\n", tmpdir);
5427 if (
mkdtemp(sox_gain_tmpdir)) {
5431 ast_debug(3,
"sox_gain_tmpdir: %s\n", sox_gain_tmpdir);
5434 dir_to_delete = sox_gain_tmpdir;
5436 res = snprintf(fname,
sizeof(fname),
"%s/output.%s", sox_gain_tmpdir, format);
5437 if (res >=
sizeof(fname)) {
5438 ast_log(
LOG_ERROR,
"Failed to create filename buffer for %s/output.%s: Too long\n", sox_gain_tmpdir, format);
5443 res = snprintf(sox_gain_cmd,
sizeof(sox_gain_cmd),
"sox -v %.4f %s.%s %s",
5444 vmu->
volgain, attach, format, fname);
5446 if (!strcasecmp(format,
"wav")) {
5448 res = snprintf(sox_gain_cmd,
sizeof(sox_gain_cmd),
"sox -v %.4f %s.%s -e signed-integer -b 16 %s",
5449 vmu->
volgain, attach, altformat, fname);
5451 res = snprintf(sox_gain_cmd,
sizeof(sox_gain_cmd),
"sox %s.%s -e signed-integer -b 16 %s",
5452 attach, altformat, fname);
5456 res = snprintf(sox_gain_cmd,
sizeof(sox_gain_cmd),
"sox -v %.4f %s.%s %s",
5457 vmu->
volgain, attach, altformat, fname);
5459 res = snprintf(sox_gain_cmd,
sizeof(sox_gain_cmd),
"sox %s.%s %s",
5460 attach, altformat, fname);
5465 if (res >=
sizeof(sox_gain_cmd)) {
5466 ast_log(
LOG_ERROR,
"Failed to generate sox command, out of buffer space\n");
5473 file_to_delete = fname;
5474 ast_debug(3,
"VOLGAIN: Stored at: %s - Level: %.4f - Mailbox: %s\n", fname, vmu->
volgain, mailbox);
5476 ast_log(
LOG_WARNING,
"Sox failed to re-encode %s: %s (have you installed support for all sox file formats?)\n",
5478 soxstatus == 1 ?
"Problem with command line options" :
"An error occurred during file processing");
5486 if (!file_to_delete) {
5487 res = snprintf(fname,
sizeof(fname),
"%s.%s", attach, format);
5488 if (res >=
sizeof(fname)) {
5489 ast_log(
LOG_ERROR,
"Failed to create filename buffer for %s.%s: Too long\n", attach, format);
5494 fprintf(p,
"--%s" ENDL, bound);
5496 fprintf(p,
"Content-Type: %s%s; name=\"%s\"" ENDL, mime_type, format, filename);
5498 fprintf(p,
"Content-Type: %s%s; name=\"%s.%s\"" ENDL, mime_type, format, greeting_attachment, format);
5499 fprintf(p,
"Content-Transfer-Encoding: base64" ENDL);
5500 fprintf(p,
"Content-Description: Voicemail sound attachment." ENDL);
5502 fprintf(p,
"Content-Disposition: attachment; filename=\"%s\"" ENDL ENDL, filename);
5504 fprintf(p,
"Content-Disposition: attachment; filename=\"%s.%s\"" ENDL ENDL, greeting_attachment, format);
5507 fprintf(p, ENDL ENDL
"--%s--" ENDL
"." ENDL, bound);
5509 if (file_to_delete) {
5510 unlink(file_to_delete);
5513 if (dir_to_delete) {
5514 rmdir(dir_to_delete);
5525 const char *fromfolder,
5532 int attach_user_voicemail,
5534 const char *category,
5539 char tmp[80] =
"/tmp/astmail-XXXXXX";
5553 if (!strcmp(format,
"wav49"))
5555 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));
5562 make_email_file(p, srcemail, vmu, msgnum, context, mailbox, fromfolder, cidnum, cidname, attach, attach2, format, duration, attach_user_voicemail, chan, category, 0, flag, msg_id);
5564 snprintf(tmp2,
sizeof(tmp2),
"( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
5566 ast_debug(1,
"Sent mail to %s with command '%s'\n", vmu->
email, mailcmd);
5571 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)
5573 char enc_cidnum[256], enc_cidname[256];
5578 char tmp[80] =
"/tmp/astmail-XXXXXX";
5584 if (!str1 || !str2) {
5603 gethostname(host,
sizeof(host)-1);
5604 if (strchr(srcemail,
'@')) {
5607 snprintf(who,
sizeof(who),
"%s@%s", srcemail, host);
5609 snprintf(dur,
sizeof(dur),
"%d:%02d", duration / 60, duration % 60);
5611 fprintf(p,
"Date: %s\n", date);
5620 prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, enc_cidnum, enc_cidname, dur, date, category, flag);
5642 fprintf(p,
"From: Asterisk PBX <%s>" ENDL, who);
5664 prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
5687 fprintf(p,
"Subject: New VM\n\n");
5689 fprintf(p,
"Subject: New %s VM\n\n", flag);
5696 prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, cidnum, cidname, dur, date, category, flag);
5704 fprintf(p,
"New %s long %s msg in box %s\n" 5705 "from %s, on %s", dur, flag, mailbox, (cidname ? cidname : (cidnum ? cidnum :
"unknown")), date);
5709 snprintf(tmp2,
sizeof(tmp2),
"( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
5711 ast_debug(1,
"Sent page to %s with command '%s'\n", pager, mailcmd);
5733 return ast_strftime(s, len,
"%a %b %e %r UTC %Y", &tm);
5742 snprintf(fn,
sizeof(fn),
"%s%s/%s/greet", VM_SPOOL_DIR, context, ext);
5744 if ((res =
create_dirpath(dest,
sizeof(dest), context, ext,
""))) {
5777 static int count_messages_in_folder(
struct odbc_obj *odbc,
const char *context,
const char *mailbox,
const char *folder,
int *messages)
5782 SQLHSTMT stmt =
NULL;
5783 struct generic_prepare_struct gps = { .sql = sql, .argc = 0 };
5789 snprintf(sql,
sizeof(sql),
"SELECT COUNT(*) FROM %s WHERE dir = '%s%s/%s/%s'", odbc_table, VM_SPOOL_DIR, context, mailbox, folder);
5794 res = SQLFetch(stmt);
5795 if (!SQL_SUCCEEDED(res)) {
5797 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
5800 res = SQLGetData(stmt, 1, SQL_CHAR, rowdata,
sizeof(rowdata),
NULL);
5801 if (!SQL_SUCCEEDED(res)) {
5803 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
5807 *messages = atoi(rowdata);
5808 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
5813 static int inboxcount2(
const char *mailbox,
int *urgentmsgs,
int *newmsgs,
int *oldmsgs)
5832 if (strchr(mailbox,
' ') || strchr(mailbox,
',')) {
5835 while ((next =
strsep(&remaining,
" ,"))) {
5852 context = strchr(tmp,
'@');
5857 context =
"default";
5865 if (count_messages_in_folder(obj, context, tmp,
"INBOX", newmsgs)
5866 || count_messages_in_folder(obj, context, tmp,
"Old", oldmsgs)
5867 || count_messages_in_folder(obj, context, tmp,
"Urgent", urgentmsgs)) {
5884 static int messagecount(
const char *mailbox_id,
const char *folder)
5891 SQLHSTMT stmt =
NULL;
5894 struct generic_prepare_struct gps = { .sql = sql, .argc = 0 };
5912 if (!strcmp(folder,
"INBOX")) {
5913 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);
5915 snprintf(sql,
sizeof(sql),
"SELECT COUNT(*) FROM %s WHERE dir = '%s%s/%s/%s'", odbc_table, VM_SPOOL_DIR, context, mailbox, folder);
5923 res = SQLFetch(stmt);
5924 if (!SQL_SUCCEEDED(res)) {
5926 goto bail_with_handle;
5928 res = SQLGetData(stmt, 1, SQL_CHAR, rowdata,
sizeof(rowdata),
NULL);
5929 if (!SQL_SUCCEEDED(res)) {
5931 goto bail_with_handle;
5933 nummsgs = atoi(rowdata);
5936 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
5957 while ((mailbox =
strsep(&parse,
",&"))) {
5965 #ifndef IMAP_STORAGE 5985 const char *frombox =
mbox(vmu, imbox);
5986 const char *userfolder;
5993 userfolder =
"Urgent";
5995 userfolder = dest_folder;
5997 userfolder =
"INBOX";
6007 make_file(frompath,
sizeof(frompath), fromdir, msgnum);
6015 make_file(topath,
sizeof(topath), todir, recipmsgnum);
6016 #ifndef ODBC_STORAGE 6018 COPY(fromdir, msgnum, todir, recipmsgnum, recip->
mailbox, recip->
context, frompath, topath);
6025 STORE(todir, recip->
mailbox, recip->
context, recipmsgnum, chan, recip, fmt, duration,
NULL,
NULL,
NULL);
6027 #ifndef ODBC_STORAGE 6046 #if !(defined(IMAP_STORAGE) || defined(ODBC_STORAGE)) 6061 static int __has_voicemail(
const char *context,
const char *mailbox,
const char *folder,
int shortcircuit)
6078 context =
"default";
6080 c = (
char *)context;
6081 m = (
char *)mailbox;
6094 snprintf(fn,
sizeof(fn),
"%s%s/%s/%s", VM_SPOOL_DIR, c, m, folder);
6096 if (!(dir = opendir(fn)))
6099 while ((de = readdir(dir))) {
6100 if (!strncasecmp(de->d_name,
"msg", 3)) {
6104 }
else if (!strncasecmp(de->d_name + 8,
"txt", 3)) {
6131 while ((box =
strsep(&tmp2,
",&"))) {
6132 if ((context = strchr(box,
'@')))
6135 context =
"default";
6139 if (!strcmp(folder,
"INBOX") &&
__has_voicemail(context, box,
"Urgent", 1)) {
6154 static int inboxcount2(
const char *mailbox,
int *urgentmsgs,
int *newmsgs,
int *oldmsgs)
6174 if (strchr(mailbox,
',')) {
6175 int tmpnew, tmpold, tmpurgent;
6180 while ((cur =
strsep(&mb,
", "))) {
6182 if (
inboxcount2(cur, urgentmsgs ? &tmpurgent :
NULL, newmsgs ? &tmpnew : NULL, oldmsgs ? &tmpold : NULL)) {
6192 *urgentmsgs += tmpurgent;
6202 if ((context = strchr(tmp,
'@'))) {
6205 context =
"default";
6224 static int inboxcount(
const char *mailbox,
int *newmsgs,
int *oldmsgs)
6227 int res =
inboxcount2(mailbox, &urgentmsgs, newmsgs, oldmsgs);
6229 *newmsgs += urgentmsgs;
6236 char arguments[255];
6237 char ext_context[256] =
"";
6238 int newvoicemails = 0, oldvoicemails = 0, urgentvoicemails = 0;
6242 snprintf(ext_context,
sizeof(ext_context),
"%s@%s", extension, context);
6254 if (!strncmp(mwi_msg->
cause,
"INV", 3))
6256 else if (!strncmp(mwi_msg->
cause,
"BLK", 3))
6261 ast_debug(1,
"Successfully executed SMDI MWI change for %s\n", extension);
6266 if (
inboxcount2(ext_context, &urgentvoicemails, &newvoicemails, &oldvoicemails)) {
6267 ast_log(
AST_LOG_ERROR,
"Problem in calculating number of voicemail messages available for extension %s\n", extension);
6269 snprintf(arguments,
sizeof(arguments),
"%s %s %s %d %d %d &",
6270 externnotify,
S_OR(context,
"\"\""),
6271 extension, newvoicemails,
6272 oldvoicemails, urgentvoicemails);
6273 ast_debug(1,
"Executing %s\n", arguments);
6286 signed char record_gain;
6298 snprintf(dst,
MSG_ID_LEN,
"%ld-%08x", (
long) time(
NULL), unique_counter);
6332 char ext_context[256] =
"";
6349 const char *category =
NULL;
6358 memset(&svm, 0,
sizeof(svm));
6370 duration = (int) (framelength / sample_rate);
6379 if (duration < recipient->minsecs) {
6380 ast_log(
LOG_NOTICE,
"Copying recording to voicemail %s@%s skipped because duration was shorter than " 6381 "minmessage of recipient\n", recdata->
mailbox, recdata->
context);
6391 snprintf(tmptxtfile,
sizeof(tmptxtfile),
"%s/XXXXXX", tmpdir);
6392 txtdes = mkstemp(tmptxtfile);
6402 txt = fdopen(txtdes,
"w+");
6408 "; Message Information file\n" 6433 date, (
long) time(
NULL),
6458 snprintf(ext_context,
sizeof(ext_context),
"%s@%s", recipient->
mailbox, recipient->
context);
6462 res =
inboxcount(ext_context, &newmsgs, &oldmsgs);
6469 if (!(vms = get_vm_state_by_mailbox(recipient->
mailbox, recipient->
context, 0))) {
6474 if (!(vms = create_vm_state_from_user(recipient))) {
6484 msgnum = newmsgs + oldmsgs;
6485 ast_debug(3,
"Messagecount set to %d\n", msgnum);
6486 snprintf(destination,
sizeof(destination),
"%simap/msg%s%04d", VM_SPOOL_DIR, recipient->
mailbox, msgnum);
6490 if ((res = imap_check_limits(
NULL, vms, recipient, msgnum))) {
6517 ast_log(
LOG_ERROR,
"Couldn't lock directory %s. Voicemail will be lost.\n", dir);
6525 make_file(destination,
sizeof(destination), dir, msgnum);
6527 make_file(tmpaudiofile,
sizeof(tmpaudiofile), tmpdir, msgnum);
6530 ast_log(
LOG_ERROR,
"Audio file failed to copy to tmp dir. Probably low disk space.\n");
6541 ast_log(
LOG_ERROR,
"Audio file failed to move to destination directory. Permissions/Overlap?\n");
6549 snprintf(desttxtfile,
sizeof(desttxtfile),
"%s.txt", destination);
6550 rename(tmptxtfile, desttxtfile);
6567 "origmailbox", recdata->
mailbox,
6575 "origtime", time(
NULL),
6576 "category",
S_OR(category,
""),
6577 "filename", tmptxtfile,
6578 "duration", duration,
6582 STORE(dir, recipient->
mailbox, recipient->
context, msgnum,
NULL, recipient, fmt, 0, vms,
"", msg_id);
6604 int newmsgs, oldmsgs;
6616 int sound_duration = 0;
6620 int greeting_only = 0;
6629 char ext_context[256] =
"";
6632 char ecodes[17] =
"#";
6637 const char *category =
NULL;
6639 const char *alldtmf =
"0123456789ABCD*#";
6648 if ((context = strchr(ext,
'@'))) {
6650 tmpptr = strchr(context,
'&');
6652 tmpptr = strchr(ext,
'&');
6673 memset(&svm, 0,
sizeof(svm));
6674 if (!(vmu =
find_user(&svm, context, ext))) {
6688 if (strcmp(vmu->
context,
"default"))
6689 snprintf(ext_context,
sizeof(ext_context),
"%s@%s", ext, vmu->
context);
6699 snprintf(prefile,
sizeof(prefile),
"%s%s/%s/busy", VM_SPOOL_DIR, vmu->
context, ext);
6701 snprintf(prefile,
sizeof(prefile),
"%s%s/%s/unavail", VM_SPOOL_DIR, vmu->
context, ext);
6707 snprintf(tempfile,
sizeof(tempfile),
"%s%s/%s/temp", VM_SPOOL_DIR, vmu->
context, ext);
6720 #ifndef IMAP_STORAGE 6723 snprintf(dir,
sizeof(dir),
"%simap", VM_SPOOL_DIR);
6734 strncat(ecodes,
"0",
sizeof(ecodes) - strlen(ecodes) - 1);
6739 strncat(ecodes,
"0",
sizeof(ecodes) - strlen(ecodes) - 1);
6744 strncat(ecodes,
"0",
sizeof(ecodes) - strlen(ecodes) - 1);
6752 strncat(ecodes,
"*",
sizeof(ecodes) - strlen(ecodes) - 1);
6756 strncat(ecodes,
"*",
sizeof(ecodes) - strlen(ecodes) - 1);
6760 strncat(ecodes,
"*",
sizeof(ecodes) - strlen(ecodes) - 1);
6765 for (code = alldtmf; *code; code++) {
6768 if (strchr(ecodes, e[0]) ==
NULL 6772 strncat(ecodes, e,
sizeof(ecodes) - strlen(ecodes) - 1);
6782 RETRIEVE(prefile, -1, ext, context);
6787 if (success == -1) {
6789 ast_debug(1,
"Greeting not retrieved from database, but found in file storage. Inserting into database\n");
6794 ast_debug(1,
"%s doesn't exist, doing what we can\n", prefile);
6799 ast_debug(1,
"Hang up during prefile playback\n");
6839 if (ouseexten || ousemacro) {
6866 if (greeting_only) {
6867 ast_debug(3,
"Greetings only VM (maxmsg=0), Skipping voicemail recording\n");
6891 res =
inboxcount(ext_context, &newmsgs, &oldmsgs);
6898 if (!(vms = get_vm_state_by_mailbox(ext, context, 0))) {
6903 if (!(vms = create_vm_state_from_user(vmu))) {
6913 msgnum = newmsgs + oldmsgs;
6914 ast_debug(3,
"Messagecount set to %d\n", msgnum);
6915 snprintf(fn,
sizeof(fn),
"%simap/msg%s%04d", VM_SPOOL_DIR, vmu->
mailbox, msgnum);
6919 if ((res = imap_check_limits(chan, vms, vmu, msgnum))) {
6934 snprintf(tmptxtfile,
sizeof(tmptxtfile),
"%s/XXXXXX", tmpdir);
6935 txtdes = mkstemp(tmptxtfile);
6959 snprintf(origtime,
sizeof(origtime),
"%ld", (
long) time(
NULL));
6970 "priority", priority,
6972 "callerid", callerid,
6974 "origtime", origtime,
6975 "category",
S_OR(category,
""),
6976 "filename", tmptxtfile,
6981 txt = fdopen(txtdes,
"w+");
6991 "; Message Information file\n" 7015 date, (
long) time(
NULL),
7016 category ? category :
"",
7027 res =
play_record_review(chan,
NULL, tmptxtfile, vmu->
maxsecs, fmt, 1, vmu, &duration, &sound_duration,
NULL, options->
record_gain, vms, flag, msg_id, 0);
7033 if (!strcmp(flag,
"Urgent")) {
7038 fprintf(txt,
"flag=%s\n", flag);
7039 if (sound_duration < vmu->
minsecs) {
7041 ast_verb(3,
"Recording was %d seconds long but needs to be at least %d - abandoning\n", sound_duration, vmu->
minsecs);
7049 fprintf(txt,
"duration=%d\n", duration);
7058 ast_debug(1,
"The recorded media file is gone, so we should remove the .txt file too!\n");
7066 #ifndef IMAP_STORAGE 7072 #ifndef IMAP_STORAGE 7078 snprintf(txtfile,
sizeof(txtfile),
"%s.txt", fn);
7080 rename(tmptxtfile, txtfile);
7090 snprintf(tmpdur,
sizeof(tmpdur),
"%d", duration);
7097 STORE(dir, vmu->
mailbox, vmu->
context, msgnum, chan, vmu, fmt, duration, vms, flag, msg_id);
7105 exten =
strsep(&tmpptr,
"&");
7106 cntx = strchr(exten,
'@');
7111 memset(&recipu, 0,
sizeof(recipu));
7112 if ((recip =
find_user(&recipu, cntx, exten))) {
7144 }
else if (res > 0 && res !=
't')
7147 if (sound_duration < vmu->
minsecs)
7159 ast_debug(3,
"*** Checking if we can expunge, expungeonhangup set to %d\n", expungeonhangup);
7160 if (expungeonhangup == 1 && vms->mailstream !=
NULL) {
7162 #ifdef HAVE_IMAP_TK2006 7163 if (LEVELUIDPLUS (vms->mailstream)) {
7164 mail_expunge_full(vms->mailstream, NIL, EX_UID);
7167 mail_expunge(vms->mailstream);
7176 #if !defined(IMAP_STORAGE) 7189 for (x = 0, dest = 0; dest != stopcount && x < vmu->
maxmsg + 10; x++) {
7225 snprintf(sequence,
sizeof(sequence),
"%ld", vms->msgArray[msg]);
7227 ast_debug(3,
"Copying sequence %s to mailbox %s\n", sequence,
mbox(vmu, box));
7231 mail_setflag(vms->mailstream, sequence,
"\\Seen");
7233 mail_clearflag(vms->mailstream, sequence,
"\\Seen");
7244 imap_mailbox_name(mailbox,
sizeof(mailbox), vms, box, 1);
7245 if (vms->mailstream && !mail_status(vms->mailstream, mailbox, SA_UIDNEXT)) {
7246 if (mail_create(vms->mailstream, mailbox) != NIL) {
7252 if (init_mailstream(vms, curr_mbox) || !vms->mailstream) {
7257 res = !mail_move(vms->mailstream, sequence, (
char *)
mbox(vmu, box));
7259 res = !mail_copy(vms->mailstream, sequence, (
char *)
mbox(vmu, box));
7271 const char *dbox =
mbox(vmu, box);
7282 for (i = 1; i <= x; i++) {
7285 make_file(dfn,
sizeof(dfn), ddir, i - 1);
7299 if (strcmp(sfn, dfn)) {
7300 COPY(dir, msg, ddir, x, username, context, sfn, dfn);
7321 unsigned char buf[256];
7353 bytes += ast_adsi_logo(buf);
7397 for (x = 0; x < 5; x++) {
7398 snprintf(num,
sizeof(num),
"%d", x);
7426 ast_debug(1,
"Done downloading scripts...\n");
7434 ast_debug(1,
"Restarting session...\n");
7467 unsigned char buf[256];
7469 unsigned char keys[8];
7474 for (x = 0; x < 8; x++)
7493 unsigned char buf[256];
7495 unsigned char keys[8];
7500 for (x = 0; x < 8; x++)
7515 unsigned char buf[256];
7517 unsigned char keys[8];
7523 for (x = 0; x < 5; x++) {
7545 unsigned char buf[256];
7552 char datetime[21] =
"";
7555 unsigned char keys[8];
7563 snprintf(fn2,
sizeof(fn2),
"%s.txt", vms->
fn);
7564 f = fopen(fn2,
"r");
7567 if (!fgets((
char *) buf,
sizeof(buf), f)) {
7571 char *stringp =
NULL;
7572 stringp = (
char *) buf;
7574 val =
strsep(&stringp,
"=");
7576 if (!strcmp((
char *) buf,
"callerid"))
7578 if (!strcmp((
char *) buf,
"origdate"))
7586 for (x = 0; x < 5; x++)
7613 name =
"Unknown Caller";
7629 snprintf(buf1,
sizeof(buf1),
"%s%s", vms->
curbox,
7630 strcasecmp(vms->
curbox,
"INBOX") ?
" Messages" :
"");
7631 snprintf(buf2,
sizeof(buf2),
"Message %d of %d", vms->
curmsg + 1, vms->
lastmsg + 1);
7647 unsigned char buf[256];
7648 unsigned char keys[8];
7656 for (x = 0; x < 5; x++)
7698 unsigned char buf[256] =
"";
7699 char buf1[256] =
"",
buf2[256] =
"";
7701 unsigned char keys[8];
7704 char *newm = (vms->
newmessages == 1) ?
"message" :
"messages";
7705 char *oldm = (vms->
oldmessages == 1) ?
"message" :
"messages";
7709 snprintf(buf1,
sizeof(buf1),
"You have %d new", vms->
newmessages);
7711 strncat(buf1,
" and",
sizeof(buf1) - strlen(buf1) - 1);
7714 snprintf(
buf2,
sizeof(
buf2),
"%s.", newm);
7717 snprintf(buf1,
sizeof(buf1),
"You have %d old", vms->
oldmessages);
7718 snprintf(
buf2,
sizeof(
buf2),
"%s.", oldm);
7720 strcpy(buf1,
"You have no messages.");
7728 for (x = 0; x < 6; x++)
7745 unsigned char buf[256] =
"";
7746 char buf1[256] =
"",
buf2[256] =
"";
7748 unsigned char keys[8];
7751 char *mess = (vms->
lastmsg == 0) ?
"message" :
"messages";
7757 for (x = 0; x < 6; x++)
7766 snprintf(buf1,
sizeof(buf1),
"%s%s has", vms->
curbox,
7767 strcasecmp(vms->
curbox,
"INBOX") ?
" folder" :
"");
7772 strcpy(
buf2,
"no messages.");
7801 unsigned char buf[256];
7827 for (x = start; x < 5; x++) {
7833 snprintf(fn,
sizeof(fn),
"vm-%s",
mbox(
NULL, x));
7842 ast_verb(4,
"Failed to find file %s; falling back to INBOX\n", fn);
7870 for (x = start; x < 5; x++) {
7874 snprintf(fn,
sizeof(fn),
"vm-%s",
mbox(NULL, x));
7910 while (((res <
'0') || (res >
'9')) &&
7911 (res !=
'#') && (res >= 0) &&
7926 isprint(res) ? res :
'?', isprint(res) ? res :
'?');
7949 char *context,
signed char record_gain,
long *duration,
struct vm_state *vms,
char *flag)
7952 int retries = 0, prepend_duration = 0, already_recorded = 0;
7957 #ifndef IMAP_STORAGE 7958 signed char zero_gain = 0;
7960 const char *msg_id =
NULL;
7962 const char *duration_str;
7965 make_file(msgfile,
sizeof(msgfile), curdir, curmsg);
7966 strcpy(textfile, msgfile);
7967 strcpy(backup, msgfile);
7968 strcpy(backup_textfile, msgfile);
7969 strncat(textfile,
".txt",
sizeof(textfile) - strlen(textfile) - 1);
7970 strncat(backup,
"-bak",
sizeof(backup) - strlen(backup) - 1);
7971 strncat(backup_textfile,
"-bak.txt",
sizeof(backup_textfile) - strlen(backup_textfile) - 1);
7974 *duration = atoi(duration_str);
7979 while ((cmd >= 0) && (cmd !=
't') && (cmd !=
'*')) {
7990 make_file(vms->introfn,
sizeof(vms->introfn), curdir, curmsg);
7991 strncat(vms->introfn,
"intro",
sizeof(vms->introfn));
7994 cmd =
play_record_review(chan,
NULL, vms->introfn, vmu->
maxsecs, vm_fmts, 1, vmu, (
int *) duration,
NULL,
NULL, record_gain, vms, flag, msg_id, 1);
8003 make_file(msgfile,
sizeof(msgfile), curdir, curmsg);
8004 strcpy(textfile, msgfile);
8005 strncat(textfile,
".txt",
sizeof(textfile) - 1);
8015 #ifndef IMAP_STORAGE 8016 if (already_recorded) {
8018 copy(backup_textfile, textfile);
8022 copy(textfile, backup_textfile);
8025 already_recorded = 1;
8043 *duration = atoi(duration_str);
8045 if (prepend_duration) {
8048 char duration_buf[12];
8050 *duration += prepend_duration;
8052 snprintf(duration_buf,
sizeof(duration_buf),
"%ld", *duration);
8063 *vms->introfn =
'\0';
8072 already_recorded = 0;
8090 isprint(cmd) ? cmd :
'?', isprint(cmd) ? cmd :
'?');
8096 if (prepend_duration)
8097 *duration = prepend_duration;
8099 if (already_recorded && cmd == -1) {
8102 rename(backup_textfile, textfile);
8105 if (cmd ==
't' || cmd ==
'S')
8110 static void queue_mwi_event(
const char *channel_id,
const char *box,
int urgent,
int new,
int old)
8119 ast_debug(3,
"Queueing event for mailbox %s New: %d Old: %d\n", box,
new + urgent, old);
8129 strcpy(alias, mapping->
alias);
8132 ast_debug(3,
"Found alias mapping: %s -> %s\n", mapping->
alias, box);
8158 int newmsgs = 0, oldmsgs = 0, urgentmsgs = 0;
8159 const char *category;
8168 #ifndef IMAP_STORAGE 8171 snprintf(todir,
sizeof(todir),
"%simap", VM_SPOOL_DIR);
8173 make_file(fn,
sizeof(fn), todir, msgnum);
8174 snprintf(ext_context,
sizeof(ext_context),
"%s@%s", vmu->
mailbox, vmu->
context);
8193 char *msg_id =
NULL;
8199 snprintf(filename,
sizeof(filename),
"%s.txt", fn);
8207 if (attach_user_voicemail)
8211 sendmail(myserveremail, vmu, msgnum, vmu->
context, vmu->
mailbox,
mbox(vmu, 0), cidnum, cidname, fn,
NULL, fmt, duration, attach_user_voicemail, chan, category, flag, msg_id);
8213 if (attach_user_voicemail)
8218 sendpage(myserveremail, vmu->
pager, msgnum, vmu->
context, vmu->
mailbox,
mbox(vmu, 0), cidnum, cidname, duration, vmu, category, flag);
8222 DELETE(todir, msgnum, fn, vmu);
8277 char ecodes[16] =
"#";
8278 int res = 0, cmd = 0;
8283 const char mailbox_context[256];
8284 int saved_messages = 0;
8285 int valid_extensions = 0;
8288 char urgent_str[7] =
"";
8289 int prompt_played = 0;
8290 #ifndef IMAP_STORAGE 8294 ast_copy_string(urgent_str, urgent ?
"Urgent" :
"",
sizeof(urgent_str));
8297 if (vms ==
NULL)
return -1;
8302 while (!res && !valid_extensions) {
8303 int use_directory = 0;
8308 while ((cmd >= 0) && !done ){
8338 isprint(cmd) ? cmd :
'?', isprint(cmd) ? cmd :
'?');
8341 if (cmd < 0 || cmd ==
't')
8345 if (use_directory) {
8348 struct ast_app* directory_app;
8351 if (directory_app) {
8352 char vmcontext[256];
8362 snprintf(vmcontext,
sizeof(vmcontext),
"%s,,v", context ? context :
"default");
8363 res =
pbx_exec(chan, directory_app, vmcontext);
8379 if (res || prompt_played > 4)
8381 if ((res =
ast_readstring(chan, username,
sizeof(username) - 1, 2000, 10000,
"#")) < 0)
8389 s =
strsep(&stringp,
"*");
8391 valid_extensions = 1;
8393 snprintf((
char*)mailbox_context,
sizeof(mailbox_context),
"%s@%s", s, context ? context :
"default");
8394 if ((is_new_message == 1 || strcmp(s, sender->
mailbox)) && (receiver =
find_user(
NULL, context, s))) {
8399 if (
inboxcount(mailbox_context, &newmsgs, &oldmsgs)) {
8400 ast_log(
LOG_ERROR,
"Problem in calculating number of voicemail messages available for extension %s\n", mailbox_context);
8403 valid_extensions = 0;
8407 if (!(dstvms = get_vm_state_by_mailbox(s, context, 0))) {
8408 if (!(dstvms = create_vm_state_from_user(receiver))) {
8412 valid_extensions = 0;
8416 check_quota(dstvms, imapfolder);
8417 if (dstvms->quota_limit && dstvms->quota_usage >= dstvms->quota_limit) {
8418 ast_log(
LOG_NOTICE,
"Mailbox '%s' is exceeded quota %u >= %u\n", mailbox_context, dstvms->quota_usage, dstvms->quota_limit);
8420 valid_extensions = 0;
8429 if ((newmsgs + oldmsgs) >= capacity) {
8430 ast_log(
LOG_NOTICE,
"Mailbox '%s' is full with capacity of %d, prompting for another extension.\n", mailbox_context, capacity);
8432 valid_extensions = 0;
8453 valid_extensions = 0;
8458 snprintf(fn,
sizeof(fn),
"%s%s/%s/greet", VM_SPOOL_DIR, receiver->
context, s);
8471 s =
strsep(&stringp,
"*");
8474 if (valid_extensions)
8480 if (is_new_message == 1) {
8483 snprintf(mailbox,
sizeof(mailbox),
"%s@%s", username, context);
8486 memset(&leave_options, 0,
sizeof(leave_options));
8494 int copy_msg_result = 0;
8498 const char *msg_id =
NULL;
8501 memcpy(&vmstmp, vms,
sizeof(vmstmp));
8505 make_file(filename,
sizeof(filename), dir, curmsg);
8506 strncat(filename,
".txt",
sizeof(filename) - strlen(filename) - 1);
8514 cmd =
vm_forwardoptions(chan, sender, vmstmp.
curdir, curmsg, vmfmts,
S_OR(context,
"default"), record_gain, &duration, &vmstmp, urgent_str);
8518 int attach_user_voicemail;
8522 dstvms = get_vm_state_by_mailbox(vmtmp->mailbox, vmtmp->context, 0);
8524 dstvms = create_vm_state_from_user(vmtmp);
8527 init_mailstream(dstvms, 0);
8528 if (!dstvms->mailstream) {
8531 copy_msg_result =
STORE(vmstmp.
curdir, vmtmp->mailbox, vmtmp->context, curmsg, chan, vmtmp, fmt, duration, dstvms, urgent_str, msg_id);
8538 myserveremail = vmtmp->serveremail;
8541 sendmail(myserveremail, vmtmp, todircount, vmtmp->context, vmtmp->mailbox,
8545 vmstmp.
fn, vmstmp.introfn, fmt, duration, attach_user_voicemail, chan,
8546 NULL, urgent_str, msg_id);
8548 copy_msg_result =
copy_message(chan, sender, 0, curmsg, duration, vmtmp, fmt, dir, urgent_str,
NULL);
8558 if (saved_messages > 0 && !copy_msg_result) {
8569 #ifndef IMAP_STORAGE 8575 make_file(msgfile,
sizeof(msgfile), dir, curmsg);
8576 strcpy(textfile, msgfile);
8577 strcpy(backup, msgfile);
8578 strcpy(backup_textfile, msgfile);
8579 strncat(textfile,
".txt",
sizeof(textfile) - strlen(textfile) - 1);
8580 strncat(backup,
"-bak",
sizeof(backup) - strlen(backup) - 1);
8581 strncat(backup_textfile,
"-bak.txt",
sizeof(backup_textfile) - strlen(backup_textfile) - 1);
8584 rename(backup_textfile, textfile);
8589 #ifndef IMAP_STORAGE 8591 make_file(msgfile,
sizeof(msgfile), dir, curmsg);
8592 strcpy(textfile, msgfile);
8593 strcpy(backup_textfile, msgfile);
8594 strncat(textfile,
".txt",
sizeof(textfile) - strlen(textfile) - 1);
8595 strncat(backup_textfile,
"-bak.txt",
sizeof(backup_textfile) - strlen(backup_textfile) - 1);
8596 rename(backup_textfile, textfile);
8606 return res ? res : cmd;
8620 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);
8671 if (time_now.tm_year == time_then.tm_year)
8672 snprintf(temp,
sizeof(temp),
"%d", time_now.tm_yday);
8674 snprintf(temp,
sizeof(temp),
"%d", (time_now.tm_year - time_then.tm_year) * 365 + (time_now.tm_yday - time_then.tm_yday));
8720 char *callerid, *
name;
8730 if ((cid ==
NULL)||(context ==
NULL))
8734 ast_debug(1,
"VM-CID: composite caller ID received: %s, context: %s\n", cid, context);
8740 ast_debug(1,
"VM-CID: comparing internalcontext: %s\n", cidinternalcontexts[i]);
8741 if ((strcmp(cidinternalcontexts[i], context) == 0))
8744 if (i != MAX_NUM_CID_CONTEXTS){
8746 snprintf(prefile,
sizeof(prefile),
"%s%s/%s/greet", VM_SPOOL_DIR, context, callerid);
8751 ast_verb(3,
"Playing envelope info: CID number '%s' matches mailbox number, playing recorded name\n", callerid);
8756 ast_verb(3,
"Playing envelope info: message from '%s'\n", callerid);
8759 res =
wait_file2(chan, vms,
"vm-from-extension");
8765 ast_debug(1,
"VM-CID: Numeric caller id: (%s)\n", callerid);
8771 ast_verb(3,
"Playing recorded name for CID number '%s' - '%s'\n", callerid,prefile);
8774 ast_verb(3,
"Played recorded name result '%d'\n", res);
8777 wait_file2(chan, vms,
"vm-from-phonenumber");
8786 ast_debug(1,
"VM-CID: From an unknown number\n");
8788 res =
wait_file2(chan, vms,
"vm-unknown-caller");
8799 if (duration ==
NULL)
8803 durations = atoi(duration);
8804 durationm = (durations / 60);
8806 ast_debug(1,
"VM-Duration: duration is: %d seconds converted to: %d minutes\n", durations, durationm);
8808 if ((!res) && (durationm >= minduration)) {
8813 div_t num = div(durationm, 10);
8815 if (durationm == 1) {
8818 }
else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
8847 const char *origtime, *
context, *category, *duration, *
flag;
8860 snprintf(filename,
sizeof(filename),
"%s.txt", vms->
fn);
8881 ten = (vms->
curmsg + 1) / 10;
8882 one = (vms->
curmsg + 1) % 10;
8885 snprintf(nextmsg,
sizeof(nextmsg),
"digits/n-%d", vms->
curmsg + 1);
8888 snprintf(nextmsg,
sizeof(nextmsg),
"digits/n-%d", ten * 10);
8892 snprintf(nextmsg,
sizeof(nextmsg),
"digits/n-%d", one);
8934 res =
wait_file2(chan, vms,
"vm-meddelandet");
8964 if (!strncasecmp(
"macro", context, 5))
9005 isprint(res) ? res :
'?', isprint(res) ? res :
'?');
9012 static int imap_remove_file(
char *dir,
int msgnum)
9020 snprintf(intro,
sizeof(intro),
"%sintro", fn);
9024 if ((msgnum < 0 && imapgreetings) || msgnum > -1) {
9029 snprintf(full_fn,
sizeof(full_fn),
"%s.txt", fn);
9037 static int imap_delete_old_greeting (
char *dir,
struct vm_state *vms)
9039 char *
file, *filename;
9049 ast_log(
AST_LOG_ERROR,
"Failed to procure file name from directory passed. You should never see this.\n");
9064 for (i = 0; i < vms->mailstream->nmsgs; i++) {
9065 mail_fetchstructure(vms->mailstream, i + 1, &body);
9067 if (body->nested.part->next && body->nested.part->next->body.parameter->value) {
9068 char *attachment = body->nested.part->next->body.parameter->value;
9069 char copy[strlen(attachment) + 1];
9071 strcpy(copy, attachment);
9074 filename =
strsep(&attachment,
".");
9075 if (!strcmp(filename, file)) {
9076 snprintf(arg,
sizeof(arg),
"%d", i + 1);
9077 mail_setflag(vms->mailstream, arg,
"\\DELETED");
9085 mail_expunge(vms->mailstream);
9087 if (curr_mbox != -1) {
9089 if (init_mailstream(vms, curr_mbox) || !vms->mailstream) {
9098 #elif !defined(IMAP_STORAGE) 9101 int count_msg, last_msg;
9115 if (count_msg < 0) {
9141 if (last_msg < -1) {
9143 }
else if (vms->
lastmsg != last_msg) {
9144 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);
9155 int last_msg_idx = 0;
9157 #ifndef IMAP_STORAGE 9158 int res = 0, nummsg;
9167 #ifndef IMAP_STORAGE 9175 if (last_msg_idx != vms->
lastmsg) {
9180 for (x = 0; x < last_msg_idx + 1; x++) {
9189 if (strcmp(vms->
fn, fn2)) {
9223 for (x = vms->
curmsg + 1; x <= nummsg; x++) {
9236 for (x = last_msg_idx - 1; x >= 0; x--) {
9277 if (!strcasecmp(box,
"vm-INBOX") || !strcasecmp(box,
"vm-Old")){
9290 if (!strcasecmp(box,
"vm-INBOX") || !strcasecmp(box,
"vm-Old")) {
9303 if (!strcasecmp(box,
"vm-INBOX") || !strcasecmp(box,
"vm-Old")) {
9304 if (!strcasecmp(box,
"vm-INBOX"))
9319 if (!strcasecmp(box,
"vm-Family") || !strcasecmp(box,
"vm-Friends") || !strcasecmp(box,
"vm-Work")){
9678 snprintf(recname,
sizeof(recname),
"digits/1kvk");
9680 snprintf(recname,
sizeof(recname),
"digits/%dhk", vms->
urgentmessages);
9693 snprintf(recname,
sizeof(recname),
"digits/1kvk");
9695 snprintf(recname,
sizeof(recname),
"digits/%dhk", vms->
newmessages);
9710 snprintf(recname,
sizeof(recname),
"digits/1kvk");
9712 snprintf(recname,
sizeof(recname),
"digits/%dhk", vms->
oldmessages);
9788 }
else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
9815 }
else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
10366 snprintf(prefile,
sizeof(prefile),
"%s%s/%s/temp", VM_SPOOL_DIR, vmu->
context, vms->
username);
10381 static int deprecation_warning = 0;
10382 if (deprecation_warning++ % 10 == 0) {
10383 ast_log(
LOG_WARNING,
"cz is not a standard language code. Please switch to using cs instead.\n");
10449 if (skipadvanced) {
10464 if (!res && !skipadvanced)
10479 int curmsg_deleted;
10480 #ifdef IMAP_STORAGE 10484 #ifdef IMAP_STORAGE 10487 if (!curmsg_deleted) {
10536 if (skipadvanced) {
10557 if (!res && !skipadvanced)
10572 int curmsg_deleted;
10573 #ifdef IMAP_STORAGE 10577 #ifdef IMAP_STORAGE 10580 if (!curmsg_deleted) {
10651 char newpassword[80] =
"";
10652 char newpassword2[80] =
"";
10654 unsigned char buf[256];
10669 snprintf(prefile,
sizeof(prefile),
"%s%s/%s/greet", VM_SPOOL_DIR, vmu->
context, vms->
username);
10671 cmd =
play_record_review(chan,
"vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration,
NULL,
NULL, record_gain, vms,
NULL,
NULL, 0);
10672 if (cmd < 0 || cmd ==
't' || cmd ==
'#')
10679 snprintf(prefile,
sizeof(prefile),
"%s%s/%s/unavail", VM_SPOOL_DIR, vmu->
context, vms->
username);
10681 cmd =
play_record_review(chan,
"vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration,
NULL,
NULL, record_gain, vms,
NULL,
NULL, 0);
10682 if (cmd < 0 || cmd ==
't' || cmd ==
'#')
10686 snprintf(prefile,
sizeof(prefile),
"%s%s/%s/busy", VM_SPOOL_DIR, vmu->
context, vms->
username);
10688 cmd =
play_record_review(chan,
"vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration,
NULL,
NULL, record_gain, vms,
NULL,
NULL, 0);
10689 if (cmd < 0 || cmd ==
't' || cmd ==
'#')
10699 newpassword[1] =
'\0';
10702 newpassword[0] =
'\0';
10703 if (cmd < 0 || cmd ==
't' || cmd ==
'#')
10705 cmd =
ast_readstring(chan, newpassword + strlen(newpassword),
sizeof(newpassword) - 1, 2000, 10000,
"#");
10706 if (cmd < 0 || cmd ==
't' || cmd ==
'#')
10713 newpassword2[1] =
'\0';
10716 newpassword2[0] =
'\0';
10717 if (cmd < 0 || cmd ==
't' || cmd ==
'#')
10719 cmd =
ast_readstring(chan, newpassword2 + strlen(newpassword2),
sizeof(newpassword2) - 1, 2000, 10000,
"#");
10720 if (cmd < 0 || cmd ==
't' || cmd ==
'#')
10722 if (!strcmp(newpassword, newpassword2))
10738 ast_debug(1,
"User %s set password to %s of length %d\n", vms->
username, newpassword, (
int) strlen(newpassword));
10749 char newpassword[80] =
"";
10750 char newpassword2[80] =
"";
10752 unsigned char buf[256];
10764 while ((cmd >= 0) && (cmd !=
't')) {
10769 snprintf(prefile,
sizeof(prefile),
"%s%s/%s/unavail", VM_SPOOL_DIR, vmu->
context, vms->
username);
10770 cmd =
play_record_review(chan,
"vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration,
NULL,
NULL, record_gain, vms,
NULL,
NULL, 0);
10773 snprintf(prefile,
sizeof(prefile),
"%s%s/%s/busy", VM_SPOOL_DIR, vmu->
context, vms->
username);
10774 cmd =
play_record_review(chan,
"vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration,
NULL,
NULL, record_gain, vms,
NULL,
NULL, 0);
10777 snprintf(prefile,
sizeof(prefile),
"%s%s/%s/greet", VM_SPOOL_DIR, vmu->
context, vms->
username);
10778 cmd =
play_record_review(chan,
"vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration,
NULL,
NULL, record_gain, vms,
NULL,
NULL, 0);
10788 newpassword[1] =
'\0';
10791 newpassword[0] =
'\0';
10795 if ((cmd =
ast_readstring(chan, newpassword + strlen(newpassword),
sizeof(newpassword) - 1, 2000, 10000,
"#")) < 0) {
10808 newpassword2[1] =
'\0';
10811 newpassword2[0] =
'\0';
10816 if ((cmd =
ast_readstring(chan, newpassword2 + strlen(newpassword2),
sizeof(newpassword2) - 1, 2000, 10000,
"#")) < 0) {
10820 if (strcmp(newpassword, newpassword2)) {
10836 ast_debug(1,
"User %s set password to %s of length %d\n",
10837 vms->
username, newpassword, (
int) strlen(newpassword));
10845 snprintf(prefile,
sizeof(prefile),
"%s%s/%s/temp", VM_SPOOL_DIR, vmu->
context, vms->
username);
10864 isprint(cmd) ? cmd :
'?', isprint(cmd) ? cmd :
'?');
10894 unsigned char buf[256];
10907 snprintf(prefile,
sizeof(prefile),
"%s%s/%s/temp", VM_SPOOL_DIR, vmu->
context, vms->
username);
10908 while ((cmd >= 0) && (cmd !=
't')) {
10913 cmd =
play_record_review(chan,
"vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration,
NULL,
NULL, record_gain, vms,
NULL,
NULL, 0);
10921 cmd =
play_record_review(chan,
"vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration,
NULL,
NULL, record_gain, vms,
NULL,
NULL, 0);
10924 DELETE(prefile, -1, prefile, vmu);
10934 "vm-tempgreeting2" :
"vm-tempgreeting");
10945 isprint(cmd) ? cmd :
'?', isprint(cmd) ? cmd :
'?');
10971 if (!strcasecmp(vms->
vmbox,
"vm-INBOX") ||!strcasecmp(vms->
vmbox,
"vm-Old")){
10973 snprintf(vms->
fn,
sizeof(vms->
fn),
"vm-%ss", vms->
curbox);
10982 snprintf(vms->
fn,
sizeof(vms->
fn),
"vm-%s", vms->
curbox);
10998 if (!strcasecmp(vms->
fn,
"INBOX")) {
11026 snprintf(vms->
fn,
sizeof(vms->
fn),
"vm-%s", vms->
curbox);
11054 snprintf(vms->
fn,
sizeof(vms->
fn),
"vm-%s", vms->
curbox);
11076 snprintf(vms->
fn,
sizeof(vms->
fn),
"vm-%s", vms->
curbox);
11107 snprintf(vms->
fn,
sizeof(vms->
fn),
"vm-%s", vms->
curbox);
11131 snprintf(vms->
fn,
sizeof(vms->
fn),
"vm-%s", vms->
curbox);
11161 snprintf(vms->
fn,
sizeof(vms->
fn),
"vm-%s", vms->
curbox);
11185 snprintf(vms->
fn,
sizeof(vms->
fn),
"vm-%s", vms->
curbox);
11228 int skipuser,
int max_logins,
int silent)
11230 int useadsi = 0, valid = 0, logretries = 0;
11236 if (!skipuser && useadsi)
11245 while (!valid && (logretries < max_logins)) {
11247 if (!skipuser &&
ast_readstring(chan, mailbox, mailbox_size - 1, 2000, 10000,
"#") < 0) {
11255 ast_verb(3,
"Username not entered\n");
11258 }
else if (mailbox[0] ==
'*') {
11260 ast_verb(4,
"Mailbox begins with '*', attempting jump to extension 'a'\n");
11265 ast_verb(4,
"Jump to extension 'a' failed; setting mailbox to NULL\n");
11273 char fullusername[80];
11276 strncat(fullusername, mailbox,
sizeof(fullusername) - 1 - strlen(fullusername));
11280 ast_debug(1,
"Before find user for mailbox %s\n", mailbox);
11281 memset(&vmus, 0,
sizeof(vmus));
11282 vmu =
find_user(&vmus, context, mailbox);
11285 password[0] =
'\0';
11292 if (
ast_readstring(chan, password,
sizeof(password) - 1, 2000, 10000,
"#") < 0) {
11296 }
else if (password[0] ==
'*') {
11298 ast_verb(4,
"Password begins with '*', attempting jump to extension 'a'\n");
11305 ast_verb(4,
"Jump to extension 'a' failed; setting mailbox and user to NULL\n");
11315 if (passptr[0] ==
'-') passptr++;
11317 if (vmu && !strcmp(passptr, password))
11320 ast_verb(3,
"Incorrect password '%s' for user '%s' (context = %s)\n", password, mailbox, context ? context :
"default");
11326 if (skipuser || logretries >= max_logins) {
11347 if (!valid && (logretries >= max_logins)) {
11353 if (vmu && !skipuser) {
11362 const char *msg_id)
11371 #ifdef IMAP_STORAGE 11384 #ifdef IMAP_STORAGE 11388 #ifdef IMAP_STORAGE 11411 memset(&vmus, 0,
sizeof(vmus));
11412 memset(&vms, 0,
sizeof(vms));
11414 if (!(vmu =
find_user(&vmus, context, mailbox))) {
11415 goto play_msg_cleanup;
11419 for (i = 0; i <
ARRAY_LEN(mailbox_folders) && !played; i++) {
11427 goto play_msg_cleanup;
11439 goto play_msg_cleanup;
11453 #ifdef IMAP_STORAGE 11455 vmstate_delete(&vms);
11467 char *mailbox =
NULL;
11468 char *context =
NULL;
11492 if ((context = strchr(
args.mailbox,
'@'))) {
11495 mailbox =
args.mailbox;
11511 char prefixstr[80] =
"";
11512 char ext_context[256]=
"";
11518 char *context =
NULL;
11519 int silentexit = 0;
11521 signed char record_gain = 0;
11523 int play_folder = 0;
11525 #ifdef IMAP_STORAGE 11550 if (
args.argc == 2) {
11556 if (sscanf(opts[OPT_ARG_RECORDGAIN],
"%30d", &gain) != 1) {
11557 ast_log(
AST_LOG_WARNING,
"Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
11560 record_gain = (
signed char) gain;
11570 if (isdigit(opts[OPT_ARG_PLAYFOLDER][0])) {
11571 if (sscanf(opts[OPT_ARG_PLAYFOLDER],
"%30d", &play_folder) != 1) {
11580 if (play_folder > 9 || play_folder < 0) {
11582 "Invalid value '%s' provided for folder autoplay option. Defaulting to 'INBOX'\n",
11583 opts[OPT_ARG_PLAYFOLDER]);
11589 while (*(
args.argv0)) {
11590 if (*(
args.argv0) ==
's')
11592 else if (*(
args.argv0) ==
'p')
11603 if ((context = strchr(
args.argv0,
'@')))
11620 ast_debug(1,
"After vm_authenticate\n");
11649 #ifdef IMAP_STORAGE 11650 pthread_once(&ts_vmstate.once, ts_vmstate.key_init);
11651 pthread_setspecific(ts_vmstate.key, &vms);
11653 vms.interactive = 1;
11657 vmstate_insert(&vms);
11658 init_vm_state(&vms);
11664 ast_channel_language_set(chan, vmu->
language);
11736 if ((cmd ==
't') || (cmd ==
'#')) {
11741 }
else if (cmd < 0) {
11748 #ifdef IMAP_STORAGE 11749 ast_debug(3,
"Checking quotas: comparing %u to %u\n", vms.quota_usage, vms.quota_limit);
11750 if (vms.quota_limit && vms.quota_usage >= vms.quota_limit) {
11751 ast_debug(1,
"*** QUOTA EXCEEDED!!\n");
11768 isprint(cmd) ? cmd :
'?', isprint(cmd) ? cmd :
'?');
11772 while ((cmd > -1) && (cmd !=
't') && (cmd !=
'#')) {
11789 isprint(cmd) ? cmd :
'?', isprint(cmd) ? cmd :
'?');
11792 }
else if (cmd > 0) {
11798 if (cmd != 11) in_urgent = 0;
11819 while ((cmd > -1) && (cmd !=
't') && (cmd !=
'#')) {
11835 ast_verb(3,
"Callback Requested\n");
11877 cmd =
forward_message(chan, context, &vms, vmu, vmfmts, 1, record_gain, 0);
11922 isprint(cmd) ? cmd :
'?', isprint(cmd) ? cmd :
'?');
11949 ast_debug(1,
"No more new messages, opened INBOX and got %d Urgent messages\n", vms.
lastmsg + 1);
11980 ast_debug(1,
"No more urgent messages, opened INBOX and got %d new messages\n", vms.
lastmsg + 1);
11999 if (play_folder == 0) {
12006 else if (play_folder == 1)
12010 if (play_folder == 0) {
12017 else if (play_folder == 1)
12033 if (in_urgent == 1) {
12042 ast_debug(1,
"No more urgent messages, opened INBOX and got %d new messages\n", vms.
lastmsg + 1);
12054 #ifdef IMAP_STORAGE 12061 cmd =
forward_message(chan, context, &vms, vmu, vmfmts, 0, record_gain, in_urgent);
12080 ast_debug(1,
"No more urgent messages, opened INBOX and got %d new messages\n", vms.
lastmsg + 1);
12101 isprint(cmd) ? cmd :
'?', isprint(cmd) ? cmd :
'?');
12106 }
else if (cmd > 0) {
12107 box = cmd = cmd -
'0';
12112 #ifndef IMAP_STORAGE 12124 snprintf(vms.
fn,
sizeof(vms.
fn),
"vm-%s",
mbox(vmu, box));
12157 ast_debug(1,
"No more urgent messages, opened INBOX and got %d new messages\n", vms.
lastmsg + 1);
12200 cmd =
vm_options(chan, vmu, &vms, vmfmts, record_gain);
12216 if ((cmd ==
't') || (cmd ==
'#')) {
12243 int new = 0, old = 0, urgent = 0;
12244 snprintf(ext_context,
sizeof(ext_context),
"%s@%s", vms.
username, vmu->
context);
12250 #ifdef IMAP_STORAGE 12252 ast_debug(3,
"*** Checking if we can expunge, deleted set to %d, expungeonhangup set to %d\n", deleted, expungeonhangup);
12253 if (vmu && deleted == 1 && expungeonhangup == 1 && vms.mailstream !=
NULL) {
12255 #ifdef HAVE_IMAP_TK2006 12256 if (LEVELUIDPLUS (vms.mailstream)) {
12257 mail_expunge_full(vms.mailstream, NIL, EX_UID);
12260 mail_expunge(vms.mailstream);
12266 vmstate_delete(&vms);
12272 #ifdef IMAP_STORAGE 12273 pthread_setspecific(ts_vmstate.key,
NULL);
12290 memset(&leave_options, 0,
sizeof(leave_options));
12295 if (
args.argc == 2) {
12303 ast_log(
AST_LOG_WARNING,
"Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
12311 leave_options.
exitcontext = opts[OPT_ARG_DTMFEXIT];
12321 res =
ast_app_getdata(chan,
"vm-whichbox", temp,
sizeof(temp) - 1, 0);
12369 ast_log(
LOG_ERROR,
"Voicemail data file %s/%d.txt has no [message] category?\n", dir, msg);
12390 ast_log(
LOG_WARNING,
"Mailbox %s in context %s begins with '*' character. The '*' character," 12391 "\n\twhen it is the first character in a mailbox or password, is used to jump to a" 12392 "\n\tpredefined extension 'a'. A mailbox or password beginning with '*' is not valid" 12393 "\n\tand will be ignored.\n", box, context);
12399 if (strcasecmp(vmu->
context, context)) {
12400 ast_log(
LOG_WARNING,
"\nIt has been detected that you have defined mailbox '%s' in separate\ 12401 \n\tcontexts and that you have the 'searchcontexts' option on. This type of\ 12402 \n\tconfiguration creates an ambiguity that you likely do not want. Please\ 12403 \n\tamend your voicemail.conf file to avoid this situation.\n", box);
12408 if (!strcasecmp(context, vmu->
context) && !strcasecmp(box, vmu->
mailbox)) {
12409 ast_log(
LOG_WARNING,
"Ignoring duplicated mailbox %s in context %s\n", box, context);
12433 int new = 0, old = 0, urgent = 0;
12444 if ((s =
strsep(&stringp,
","))) {
12447 "\n\tmust be reset in voicemail.conf.\n", box);
12452 if (stringp && (s =
strsep(&stringp,
","))) {
12455 if (stringp && (s =
strsep(&stringp,
","))) {
12458 if (stringp && (s =
strsep(&stringp,
","))) {
12467 snprintf(secretfn,
sizeof(secretfn),
"%s%s/%s/secret.conf", VM_SPOOL_DIR, vmu->
context, vmu->
mailbox);
12477 #ifdef IMAP_STORAGE 12478 imap_logout(mailbox_full);
12485 #ifdef TEST_FRAMEWORK 12491 static const char options_string[] =
"attach=yes|attachfmt=wav49|" 12492 "[email protected]|fromstring=Voicemail System|tz=central|delete=yes|saycid=yes|" 12493 "sendvoicemail=yes|review=yes|tempgreetwarn=yes|messagewrap=yes|operator=yes|" 12494 "envelope=yes|moveheard=yes|sayduration=yes|saydurationm=5|forcename=yes|" 12495 "forcegreetings=yes|callback=somecontext|dialout=somecontext2|" 12496 "exitcontext=somecontext3|minsecs=10|maxsecs=100|nextaftercmd=yes|" 12497 "backupdeleted=50|volgain=1.3|passwordlocation=spooldir|emailbody=" 12498 "Dear ${VM_NAME}:\n\n\tYou were just left a ${VM_DUR} long message|emailsubject=" 12499 "[PBX]: New message \\\\${VM_MSGNUM}\\\\ in mailbox ${VM_MAILBOX}";
12500 #ifdef IMAP_STORAGE 12501 static const char option_string2[] =
"imapuser=imapuser|imappassword=imappasswd|" 12502 "imapfolder=INBOX|imapvmshareid=6000|imapserver=imapserver|imapport=1234|imapflags=flagged";
12507 info->name =
"vmuser";
12508 info->category =
"/apps/app_voicemail/";
12509 info->summary =
"Vmuser unit test";
12510 info->description =
12511 "This tests passing all supported parameters to apply_options, the voicemail user config parser";
12529 if (strcasecmp(vmu->
attachfmt,
"wav49")) {
12533 if (strcasecmp(vmu->
fromstring,
"Voicemail System")) {
12541 if (!vmu->
emailsubject || strcasecmp(vmu->
emailsubject,
"[PBX]: New message \\${VM_MSGNUM}\\ in mailbox ${VM_MAILBOX}")) {
12545 if (!vmu->
emailbody || strcasecmp(vmu->
emailbody,
"Dear ${VM_NAME}:\n\n\tYou were just left a ${VM_DUR} long message")) {
12549 if (strcasecmp(vmu->
zonetag,
"central")) {
12605 if (strcasecmp(vmu->
callback,
"somecontext")) {
12609 if (strcasecmp(vmu->
dialout,
"somecontext2")) {
12613 if (strcasecmp(vmu->
exit,
"somecontext3")) {
12641 #ifdef IMAP_STORAGE 12644 if (strcasecmp(vmu->imapuser,
"imapuser")) {
12648 if (strcasecmp(vmu->imappassword,
"imappasswd")) {
12652 if (strcasecmp(vmu->imapfolder,
"INBOX")) {
12656 if (strcasecmp(vmu->imapvmshareid,
"6000")) {
12660 if (strcasecmp(vmu->imapserver,
"imapserver")) {
12664 if (strcasecmp(vmu->imapport,
"1234")) {
12668 if (strcasecmp(vmu->imapflags,
"flagged")) {
12697 ast_log(
LOG_ERROR,
"VM_INFO requires an argument (<mailbox>[@<context>],attribute[,folder])\n");
12707 ast_log(
LOG_ERROR,
"VM_INFO requires an argument (<mailbox>[@<context>],attribute[,folder])\n");
12711 memset(&svm, 0,
sizeof(svm));
12712 vmu =
find_user(&svm, context, mailbox);
12714 if (!strncasecmp(arg.attribute,
"exists", 5)) {
12721 if (!strncasecmp(arg.attribute,
"password", 8)) {
12723 }
else if (!strncasecmp(arg.attribute,
"fullname", 8)) {
12725 }
else if (!strncasecmp(arg.attribute,
"email", 5)) {
12727 }
else if (!strncasecmp(arg.attribute,
"pager", 5)) {
12729 }
else if (!strncasecmp(arg.attribute,
"language", 8)) {
12731 }
else if (!strncasecmp(arg.attribute,
"locale", 6)) {
12733 }
else if (!strncasecmp(arg.attribute,
"tz", 2)) {
12735 }
else if (!strncasecmp(arg.attribute,
"count", 5)) {
12738 mailbox_id =
ast_alloca(strlen(mailbox) + strlen(context) + 2);
12739 sprintf(mailbox_id,
"%s@%s", mailbox, context);
12744 ast_log(
LOG_ERROR,
"Unable to retrieve message count for mailbox %s\n", arg.mailbox_context);
12748 snprintf(buf, len,
"%d", res);
12750 ast_log(
LOG_ERROR,
"Unknown attribute '%s' for VM_INFO\n", arg.attribute);
12770 int silent = 0, skipuser = 0;
12776 options =
strsep(&s,
",");
12780 context =
strsep(&s,
"");
12788 silent = (strchr(options,
's')) !=
NULL;
12791 if (!
vm_authenticate(chan, mailbox,
sizeof(mailbox), &vmus, context,
NULL, skipuser, 3, silent)) {
12796 }
else if (mailbox[0] ==
'*') {
12809 const char *cat =
NULL;
12818 "=============================================================\n" 12819 "=== Configured Voicemail Users ==============================\n" 12820 "=============================================================\n" 12826 "=== Mailbox ...\n" 12832 "=== ---------------------------------------------------------\n" 12837 "=============================================================\n" 12850 const char *context =
"";
12855 wordlen = strlen(word);
12857 if (!strncasecmp(word, vmu->
context, wordlen)) {
12858 if (context && strcmp(context, vmu->
context) && ++which > state)
12871 #define HVSU_OUTPUT_FORMAT "%-10s %-5s %-25s %-10s %6s\n" 12872 const char *context =
NULL;
12873 int users_counter = 0;
12877 e->
command =
"voicemail show users [for]";
12879 "Usage: voicemail show users [for <context>]\n" 12880 " Lists all mailboxes currently set up\n";
12888 if (a->
argc == 5) {
12889 if (strcmp(a->
argv[3],
"for"))
12891 context = a->
argv[4];
12896 ast_cli(a->
fd,
"You must specify a specific context to show users from realtime!\n");
12904 ast_cli(a->
fd,
"There are no voicemail users currently defined\n");
12913 if (!strcmp(context, vmu->
context)) {
12921 ast_cli(a->
fd,
"No such voicemail context \"%s\"\n", context);
12927 int newmsgs = 0, oldmsgs = 0;
12928 char count[12], tmp[256] =
"";
12930 if (!context || !strcmp(context, vmu->
context)) {
12933 snprintf(count,
sizeof(count),
"%d", newmsgs);
12939 ast_cli(a->
fd,
"%d voicemail users configured.\n", users_counter);
12947 #define HVSZ_OUTPUT_FORMAT "%-15s %-20s %-45s\n" 12952 e->
command =
"voicemail show zones";
12954 "Usage: voicemail show zones\n" 12955 " Lists zone message formats\n";
12971 ast_cli(a->
fd,
"There are no voicemail zones currently defined\n");
12984 #define ALIASES_OUTPUT_FORMAT "%-32s %-32s\n" 12989 e->
command =
"voicemail show aliases";
12991 "Usage: voicemail show aliases\n" 12992 " Lists mailbox aliases\n";
13002 ast_cli(a->
fd,
"Aliases are not enabled\n");
13006 ast_cli(a->
fd,
"Aliases context: %s\n", aliasescontext);
13024 e->
command =
"voicemail reload";
13026 "Usage: voicemail reload\n" 13027 " Reload voicemail configuration\n";
13036 ast_cli(a->
fd,
"Reloading voicemail configuration...\n");
13051 int new = 0, old = 0, urgent = 0;
13060 #ifdef IMAP_STORAGE 13061 if (imap_poll_logout) {
13076 while (poll_thread_run) {
13077 struct timespec ts = { 0, };
13078 struct timeval wait;
13082 if (!poll_thread_run) {
13087 ts.tv_sec = wait.tv_sec;
13088 ts.tv_nsec = wait.tv_usec * 1000;
13098 #ifdef IMAP_STORAGE 13099 static void imap_logout(
const char *mailbox_id)
13112 memset(&vmus, 0,
sizeof(vmus));
13114 if (!(vmu =
find_user(&vmus, context, mailbox)) || vmu->imapuser[0] ==
'\0') {
13118 vms = get_vm_state_by_imapuser(vmu->imapuser, 0);
13120 vms = get_vm_state_by_mailbox(mailbox, context, 0);
13127 vms->mailstream = mail_close(vms->mailstream);
13130 vmstate_delete(vms);
13133 static int imap_close_subscribed_mailbox(
struct ast_mwi_state *mwi_state,
void *data)
13155 #ifdef IMAP_STORAGE 13156 imap_close_subscribed_mailbox(mwi_state,
NULL);
13202 poll_thread_run = 1;
13211 poll_thread_run = 0;
13217 pthread_join(poll_thread,
NULL);
13230 const char* event_name,
13231 const char* actionid
13239 if((s ==
NULL) || (vmu ==
NULL) || (event_name ==
NULL) || (actionid ==
NULL)) {
13259 ast_log(
LOG_ERROR,
"Could not get mailbox count. user[%s], context[%s]\n",
13267 "VMContext: %s\r\n" 13268 "VoiceMailbox: %s\r\n" 13272 "ServerEmail: %s\r\n" 13273 "FromString: %s\r\n" 13274 "MailCommand: %s\r\n" 13280 "ExitContext: %s\r\n" 13281 "SayDurationMinimum: %d\r\n" 13282 "SayEnvelope: %s\r\n" 13284 "AttachMessage: %s\r\n" 13285 "AttachmentFormat: %s\r\n" 13286 "DeleteMessage: %s\r\n" 13287 "VolumeGain: %.2f\r\n" 13288 "CanReview: %s\r\n" 13289 "CallOperator: %s\r\n" 13290 "MaxMessageCount: %d\r\n" 13291 "MaxMessageLength: %d\r\n" 13292 "NewMessageCount: %d\r\n" 13293 "OldMessageCount: %d\r\n" 13294 #ifdef IMAP_STORAGE
13296 "IMAPServer: %s\r\n" 13298 "IMAPFlags: %s\r\n" 13331 #ifdef IMAP_STORAGE
13356 (at = strchr(mwi_state->
uniqueid,
'@')) &&
13360 (at = strchr(mwi_state->
uniqueid,
'@')) &&
13361 strcmp(context, at + 1) == 0) ||
13364 (at = strchr(mwi_state->
uniqueid,
'@')) &&
13366 strcmp(context, at + 1) == 0)
13386 char actionid[128];
13398 actionid[0] =
'\0';
13400 snprintf(actionid,
sizeof(actionid),
"ActionID: %s\r\n",
id);
13404 memset(&svm, 0,
sizeof(svm));
13405 vmu =
find_user(&svm, context, mailbox);
13408 astman_send_ack(s, m,
"There is no voicemail user of the given info.");
13432 char actionid[128];
13436 actionid[0] =
'\0';
13438 snprintf(actionid,
sizeof(actionid),
"ActionID: %s\r\n",
id);
13444 astman_send_ack(s, m,
"There are no voicemail users currently defined.");
13501 for (current = (
char *) value; *current; current++) {
13502 if (*current ==
'\\') {
13508 switch (*current) {
13516 #ifdef IMAP_STORAGE 13517 if (!str->used || str->str[str->used - 1] !=
'\r') {
13551 ast_log(
LOG_ERROR,
"Config file users.conf is in an invalid format. Avoiding.\n");
13566 ast_log(
LOG_ERROR,
"Config file users.conf is in an invalid format. Avoiding.\n");
13579 #ifdef TEST_FRAMEWORK 13591 size_t from_len = strlen(alias) + 1;
13592 size_t to_len = strlen(mailbox) + 1;
13594 mapping =
ao2_alloc(
sizeof(*mapping) + from_len + to_len,
NULL);
13617 ao2_link(alias_mailbox_mappings, mapping);
13618 ao2_link(mailbox_alias_mappings, mapping);
13634 char storage[strlen(var->
value) + 1];
13641 strcpy(storage, var->
value);
13642 msg_format = storage;
13643 tzone =
strsep(&msg_format,
"|,");
13666 if (strcasecmp(cat,
"general") == 0
13667 || strcasecmp(cat, aliasescontext) == 0
13668 || strcasecmp(cat,
"zonemessages") == 0) {
13685 char *q, *stringp, *
tmp;
13687 unsigned int tmpadsi[4];
13689 long tps_queue_low;
13690 long tps_queue_high;
13692 #ifdef IMAP_STORAGE 13702 #ifdef IMAP_STORAGE 13718 memset(ext_pass_cmd, 0,
sizeof(ext_pass_cmd));
13719 memset(ext_pass_check_cmd, 0,
sizeof(ext_pass_check_cmd));
13728 aliasescontext[0] =
'\0';
13743 sscanf(val,
"%30lf", &volgain);
13745 #ifdef ODBC_STORAGE 13746 strcpy(odbc_database,
"asterisk");
13750 strcpy(odbc_table,
"voicemessages");
13762 maxsilence = atoi(val);
13763 if (maxsilence > 0)
13764 maxsilence *= 1000;
13770 maxmsg = atoi(val);
13783 if (sscanf(val,
"%30d", &x) == 1)
13790 if (maxdeletedmsg < 0) {
13820 ast_copy_string(ext_pass_check_cmd, val,
sizeof(ext_pass_check_cmd));
13821 ast_debug(1,
"found externpasscheck: %s\n", ext_pass_check_cmd);
13824 #ifdef IMAP_STORAGE 13852 expungeonhangup = 0;
13854 expungeonhangup = 1;
13856 expungeonhangup = 1;
13883 imap_poll_logout = 0;
13891 mail_parameters(NIL, SET_READTIMEOUT, (
void *) (atol(val)));
13893 mail_parameters(NIL, SET_READTIMEOUT, (
void *) 60L);
13897 mail_parameters(NIL, SET_WRITETIMEOUT, (
void *) (atol(val)));
13899 mail_parameters(NIL, SET_WRITETIMEOUT, (
void *) 60L);
13903 mail_parameters(NIL, SET_OPENTIMEOUT, (
void *) (atol(val)));
13905 mail_parameters(NIL, SET_OPENTIMEOUT, (
void *) 60L);
13909 mail_parameters(NIL, SET_CLOSETIMEOUT, (
void *) (atol(val)));
13911 mail_parameters(NIL, SET_CLOSETIMEOUT, (
void *) 60L);
13920 ast_debug(1,
"found externnotify: %s\n", externnotify);
13922 externnotify[0] =
'\0';
13927 ast_debug(1,
"Enabled SMDI voicemail notification\n");
13931 ast_debug(1,
"No SMDI interface set, trying default (/dev/ttyS0)\n");
13935 ast_log(
AST_LOG_ERROR,
"No valid SMDI interface specfied, disabling SMDI voicemail notification\n");
13942 silencethreshold = atoi(val);
13950 if (sscanf(val,
"%30d", &x) == 1) {
13956 static int maxmessage_deprecate = 0;
13957 if (maxmessage_deprecate == 0) {
13958 maxmessage_deprecate = 1;
13961 if (sscanf(val,
"%30d", &x) == 1) {
13970 if (sscanf(val,
"%30d", &x) == 1) {
13972 if (maxsilence / 1000 >= vmminsecs) {
13979 static int maxmessage_deprecate = 0;
13980 if (maxmessage_deprecate == 0) {
13981 maxmessage_deprecate = 1;
13984 if (sscanf(val,
"%30d", &x) == 1) {
13986 if (maxsilence / 1000 >= vmminsecs) {
14001 ast_log(
LOG_ERROR,
"Error processing format string, defaulting to format 'wav'\n");
14009 if (sscanf(val,
"%30d", &x) == 1) {
14017 if (sscanf(val,
"%30d", &x) == 1) {
14026 if (sscanf(val,
"%30d", &x) == 1) {
14035 if (sscanf(val,
"%30d", &x) == 1) {
14053 ast_debug(1,
"VM_CID Internal context string: %s\n", val);
14057 q =
strsep(&stringp,
",");
14058 while ((*q ==
' ')||(*q ==
'\t'))
14060 ast_copy_string(cidinternalcontexts[x], q,
sizeof(cidinternalcontexts[x]));
14061 ast_debug(1,
"VM_CID Internal context %d: %s\n", x, cidinternalcontexts[x]);
14063 cidinternalcontexts[x][0] =
'\0';
14068 ast_debug(1,
"VM Review Option disabled globally\n");
14075 ast_debug(1,
"VM Temporary Greeting Reminder Option disabled globally\n");
14078 ast_debug(1,
"VM Temporary Greeting Reminder Option enabled globally\n");
14082 ast_debug(1,
"VM next message wrap disabled globally\n");
14088 ast_debug(1,
"VM Operator break disabled globally\n");
14094 ast_debug(1,
"VM CID Info before msg disabled globally\n");
14100 ast_debug(1,
"Send Voicemail msg disabled globally\n");
14106 ast_debug(1,
"ENVELOPE before msg enabled globally\n");
14112 ast_debug(1,
"Move Heard enabled globally\n");
14118 ast_debug(1,
"Autoset of Urgent flag on forwarded Urgent messages disabled globally\n");
14124 ast_debug(1,
"Duration info before msg enabled globally\n");
14129 saydurationminfo = 2;
14131 if (sscanf(val,
"%30d", &x) == 1) {
14132 saydurationminfo = x;
14139 ast_debug(1,
"We are not going to skip to the next msg after save/delete\n");
14146 ast_debug(1,
"found dialout context: %s\n", dialcontext);
14148 dialcontext[0] =
'\0';
14153 ast_debug(1,
"found callback context: %s\n", callcontext);
14155 callcontext[0] =
'\0';
14160 ast_debug(1,
"found operator context: %s\n", exitcontext);
14162 exitcontext[0] =
'\0';
14175 ast_copy_string(vm_invalid_password, val,
sizeof(vm_invalid_password));
14179 ast_copy_string(vm_reenterpassword, val,
sizeof(vm_reenterpassword));
14186 ast_copy_string(vm_prepend_timeout, val,
sizeof(vm_prepend_timeout));
14190 ast_copy_string(listen_control_forward_key, val,
sizeof(listen_control_forward_key));
14192 ast_copy_string(listen_control_reverse_key, val,
sizeof(listen_control_reverse_key));
14194 ast_copy_string(listen_control_pause_key, val,
sizeof(listen_control_pause_key));
14196 ast_copy_string(listen_control_restart_key, val,
sizeof(listen_control_restart_key));
14198 ast_copy_string(listen_control_stop_key, val,
sizeof(listen_control_stop_key));
14205 val =
"voicemail.conf";
14207 if (!(strcmp(val,
"spooldir"))) {
14215 if (sscanf(val,
"%30u", &poll_freq) != 1) {
14221 poll_mailboxes = 0;
14225 memset(fromstring, 0,
sizeof(fromstring));
14226 memset(pagerfromstring, 0,
sizeof(pagerfromstring));
14227 strcpy(charset,
"ISO-8859-1");
14232 if (emailsubject) {
14234 emailsubject =
NULL;
14240 if (pagersubject) {
14242 pagersubject =
NULL;
14253 sscanf(val,
"%2x%2x%2x%2x", &tmpadsi[0], &tmpadsi[1], &tmpadsi[2], &tmpadsi[3]);
14254 for (x = 0; x < 4; x++) {
14255 memcpy(&adsifdn[x], &tmpadsi[x], 1);
14259 sscanf(val,
"%2x%2x%2x%2x", &tmpadsi[0], &tmpadsi[1], &tmpadsi[2], &tmpadsi[3]);
14260 for (x = 0; x < 4; x++) {
14261 memcpy(&adsisec[x], &tmpadsi[x], 1);
14266 adsiver = atoi(val);
14290 if (sscanf(val,
"%30ld", &tps_queue_high) != 1 || tps_queue_high <= 0) {
14295 tps_queue_low = -1;
14297 if (sscanf(val,
"%30ld", &tps_queue_low) != 1 ||
14298 tps_queue_low < -1 || tps_queue_high < tps_queue_low) {
14300 tps_queue_low = -1;
14310 if (!strcasecmp(cat,
"general")) {
14325 snprintf(secretfn,
sizeof(secretfn),
"%s%s/%s/secret.conf", VM_SPOOL_DIR, current->
context, current->
mailbox);
14363 snprintf(dir,
sizeof(dir),
"%s%s/%s/greet", VM_SPOOL_DIR, context, mailbox);
14364 ast_debug(2,
"About to try retrieving name file %s\n", dir);
14365 RETRIEVE(dir, -1, mailbox, context);
14393 return sayname(chan, mailbox, context);
14410 ast_log(
LOG_NOTICE,
"Failed reading voicemail password from %s, using secret from config file\n", secretfn);
14458 if ((res =
sayname(chan, mailbox, context)) < 0) {
14459 ast_debug(3,
"Greeting not found for '%s@%s', falling back to mailbox number.\n", mailbox, context);
14469 #ifdef TEST_FRAMEWORK 14484 static const char TEST_CONTEXT[] =
"very_long_unique_context_so_that_nobody_will_ever_have_the_same_one_configured_3141592653";
14498 info->name =
"vmsayname_exec";
14499 info->category =
"/apps/app_voicemail/";
14500 info->summary =
"Vmsayname unit test";
14501 info->description =
14502 "This tests passing various parameters to vmsayname";
14509 NULL,
NULL, 0, 0,
"TestChannel1"))) {
14510 goto exit_vmsayname_test;
14515 if (!capabilities) {
14516 goto exit_vmsayname_test;
14530 snprintf(dir,
sizeof(dir),
"%s@%s", TEST_EXTENSION, TEST_CONTEXT);
14532 snprintf(dir,
sizeof(dir),
"%s%s/%s/greet", VM_SPOOL_DIR, TEST_CONTEXT, TEST_EXTENSION);
14536 goto exit_vmsayname_test;
14539 if ((res =
create_dirpath(dir,
sizeof(dir), TEST_CONTEXT, TEST_EXTENSION,
""))) {
14541 goto exit_vmsayname_test;
14544 snprintf(dir2,
sizeof(dir2),
"%s%s/%s/greet.gsm", VM_SPOOL_DIR, TEST_CONTEXT, TEST_EXTENSION);
14546 if ((res = symlink(dir, dir2))) {
14548 goto exit_vmsayname_test;
14551 snprintf(dir,
sizeof(dir),
"%s@%s", TEST_EXTENSION, TEST_CONTEXT);
14556 snprintf(dir2,
sizeof(dir2),
"%s%s/%s", VM_SPOOL_DIR, TEST_CONTEXT, TEST_EXTENSION);
14558 snprintf(dir2,
sizeof(dir2),
"%s%s", VM_SPOOL_DIR, TEST_CONTEXT);
14563 exit_vmsayname_test:
14582 #ifdef IMAP_STORAGE 14588 const char origweasels[] =
"tt-weasels";
14589 const char testcontext[] =
"test";
14590 const char testmailbox[] =
"00000000";
14591 const char testspec[] =
"00000000@test";
14593 int new, old, urgent;
14594 const char *folders[3] = {
"Old",
"Urgent",
"INBOX" };
14595 const int folder2mbox[3] = { 1, 11, 0 };
14596 const int expected_results[3][12] = {
14598 { 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0 },
14599 { 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1 },
14600 { 1, 1, 1, 1, 0, 2, 1, 1, 1, 1, 1, 2 },
14605 info->name =
"test_voicemail_msgcount";
14606 info->category =
"/apps/app_voicemail/";
14607 info->summary =
"Test Voicemail status checks";
14608 info->description =
14609 "Verify that message counts are correct when retrieved through the public API";
14616 snprintf(syscmd,
sizeof(syscmd),
"rm -rf \"%s%s/%s\"", VM_SPOOL_DIR, testcontext, testmailbox);
14619 syserr > 0 ? strerror(syserr) :
"unable to fork()");
14623 #ifdef IMAP_STORAGE 14630 memset(&svm, 0,
sizeof(svm));
14631 if (!(vmu =
find_user(&svm, testcontext, testmailbox)) &&
14635 #ifdef IMAP_STORAGE 14642 memset(&vms, 0,
sizeof(vms));
14645 for (i = 0; i < 3; i++) {
14646 create_dirpath(tmp[i].dir,
sizeof(tmp[i].dir), testcontext, testmailbox, folders[i]);
14647 make_file(tmp[i].file,
sizeof(tmp[i].file), tmp[i].dir, 0);
14648 snprintf(tmp[i].
txtfile,
sizeof(tmp[i].txtfile),
"%s.txt", tmp[i].file);
14651 snprintf(syscmd,
sizeof(syscmd),
"cp \"%s/sounds/en/%s.gsm\" \"%s/%s/%s/%s/msg0000.gsm\"",
ast_config_AST_DATA_DIR, origweasels,
14652 VM_SPOOL_DIR, testcontext, testmailbox, folders[i]);
14655 syserr > 0 ? strerror(syserr) :
"unable to fork()");
14657 #ifdef IMAP_STORAGE 14665 if ((txt = fopen(tmp[i].txtfile,
"w+"))) {
14666 fprintf(txt,
"; just a stub\n[message]\nflag=%s\n", strcmp(folders[i],
"Urgent") ?
"" :
"Urgent");
14674 STORE(tmp[i].dir, testmailbox, testcontext, 0, chan, vmu,
"gsm", 600, &vms, strcmp(folders[i],
"Urgent") ?
"" :
"Urgent",
NULL);
14677 for (j = 0; j < 3; j++) {
14686 new = old = urgent = 0;
14690 }
else if (old != expected_results[i][3 + 0] ||
new != expected_results[i][3 + 2]) {
14692 testspec, old, expected_results[i][3 + 0],
new, expected_results[i][3 + 2]);
14696 new = old = urgent = 0;
14700 }
else if (old != expected_results[i][6 + 0] ||
14701 urgent != expected_results[i][6 + 1] ||
14702 new != expected_results[i][6 + 2] ) {
14703 ast_test_status_update(
test,
"inboxcount2(%s) returned old=%d (expected %d), urgent=%d (expected %d), and new=%d (expected %d)\n",
14704 testspec, old, expected_results[i][6 + 0], urgent, expected_results[i][6 + 1],
new, expected_results[i][6 + 2]);
14708 new = old = urgent = 0;
14709 for (j = 0; j < 3; j++) {
14712 testspec, folders[j],
ast_app_messagecount(testspec, folders[j]), expected_results[i][9 + j]);
14718 for (i = 0; i < 3; i++) {
14722 DELETE(tmp[i].dir, 0, tmp[i].file, vmu);
14733 #ifdef IMAP_STORAGE 14738 snprintf(syscmd,
sizeof(syscmd),
"rm -rf \"%s%s/%s\"", VM_SPOOL_DIR, testcontext, testmailbox);
14741 syserr > 0 ? strerror(syserr) :
"unable to fork()");
14751 char testcontext[] =
"test";
14752 char testmailbox[] =
"00000000";
14753 char from[] =
"[email protected]", cidnum[] =
"1234", cidname[] =
"Mark Spencer", format[] =
"gsm";
14754 char attach[256], attach2[256];
14755 char buf[256] =
"";
14763 enum { INT, FLAGVAL, STATIC, STRPTR }
type;
14770 {
"plain jane config", STATIC, vmus.
password, .u.strval =
"1234" },
14771 {
"emailsubject", STRPTR, vmus.
emailsubject, .u.strval =
"Oogly boogly\xf8koogly with what appears to be UTF-8" },
14772 {
"emailbody", STRPTR, vmus.
emailbody, .u.strval =
"This is a test\n\twith multiple\nlines\nwithin\n" },
14773 {
"serveremail", STATIC, vmus.
serveremail, .u.strval =
"\"\xf8Something\xe8that\xd8seems to have UTF-8 chars\" <[email protected]>" },
14774 {
"attachment flag", FLAGVAL, &vmus.
flags, .u.intval =
VM_ATTACH },
14775 {
"attach2", STRPTR, attach2, .u.strval =
"" },
14776 {
"attach", STRPTR, attach, .u.strval =
"" },
14782 info->name =
"test_voicemail_notify_endl";
14783 info->category =
"/apps/app_voicemail/";
14784 info->summary =
"Test Voicemail notification end-of-line";
14785 info->description =
14786 "Verify that notification emails use a consistent end-of-line character";
14795 if (!(vmu =
find_user(&vmus, testcontext, testmailbox)) &&
14801 if (vmu != &vmus && !(vmu =
find_user(&vmus, testcontext, testmailbox))) {
14808 #ifdef IMAP_STORAGE 14813 for (which = 0; which <
ARRAY_LEN(test_items); which++) {
14816 if (ftruncate(fileno(file), 0)) {
14823 if (test_items[which].
type == INT) {
14824 *((
int *) test_items[which].location) = test_items[which].u.intval;
14825 }
else if (test_items[which].
type == FLAGVAL) {
14831 }
else if (test_items[which].
type == STATIC) {
14832 strcpy(test_items[which].location, test_items[which].u.strval);
14833 }
else if (test_items[which].
type == STRPTR) {
14834 test_items[which].location = test_items[which].u.strval;
14837 make_email_file(file, from, vmu, 0, testcontext, testmailbox,
"INBOX", cidnum, cidname, attach, attach2, format, 999, 1, chan,
NULL, 0,
NULL,
NULL);
14839 while (fgets(buf,
sizeof(buf), file)) {
14841 (strlen(buf) > 1 &&
14842 #ifdef IMAP_STORAGE
14843 buf[strlen(buf) - 2] !=
'\r' 14845 buf[strlen(buf) - 2] ==
'\r' 14848 || buf[strlen(buf) - 1] !=
'\n') {
14870 info->name =
"test_voicemail_load_config";
14871 info->category =
"/apps/app_voicemail/";
14872 info->summary =
"Test loading Voicemail config";
14873 info->description =
14874 "Verify that configuration is loaded consistently. " 14875 "This is to test regressions of ASTERISK-18838 where it was noticed that " 14876 "some options were loaded after the mailboxes were instantiated, causing " 14877 "those options not to be set correctly.";
14884 if ((fd = mkstemp(config_filename)) < 0) {
14887 if (!(file = fdopen(fd,
"w"))) {
14889 unlink(config_filename);
14892 fputs(
"[general]\ncallback=somecontext\nlocale=de_DE.UTF-8\ntz=european\n[test]", file);
14893 fputs(
"00000001 => 9999,Mr. Test,,,callback=othercontext|locale=nl_NL.UTF-8|tz=central\n", file);
14894 fputs(
"00000002 => 9999,Mrs. Test\n", file);
14905 #define CHECK(u, attr, value) else if (strcmp(u->attr, value)) { \ 14906 ast_test_status_update(test, "mailbox %s should have %s '%s', but has '%s'\n", \ 14907 u->mailbox, #attr, value, u->attr); res = AST_TEST_FAIL; break; } 14911 if (!strcmp(vmu->
mailbox,
"00000001")) {
14913 CHECK(vmu, callback,
"othercontext")
14914 CHECK(vmu, locale,
"nl_NL.UTF-8")
14915 CHECK(vmu, zonetag,
"central")
14916 }
else if (!strcmp(vmu->
mailbox,
"00000002")) {
14918 CHECK(vmu, callback,
"somecontext")
14919 CHECK(vmu, locale,
"de_DE.UTF-8")
14920 CHECK(vmu, zonetag,
"european")
14931 unlink(config_filename);
14939 const char testcontext[] =
"test";
14940 const char testmailbox[] =
"00000000";
14941 const char vminfo_cmd[] =
"VM_INFO";
14942 char vminfo_buf[256], vminfo_args[256];
14945 int test_counter = 0;
14948 char *vminfo_test_args;
14949 char *vminfo_expected;
14953 {
"00000000@test,badparam",
"", -1 },
14954 {
"00000000@test",
"", -1 },
14955 {
"00000000@test,exists",
"1", 0 },
14956 {
"11111111@test,exists",
"0", 0 },
14958 {
"11111111@test,email",
"", 0 },
14959 {
"00000000@test,fullname",
"Test Framework Mailbox", 0 },
14961 {
"00000000@test,locale",
"en_US", 0 },
14962 {
"00000000@test,tz",
"central", 0 },
14963 {
"00000000@test,language",
"en", 0 },
14964 {
"00000000@test,password",
"9876", 0 },
14969 info->name =
"test_voicemail_vm_info";
14970 info->category =
"/apps/app_voicemail/";
14971 info->summary =
"VM_INFO unit test";
14972 info->description =
14973 "This tests passing various parameters to VM_INFO";
15001 for (test_counter = 0; test_counter <
ARRAY_LEN(test_items); test_counter++) {
15002 ast_copy_string(vminfo_args, test_items[test_counter].vminfo_test_args,
sizeof(vminfo_args));
15003 test_ret =
acf_vm_info(chan, vminfo_cmd, vminfo_args, vminfo_buf,
sizeof(vminfo_buf));
15004 if (strcmp(vminfo_buf, test_items[test_counter].vminfo_expected)) {
15005 ast_test_status_update(
test,
"VM_INFO respose was: '%s', but expected: '%s'\n", vminfo_buf, test_items[test_counter].vminfo_expected);
15008 if (!(test_ret == test_items[test_counter].vminfo_ret)) {
15009 ast_test_status_update(
test,
"VM_INFO return code was: '%i', but expected '%i'\n", test_ret, test_items[test_counter].vminfo_ret);
15063 #ifdef TEST_FRAMEWORK 15074 #ifdef TEST_FRAMEWORK 15077 ao2_ref(inprocess_container, -1);
15091 #ifdef IMAP_STORAGE 15106 prnt(where,
"Alias: %s Mailbox: %s", mapping->
alias, mapping->
mailbox);
15126 my_umask = umask(0);
15131 if (!inprocess_container) {
15136 alias_mailbox_mapping_hash_fn,
NULL, alias_mailbox_mapping_cmp_fn);
15137 if (!alias_mailbox_mappings) {
15138 ast_log(
LOG_ERROR,
"Unable to create alias_mailbox_mappings container\n");
15144 ast_log(
LOG_ERROR,
"Unable to register alias_mailbox_mappings container\n");
15151 mailbox_alias_mapping_hash_fn,
NULL, mailbox_alias_mapping_cmp_fn);
15152 if (!mailbox_alias_mappings) {
15153 ast_log(
LOG_ERROR,
"Unable to create mailbox_alias_mappings container\n");
15161 ast_log(
LOG_ERROR,
"Unable to register mailbox_alias_mappings container\n");
15190 #ifdef TEST_FRAMEWORK 15200 ast_log(
LOG_ERROR,
"Failure registering applications, functions or tests\n");
15223 #ifdef TEST_FRAMEWORK 15236 char destination[80] =
"";
15240 ast_verb(3,
"Destination number will be entered manually\n");
15241 while (retries < 3 && cmd !=
't') {
15242 destination[1] =
'\0';
15251 destination[0] = cmd;
15260 ast_verb(3,
"User hit '*' to cancel outgoing call\n");
15263 if ((cmd =
ast_readstring(chan, destination + strlen(destination),
sizeof(destination) - 1, 6000, 10000,
"#")) < 0)
15269 isprint(cmd) ? cmd :
'?', isprint(cmd) ? cmd :
'?');
15271 if (retries >= 3) {
15276 ast_verb(3,
"Destination number is CID number '%s'\n", num);
15281 if (destination[strlen(destination) -1 ] ==
'*')
15283 ast_verb(3,
"Placing outgoing call to extension '%s' in context '%s' from context '%s'\n", destination, outgoing_context,
ast_channel_context(chan));
15310 const char *origtime, *
context;
15321 snprintf(filename,
sizeof(filename),
"%s.txt", vms->
fn);
15338 if (!strncasecmp(
"macro", context, 5))
15358 while ((res > -1) && (res !=
't')) {
15382 ast_verb(3,
"Caller can not specify callback number - no dialout context available\n");
15404 ast_verb(3,
"Confirm CID number '%s' is number to use for callback\n", num);
15435 isprint(res) ? res :
'?', isprint(res) ? res :
'?');
15441 else if (res ==
'*')
15453 ast_verb(3,
"No CID number available, no reply sent\n");
15460 memset(&vmu2, 0,
sizeof(vmu2));
15465 snprintf(mailbox,
sizeof(mailbox),
"%s@%s", num, vmu->
context);
15467 ast_verb(3,
"Leaving voicemail for '%s' in context '%s'\n", num, vmu->
context);
15469 memset(&leave_options, 0,
sizeof(leave_options));
15480 ast_verb(3,
"No mailbox number '%s' in context '%s', no reply sent\n", num, vmu->
context);
15494 #ifndef IMAP_STORAGE 15497 vms->
heard[msg] = 1;
15505 int outsidecaller,
struct ast_vm_user *vmu,
int *duration,
int *sound_duration,
const char *unlockdir,
15506 signed char record_gain,
struct vm_state *vms,
char *flag,
const char *msg_id,
int forwardintro)
15511 int max_attempts = 3;
15514 int msg_exists = 0;
15515 signed char zero_gain = 0;
15517 char *acceptdtmf =
"#";
15518 char *canceldtmf =
"";
15519 int canceleddtmf = 0;
15524 if (duration ==
NULL) {
15529 if (!outsidecaller)
15530 snprintf(tempfile,
sizeof(tempfile),
"%s.tmp", recordfile);
15536 while ((cmd >= 0) && (cmd !=
't')) {
15545 ast_verb(3,
"Saving message as is\n");
15546 if (!outsidecaller)
15548 if (!forwardintro) {
15551 if (!outsidecaller) {
15553 STORE(recordfile, vmu->
mailbox, vmu->
context, -1, chan, vmu, fmt, *duration, vms, flag, msg_id);
15561 ast_verb(3,
"Reviewing the message\n");
15568 ast_verb(3,
"Re-recording the message\n");
15570 ast_verb(3,
"Recording the message\n");
15572 if (recorded && outsidecaller) {
15573 if (forwardintro) {
15586 cmd =
ast_play_and_record_full(chan, playfile, tempfile, maxtime, fmt, duration, sound_duration, 0, silencethreshold, maxsilence, unlockdir, acceptdtmf, canceldtmf, 0,
AST_RECORD_IF_EXISTS_OVERWRITE);
15587 if (strchr(canceldtmf, cmd)) {
15595 if (!outsidecaller) {
15603 }
else if (cmd ==
'*') {
15606 }
else if (vmu->review && sound_duration && (*sound_duration < 5)) {
15608 ast_verb(3,
"Message too short\n");
15612 }
else if (vmu->review && (cmd == 2 && sound_duration && *sound_duration < (maxsilence + 3))) {
15614 ast_verb(3,
"Nothing recorded\n");
15628 if (outsidecaller) {
15631 ast_verb(3,
"marking message as Urgent\n");
15633 strcpy(flag,
"Urgent");
15635 ast_verb(3,
"UNmarking message as Urgent\n");
15662 if (outsidecaller) {
15674 if (msg_exists || recorded) {
15682 }
else if (cmd ==
'4') {
15685 strcpy(flag,
"Urgent");
15691 DELETE(tempfile, -1, tempfile, vmu);
15705 if (!cmd && outsidecaller) {
15732 if (attempts > max_attempts) {
15737 if (!outsidecaller && (cmd == -1 || cmd ==
't')) {
15742 if (cmd !=
't' && outsidecaller)
15752 if (!(msg_snapshot =
ast_calloc(1,
sizeof(*msg_snapshot)))) {
15761 return msg_snapshot;
15772 #ifdef TEST_FRAMEWORK 15780 if (!strcmp(context, vmu->
context)
15781 && !strcmp(mailbox, vmu->
mailbox)) {
15819 int snapshot_index,
15835 snprintf(filename,
sizeof(filename),
"%s.txt", vms->
fn);
15859 filename,
id,
sizeof(
id), vmu, mailbox_index))) {
15890 switch (sort_val) {
15903 if (descending && val >= 0) {
15907 }
else if (!descending && val <= 0) {
15932 const char *context,
15933 const char *folder,
15936 int combine_INBOX_and_OLD)
15943 int this_index_only = -1;
15950 ast_log(
LOG_WARNING,
"Cannot create a mailbox snapshot since no mailbox was specified\n");
15954 memset(&vmus, 0,
sizeof(vmus));
15958 for (i = 0; i <
ARRAY_LEN(mailbox_folders); i++) {
15959 if (!strcasecmp(mailbox_folders[i], folder)) {
15960 this_index_only = i;
15964 if (this_index_only == -1) {
15970 if (!(vmu =
find_user(&vmus, context, mailbox))) {
15971 ast_log(
AST_LOG_WARNING,
"Failed to create mailbox snapshot for unknown voicemail user %s@%s\n", mailbox, context);
15975 if (!(mailbox_snapshot =
ast_calloc(1,
sizeof(*mailbox_snapshot)))) {
15989 for (i = 0; i < mailbox_snapshot->
folders; i++) {
15990 int msg_folder_index = i;
15997 if (!(this_index_only == -1 || this_index_only == i || (this_index_only == inbox_index && combine_INBOX_and_OLD && (i == old_index || i == urgent_index)))) {
16002 if (combine_INBOX_and_OLD && (i == old_index || i == urgent_index)) {
16003 msg_folder_index = inbox_index;
16006 memset(&vms, 0,
sizeof(vms));
16014 goto snapshot_cleanup;
16021 ast_log(
LOG_WARNING,
"Failed to create msg snapshots for %s@%s\n", mailbox, context);
16022 goto snapshot_cleanup;
16028 goto snapshot_cleanup;
16038 #ifdef IMAP_STORAGE 16040 vmstate_delete(&vms);
16045 return mailbox_snapshot;
16053 for (i = 0; i < mailbox_snapshot->
folders; i++) {
16086 for (i = 0; i < num_msgs; ++i) {
16087 const char *msg_id = msg_ids[i];
16090 const char *other_msg_id;
16096 snprintf(filename,
sizeof(filename),
"%s.txt", vms->
fn);
16107 if (!
ast_strlen_zero(other_msg_id) && !strcmp(other_msg_id, msg_id)) {
16112 msg_nums[i] = vms->
curmsg;
16133 int new = 0, old = 0, urgent = 0;
16134 char ext_context[1024];
16136 snprintf(ext_context,
sizeof(ext_context),
"%s@%s", vmu->
mailbox, vmu->
context);
16143 const char *from_context,
16144 const char *from_folder,
16145 const char *to_mailbox,
16146 const char *to_context,
16147 const char *to_folder,
16149 const char *msg_ids [],
16158 int from_folder_index;
16165 ast_log(
LOG_WARNING,
"Cannot forward message because either the from or to mailbox was not specified\n");
16170 ast_log(
LOG_WARNING,
"Invalid number of messages specified to forward: %zu\n", num_msgs);
16175 ast_log(
LOG_WARNING,
"Cannot forward message because the from_folder or to_folder was not specified\n");
16179 memset(&vmus, 0,
sizeof(vmus));
16180 memset(&to_vmus, 0,
sizeof(to_vmus));
16181 memset(&from_vms, 0,
sizeof(from_vms));
16184 if (from_folder_index == -1) {
16192 if (!(vmu =
find_user(&vmus, from_context, from_mailbox))) {
16193 ast_log(
LOG_WARNING,
"Can't find voicemail user to forward from (%s@%s)\n", from_mailbox, from_context);
16197 if (!(to_vmu =
find_user(&to_vmus, to_context, to_mailbox))) {
16198 ast_log(
LOG_WARNING,
"Can't find voicemail user to forward to (%s@%s)\n", to_mailbox, to_context);
16208 if ((res =
open_mailbox(&from_vms, vmu, from_folder_index)) < 0) {
16211 goto vm_forward_cleanup;
16216 if ((from_vms.
lastmsg + 1) < num_msgs) {
16217 ast_log(
LOG_WARNING,
"Folder %s has less than %zu messages\n", from_folder, num_msgs);
16219 goto vm_forward_cleanup;
16222 msg_nums =
ast_alloca(
sizeof(
int) * num_msgs);
16225 goto vm_forward_cleanup;
16229 for (i = 0; i < num_msgs; i++) {
16230 int cur_msg = msg_nums[i];
16235 snprintf(filename,
sizeof(filename),
"%s.txt", from_vms.
fn);
16247 duration = atoi(value);
16250 copy_message(
NULL, vmu, from_folder_index, cur_msg, duration, to_vmu, vmfmts, from_vms.
curdir,
"", to_folder);
16253 from_vms.
deleted[cur_msg] = 1;
16262 goto vm_forward_cleanup;
16266 vm_forward_cleanup:
16270 #ifdef IMAP_STORAGE 16272 vmstate_delete(&from_vms);
16286 const char *context,
16288 const char *oldfolder,
16289 const char *old_msg_ids [],
16290 const char *newfolder)
16294 int old_folder_index;
16295 int new_folder_index;
16307 ast_log(
LOG_WARNING,
"Invalid number of messages specified to move: %zu\n", num_msgs);
16312 ast_log(
LOG_WARNING,
"Cannot move message because either oldfolder or newfolder was not specified\n");
16319 memset(&vmus, 0,
sizeof(vmus));
16320 memset(&vms, 0,
sizeof(vms));
16322 if (old_folder_index == -1 || new_folder_index == -1) {
16326 if (!(vmu =
find_user(&vmus, context, mailbox))) {
16335 if ((res =
open_mailbox(&vms, vmu, old_folder_index)) < 0) {
16338 goto vm_move_cleanup;
16343 if ((vms.
lastmsg + 1) < num_msgs) {
16344 ast_log(
LOG_WARNING,
"Folder %s has less than %zu messages\n", oldfolder, num_msgs);
16346 goto vm_move_cleanup;
16349 old_msg_nums =
ast_alloca(
sizeof(
int) * num_msgs);
16352 goto vm_move_cleanup;
16356 for (i = 0; i < num_msgs; ++i) {
16359 goto vm_move_cleanup;
16361 vms.
deleted[old_msg_nums[i]] = 1;
16367 goto vm_move_cleanup;
16375 #ifdef IMAP_STORAGE 16377 vmstate_delete(&vms);
16390 const char *context,
16392 const char *folder,
16393 const char *msgs[])
16409 ast_log(
LOG_WARNING,
"Invalid number of messages specified to remove: %zu\n", num_msgs);
16418 memset(&vmus, 0,
sizeof(vmus));
16419 memset(&vms, 0,
sizeof(vms));
16422 if (folder_index == -1) {
16427 if (!(vmu =
find_user(&vmus, context, mailbox))) {
16428 ast_log(
LOG_WARNING,
"Can't find voicemail user to remove msg from (%s@%s)\n", mailbox, context);
16437 if ((res =
open_mailbox(&vms, vmu, folder_index)) < 0) {
16440 goto vm_remove_cleanup;
16445 if ((vms.
lastmsg + 1) < num_msgs) {
16448 goto vm_remove_cleanup;
16451 msg_nums =
ast_alloca(
sizeof(
int) * num_msgs);
16454 goto vm_remove_cleanup;
16457 for (i = 0; i < num_msgs; i++) {
16458 vms.
deleted[msg_nums[i]] = 1;
16465 goto vm_remove_cleanup;
16473 #ifdef IMAP_STORAGE 16475 vmstate_delete(&vms);
16488 const char *mailbox,
16489 const char *context,
16490 const char *folder,
16491 const char *msg_id,
16516 ast_log(
LOG_WARNING,
"Cannot play message because no message number was specified\n");
16520 memset(&vmus, 0,
sizeof(vmus));
16521 memset(&vms, 0,
sizeof(vms));
16524 context =
"default";
16527 if (!(vmu =
find_user(&vmus, context, mailbox))) {
16536 goto play2_msg_cleanup;
16542 goto play2_msg_cleanup;
16547 snprintf(filename,
sizeof(filename),
"%s.txt", vms.
fn);
16554 goto play2_msg_cleanup;
16557 duration = atoi(value);
16561 #ifdef IMAP_STORAGE 16570 cb(chan, vms.
fn, duration);
16571 }
else if ((
wait_file(chan, &vms, vms.
fn)) < 0) {
16587 #ifdef IMAP_STORAGE 16589 vmstate_delete(&vms);
16610 .optional_modules =
"res_adsi,res_smdi",
unsigned int module_version
The version of this function table.
int ast_filecopy(const char *oldname, const char *newname, const char *fmt)
Copies a file.
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
struct ast_category * ast_category_new(const char *name, const char *in_file, int lineno)
Create a category.
static int mwi_handle_unsubscribe2(void *data)
struct ast_variable * ast_load_realtime(const char *family,...) attribute_sentinel
struct ast_variable * next
#define AST_THREADSTORAGE(name)
Define a thread storage variable.
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, const char *dest_folder)
Copies a message from one mailbox to another.
static int saydurationminfo
#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)
int ast_delete_mwi_state_full(const char *mailbox, const char *context, struct ast_eid *eid)
Delete MWI state cached by stasis with all parameters.
#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)
int ast_config_text_file_save(const char *filename, const struct ast_config *cfg, const char *generator)
Save a config text file preserving the pre 13.2 behavior.
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]
Asterisk locking-related definitions:
void astman_append(struct mansession *s, const char *fmt,...)
static struct ast_custom_function vm_info_acf
Asterisk main include file. File version handling, generic pbx functions.
static int vm_play_folder_name_ja(struct ast_channel *chan, char *box)
static const char * substitute_escapes(const char *value)
static const struct ast_vm_functions vm_table
#define ast_realloc(p, len)
A wrapper for realloc()
static int vm_instructions_ja(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int skipadvanced, int in_urgent)
int ast_adsi_begin_download(struct ast_channel *chan, char *service, unsigned char *fdn, unsigned char *sec, int version)
static int load_config(int reload)
static void apply_options_full(struct ast_vm_user *retval, struct ast_variable *var)
Loads the options specific to a voicemail user.
static int get_folder_ja(struct ast_channel *chan, int start)
#define MAX_VM_CONTEXT_LEN
static FILE * vm_mkftemp(char *template)
unsigned char iobuf[BASEMAXINLINE]
#define DEFAULT_LISTEN_CONTROL_REVERSE_KEY
int ast_callerid_split(const char *src, char *name, int namelen, char *num, int numlen)
#define MAX_NUM_CID_CONTEXTS
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 char vm_newuser[80]
static void rename_file(char *sfn, char *dfn)
Renames a message in a mailbox folder.
void ast_unreplace_sigchld(void)
Restore the SIGCHLD handler.
String manipulation functions.
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.
void ast_channel_set_writeformat(struct ast_channel *chan, struct ast_format *format)
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
int ast_adsi_data_mode(unsigned char *buf)
Puts CPE in data mode.
static void free_vm_users(void)
Free the users structure.
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.
int(*const write)(struct ast_channel *chan, struct ast_frame *frame)
Write a frame, in standard format (see frame.h)
#define ast_channel_unref(c)
Decrease channel reference count.
static char * voicemailmain_app
The arg parameter is a search key, but is not an object.
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 int vm_msg_snapshot_create(struct ast_vm_user *vmu, struct vm_state *vms, struct ast_vm_mailbox_snapshot *mailbox_snapshot, int snapshot_index, int mailbox_index, int descending, enum ast_vm_snapshot_sort_val sort_val)
Create and store off all the msgs in an open mailbox.
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
const ast_string_field recording_file
static char pagerdateformat[32]
static int adsi_logo(unsigned char *buf)
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
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.
const ast_string_field mailbox
static int manager_status_voicemail_user(struct mansession *s, const struct message *m)
#define SMDI_MWI_WAIT_TIMEOUT
Convenient Signal Processing routines.
static int play_message_callerid(struct ast_channel *chan, struct vm_state *vms, char *cid, const char *context, int callback, int saycidnumber)
static int inprocess_cmp_fn(void *obj, void *arg, int flags)
void ast_channel_set_rawwriteformat(struct ast_channel *chan, struct ast_format *format)
#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.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
void ast_install_vm_test_functions(ast_vm_test_create_user_fn *vm_test_create_user_func, ast_vm_test_destroy_user_fn *vm_test_destroy_user_func)
void astman_send_list_complete_start(struct mansession *s, const struct message *m, const char *event_name, int count)
Start the list complete 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.
static int vm_browse_messages_gr(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
Greek syntax for 'You have N messages' greeting.
descriptor for a cli entry.
void ast_uninstall_vm_test_functions(void)
static int sayname(struct ast_channel *chan, const char *mailbox, const char *context)
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
static struct ao2_container * alias_mailbox_mappings
int ast_file_is_readable(const char *filename)
Test that a file exists and is readable by the effective user.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Voicemail greeter function table definition.
static char intro[ADSI_MAX_INTRO][20]
static int debug
Global debug status.
#define AST_TASKPROCESSOR_HIGH_WATER_LEVEL
#define ao2_callback(c, flags, cb_fn, arg)
static int vm_intro_ja(struct ast_channel *chan, struct vm_state *vms)
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...
int ast_unload_realtime(const char *family)
Release any resources cached for a realtime family.
#define CONFIG_STATUS_FILEINVALID
static int vm_intro_de(struct ast_channel *chan, struct vm_state *vms)
static struct stasis_rest_handlers mailboxes
REST handler for /api-docs/mailboxes.json.
struct ast_smdi_interface * ast_smdi_interface_find(const char *iface_name)
Find an SMDI interface with the specified name.
static void print_mappings(void *v_obj, void *where, ao2_prnt_fn *prnt)
int ast_odbc_prepare(struct odbc_obj *obj, SQLHSTMT *stmt, const char *sql)
Prepares a SQL query on a statement.
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.
void(* on_subscribe)(const char *mailbox, struct ast_mwi_subscriber *sub)
Raised when MWI is being subscribed.
static int vm_browse_messages_ja(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
Japanese syntax for 'You have N messages' greeting.
int ast_check_realtime(const char *family)
Check if realtime engine is configured for family.
Structure for variables, used for configurations and for channel variables.
void ast_close_fds_above_n(int n)
Common routine for child processes, to close all fds prior to exec(2)
static int append_vmu_info_astman(struct mansession *s, struct ast_vm_user *vmu, const char *event_name, const char *actionid)
Append vmu info string into given astman with event_name.
static unsigned char adsisec[4]
static int vm_sayname(struct ast_channel *chan, const char *mailbox_id)
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.
#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 manager_voicemail_refresh(struct mansession *s, const struct message *m)
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)
int ast_say_digit_str(struct ast_channel *chan, const char *num, const char *ints, const char *lang)
says digits of a string
#define AST_TEST_REGISTER(cb)
static int messagecount(const char *mailbox_id, const char *folder)
int ast_adsi_download_disconnect(unsigned char *buf)
Disconnects (and hopefully saves) a downloaded script.
ast_channel_state
ast_channel states
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)
static char listen_control_reverse_key[12]
static const struct ast_vm_greeter_functions vm_greeter_table
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
#define ast_cli_register_multiple(e, len)
Register multiple commands.
void ast_vm_unregister(const char *module_name)
Unregister the specified voicemail provider.
static struct ast_threadstorage buf2
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
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().
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...
#define VM_GREETER_MODULE_VERSION
static int vm_newuser_setup(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain)
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
static int play_message_by_id_helper(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, const char *msg_id)
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 ...
static int get_folder_by_name(const char *name)
static char aliasescontext[MAX_VM_CONTEXT_LEN]
#define ast_copy_flags(dest, src, flagz)
#define ast_str_alloca(init_len)
static void load_aliases(struct ast_config *cfg)
static int vm_allocate_dh(struct vm_state *vms, struct ast_vm_user *vmu, int count_msg)
#define ast_strdup(str)
A wrapper for strdup()
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, const char *msg_id)
static int unload_module(void)
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_mwi_state_callback_subscribed(on_mwi_state handler, void *data)
For each managed mailbox that has a subscriber call the given handler.
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
int ast_taskprocessor_alert_set_levels(struct ast_taskprocessor *tps, long low_water, long high_water)
Set the high and low alert water marks of the given taskprocessor queue.
static ast_cond_t poll_cond
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
static void mwi_handle_subscribe(const char *id, struct ast_mwi_subscriber *sub)
static char externnotify[160]
static int inprocess_count(const char *context, const char *mailbox, int delta)
int ast_unlock_path(const char *path)
Unlock a path.
struct ast_mwi_state * ast_mwi_subscriber_data(struct ast_mwi_subscriber *sub)
Retrieves the state data object associated with the MWI subscriber.
static int inbuf(struct baseio *bio, FILE *fi)
utility used by inchar(), for base_encode()
static char * emailsubject
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.
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)
void ast_category_destroy(struct ast_category *cat)
static int input(yyscan_t yyscanner)
int ast_mwi_add_observer(struct ast_mwi_observer *observer)
Add an observer to receive MWI state related events.
static int inboxcount2(const char *mailbox, int *urgentmsgs, int *newmsgs, int *oldmsgs)
Check the given mailbox's message count.
int ast_channel_setoption(struct ast_channel *channel, int option, void *data, int datalen, int block)
Sets an option on a channel.
list of users found in the config file
static int vm_msg_remove(const char *mailbox, const char *context, size_t num_msgs, const char *folder, const char *msgs[])
int ast_unregister_application(const char *app)
Unregister an application.
#define CHECK(u, attr, value)
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
static char cid_num[AST_MAX_EXTENSION]
#define ast_cond_signal(cond)
int ast_channel_priority(const struct ast_channel *chan)
static struct ast_str * password
const ast_string_field folder
static char * playmsg_app
static struct ast_smdi_interface * smdi_iface
static char fromstring[100]
int ast_update_realtime(const char *family, const char *keyfield, const char *lookup,...) attribute_sentinel
Update realtime configuration.
#define ast_verb(level,...)
void() ast_vm_msg_play_cb(struct ast_channel *chan, const char *playfile, int duration)
Voicemail playback callback function definition.
static const struct ast_app_option vm_app_options[128]
char context[MAX_VM_CONTEXT_LEN]
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.
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
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.
def from_mailbox(key, val, section, pjsip, nmapped)
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
#define STORE(a, b, c, d, e, f, g, h, i, j, k)
static int vm_msg_play(struct ast_channel *chan, const char *mailbox, const char *context, const char *folder, const char *msg_num, ast_vm_msg_play_cb cb)
const ast_string_field recording_ext
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
static void load_users(struct ast_config *cfg)
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
void() ao2_prnt_fn(void *where, const char *fmt,...)
Print output.
pthread_cond_t ast_cond_t
#define ast_strlen_zero(foo)
static const char * mbox(struct ast_vm_user *vmu, int id)
char cause[SMDI_MWI_FAIL_CAUSE_LEN+1]
int ast_update2_realtime(const char *family,...) attribute_sentinel
Update realtime configuration.
All configuration options for statsd client.
off_t ast_tellstream(struct ast_filestream *fs)
Tell where we are in a stream.
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_vm_user::@82 list
AO2_STRING_FIELD_HASH_FN(alias_mailbox_mapping, alias)
int ast_smdi_mwi_set(struct ast_smdi_interface *iface, const char *mailbox)
Set the MWI indicator for a mailbox.
#define AST_APP_OPTIONS(holder, options...)
Declares an array of options for an application.
void ast_channel_tech_set(struct ast_channel *chan, const struct ast_channel_tech *value)
#define ALIASES_OUTPUT_FORMAT
static int add_message_id(struct ast_config *msg_cfg, char *dir, int msg, char *filename, char *id, size_t id_size, struct ast_vm_user *vmu, int folder)
AST_TEST_DEFINE(test_voicemail_vmuser)
#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 char pagerfromstring[100]
enum AST_LOCK_RESULT ast_lock_path(const char *path)
Lock a filesystem path.
Configuration File Parser.
static void vm_change_password(struct ast_vm_user *vmu, const char *newpassword)
The handler for the change password option.
void ao2_container_unregister(const char *name)
Unregister a container for CLI stats and integrity check.
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 char mailbox[AST_MAX_MAILBOX_UNIQUEID]
static int vm_intro_multilang(struct ast_channel *chan, struct vm_state *vms, const char message_gender[])
int ast_app_inboxcount2(const char *mailboxes, int *urgentmsgs, int *newmsgs, int *oldmsgs)
Determine number of urgent/new/old messages in a mailbox.
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]
int ao2_container_register(const char *name, struct ao2_container *self, ao2_prnt_obj_fn *prnt_obj)
Register a container for CLI stats and integrity check.
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
static int vm_browse_messages_it(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
Italian syntax for 'You have N messages' greeting.
int ast_adsi_set_line(unsigned char *buf, int page, int line)
Sets the current line and page.
void ast_channel_set_rawreadformat(struct ast_channel *chan, struct ast_format *format)
static int inprocess_hash_fn(const void *obj, const int flags)
static int vm_msg_forward(const char *from_mailbox, const char *from_context, const char *from_folder, const char *to_mailbox, const char *to_context, const char *to_folder, size_t num_msgs, const char *msg_ids[], int delete_old)
static void load_zonemessages(struct ast_config *cfg)
static struct ast_vm_msg_snapshot * vm_msg_snapshot_destroy(struct ast_vm_msg_snapshot *msg_snapshot)
#define ast_config_load(filename, flags)
Load a config file.
int ast_adsi_input_format(unsigned char *buf, int num, int dir, int wrap, char *format1, char *format2)
Set input format.
static char * config_filename
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)
static int vm_browse_messages_es(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
Spanish syntax for 'You have N messages' greeting.
int ast_say_counted_noun(struct ast_channel *chan, int num, const char *noun)
int ast_store_realtime(const char *family,...) attribute_sentinel
Create realtime configuration.
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.
const ast_string_field call_macrocontext
static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms)
General Asterisk PBX channel definitions.
int ast_realtime_require_field(const char *family,...) attribute_sentinel
Inform realtime what fields that may be stored.
static char dialcontext[AST_MAX_CONTEXT]
Asterisk file paths, configured in asterisk.conf.
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
static int quote(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
static const char *const mailbox_folders[]
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
#define ast_test_status_update(a, b, c...)
static char * vmauthenticate_app
static int vm_execmain(struct ast_channel *chan, const char *data)
void ast_channel_nativeformats_set(struct ast_channel *chan, struct ast_format_cap *value)
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
static struct ast_flags globalflags
static void notify_new_state(struct ast_vm_user *vmu)
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 DEFAULT_LISTEN_CONTROL_STOP_KEY
#define AST_PTHREADT_NULL
#define ast_dummy_channel_alloc()
Create a fake channel structure.
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)
static int silencethreshold
static void * mb_poll_thread(void *data)
#define AST_MAX_EXTENSION
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)
Caller Party information.
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
static char vm_reenterpassword[80]
structure to hold extensions
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.
#define ao2_ref(o, delta)
void ast_channel_set_readformat(struct ast_channel *chan, struct ast_format *format)
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
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 beep, int silencethreshold, int maxsilence_ms, const char *path, const char *acceptdtmf, const char *canceldtmf, int skip_confirmation_sound, enum ast_record_if_exists if_exists)
Record a file based on input from a channel This function will play "auth-thankyou" upon successful r...
void ast_config_destroy(struct ast_config *config)
Destroys a config.
In case you didn't read that giant block of text above the mansession_session struct, the struct mansession is named this solely to keep the API the same in Asterisk. This structure really represents data that is different from Manager action to Manager action. The mansession_session pointer contained within points to session-specific data.
#define VM_MODULE_VERSION
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.
#define ast_strdupa(s)
duplicate a string in memory from the stack
static void generate_msg_id(char *dst)
Sets the destination string to a uniquely identifying msg_id string.
const ast_string_field origtime
static int say_and_wait(struct ast_channel *chan, int num, const char *language)
static const char * vm_index_to_foldername(int id)
static void queue_mwi_event(const char *channel_id, const char *box, int urgent, int new, int old)
#define COPY(a, b, c, d, e, f, g, h)
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)
#define ast_malloc(len)
A wrapper for malloc()
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)
#define ast_variable_new(name, value, filename)
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.
static char VM_SPOOL_DIR[PATH_MAX]
int ast_say_character_str(struct ast_channel *chan, const char *num, const char *ints, const char *lang, enum ast_say_case_sensitivity sensitivity)
function to pronounce character and phonetic strings
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
static int 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)
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
static int vm_delete(char *file)
Removes the voicemail sound and information file.
struct ast_config * ast_config_new(void)
Create a new base configuration structure.
int ast_ratestream(struct ast_filestream *fs)
Return the sample rate of the stream's format.
#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.
const char * ast_channel_exten(const struct ast_channel *chan)
Core PBX routines and definitions.
static char vm_mismatch[80]
void ast_vm_greeter_unregister(const char *module_name)
Unregister the specified voicemail greeter provider.
const ast_string_field call_callerid
static char vm_pls_try_again[80]
#define CONFIG_STATUS_FILEUNCHANGED
static struct ast_taskprocessor * mwi_subscription_tps
#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,...)
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
const char * ast_channel_uniqueid(const struct ast_channel *chan)
static void apply_option(struct ast_vm_user *vmu, const char *var, const char *value)
Sets a specific property value.
#define ast_vm_register(vm_table)
See __ast_vm_register()
static void run_externnotify(const char *context, const char *extension, const char *flag)
static int vm_intro(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms)
const char * ast_config_AST_DATA_DIR
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
#define DEFAULT_POLL_FREQ
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
#define HVSU_OUTPUT_FORMAT
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)
struct ast_config * ast_load_realtime_multientry(const char *family,...) attribute_sentinel
Retrieve realtime configuration.
static int poll_subscribed_mailbox(struct ast_mwi_state *mwi_state, void *data)
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_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.
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
static struct ast_vm_user * find_user_realtime(struct ast_vm_user *ivm, const char *context, const char *mailbox)
Finds a voicemail user from the realtime engine.
static int vm_test_destroy_user(const char *context, const char *mailbox)
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 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, const char *msg_id, int forwardintro)
AO2_STRING_FIELD_CMP_FN(alias_mailbox_mapping, alias)
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 ...
int ast_safe_system(const char *s)
Safely spawn an OS shell command while closing file descriptors.
void ast_mwi_remove_observer(struct ast_mwi_observer *observer)
Remove an MWI state observer.
#define AST_OPTION_RXGAIN
static char * handle_voicemail_show_aliases(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Show a list of voicemail zones in the CLI.
#define RENAME(a, b, c, d, e, f, g, h)
char * mkdtemp(char *template_s)
#define AST_APP_OPTION_ARG(option, flagno, argno)
Declares an application option that accepts an argument.
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.
struct ast_vm_mailbox_snapshot::@223 * snapshots
const char * module_name
The name of the module that provides the voicemail greeter functionality.
static unsigned int poll_mailboxes
static char listen_control_restart_key[12]
static struct ast_vm_mailbox_snapshot * vm_mailbox_snapshot_destroy(struct ast_vm_mailbox_snapshot *mailbox_snapshot)
#define AST_TEST_UNREGISTER(cb)
static const struct cfalias aliases[]
#define AST_NONSTANDARD_APP_ARGS(args, parse, sep)
Performs the 'nonstandard' argument separation process for an application.
const ast_string_field context
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
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 int vm_intro_is(struct ast_channel *chan, struct vm_state *vms)
int ast_safe_fork(int stop_reaper)
Common routine to safely fork without a chance of a signal handler firing badly in the child...
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_intro_vi(struct ast_channel *chan, struct vm_state *vms)
#define ao2_iterator_next(iter)
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()
const ast_string_field call_callerchan
int ast_goto_if_exists(struct ast_channel *chan, const char *context, const char *exten, int priority)
#define VOICEMAIL_DIR_MODE
char * strcasestr(const char *, const char *)
static void adsi_goodbye(struct ast_channel *chan)
int ast_seekstream(struct ast_filestream *fs, off_t sample_offset, int whence)
Seeks into stream.
static int vm_instructions(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int skipadvanced, int in_urgent)
#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.
static int manager_match_mailbox(struct ast_mwi_state *mwi_state, void *data)
#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 int vm_playmsgexec(struct ast_channel *chan, const char *data)
static void parse(struct mgcp_request *req)
static int mwi_handle_subscribe2(void *data)
static int load_config_from_memory(int reload, struct ast_config *cfg, struct ast_config *ucfg)
static int save_to_folder(struct ast_vm_user *vmu, struct vm_state *vms, int msg, int box, int *newmsg, int move)
static char emaildateformat[32]
void ast_mwi_state_callback_all(on_mwi_state handler, void *data)
For each managed mailbox call the given handler.
#define ast_calloc(num, len)
A wrapper for calloc()
#define ast_pthread_create(a, b, c, d)
static int vm_browse_messages_pt(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
Portuguese syntax for 'You have N messages' greeting.
static void mwi_handle_unsubscribe(const char *id, struct ast_mwi_subscriber *sub)
static int separate_mailbox(char *mailbox_id, char **mailbox, char **context)
static int fake_write(struct ast_channel *ast, struct ast_frame *frame)
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.
#define ast_odbc_request_obj(a, b)
static char * voicemail_app
int ast_closestream(struct ast_filestream *f)
Closes a stream.
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
static int inchar(struct baseio *bio, FILE *fi)
utility used by base_encode()
static int load_module(void)
Load the module.
static char vm_passchanged[80]
SMDI support for Asterisk.
static int msg_create_from_file(struct ast_vm_recording_data *recdata)
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.
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.
Module has failed to load, may be in an inconsistent state.
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[]
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...
#define ast_publish_mwi_state_channel(mailbox, context, new_msgs, old_msgs, channel_id)
Publish a MWI state update associated with some channel.
#define ao2_find(container, arg, flags)
#define MAX_VM_MBOX_ID_LEN
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_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.
char fwd_st[SMDI_MAX_STATION_NUM_LEN+1]
char language[MAX_LANGUAGE]
static char listen_control_pause_key[12]
structure to hold users read from users.conf
static struct ao2_container * mailbox_alias_mappings
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_app_has_voicemail(const char *mailboxes, 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_clear_flag(p, flag)
struct ast_party_redirecting * ast_channel_redirecting(struct ast_channel *chan)
Support for logging to various files, console and syslog Configuration in file logger.conf.
static char cid_name[AST_MAX_EXTENSION]
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS|AST_MODFLAG_LOAD_ORDER, "HTTP Phone Provisioning",.support_level=AST_MODULE_SUPPORT_EXTENDED,.load=load_module,.unload=unload_module,.reload=reload,.load_pri=AST_MODPRI_CHANNEL_DEPEND,.requires="http",)
Options for leaving voicemail with the voicemail() application.
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
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)
void ast_variable_append(struct ast_category *category, struct ast_variable *variable)
int ast_app_messagecount(const char *mailbox_id, const char *folder)
Get the number of messages in a given mailbox folder.
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...
static int vm_intro_pt_BR(struct ast_channel *chan, struct vm_state *vms)
void ast_category_append(struct ast_config *config, struct ast_category *cat)
Appends a category to a config.
#define RETRIEVE(a, b, c, d)
struct ast_frame ast_null_frame
static struct ast_vm_msg_snapshot * vm_msg_snapshot_alloc(void)
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
const char * module_name
The name of the module that provides the voicemail functionality.
SQLRETURN ast_odbc_execute_sql(struct odbc_obj *obj, SQLHSTMT *stmt, const char *sql)
Execute a nonprepared SQL query.
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
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
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.
char * strsep(char **str, const char *delims)
Structure used for ast_copy_recording_to_vm in order to cleanly supply data needed for making the rec...
A ast_taskprocessor structure is a singleton by name.
int ast_taskprocessor_push(struct ast_taskprocessor *tps, int(*task_exe)(void *datap), void *datap) attribute_warn_unused_result
Push a task into the specified taskprocessor queue and signal the taskprocessor thread.
This structure is allocated by file.c in one chunk, together with buf_size and desc_size bytes of mem...
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
int ast_say_number(struct ast_channel *chan, int num, const char *ints, const char *lang, const char *options)
says a number
Standard Command Line Interface.
int ast_destroy_realtime(const char *family, const char *keyfield, const char *lookup,...) attribute_sentinel
Destroy realtime configuration.
static int has_voicemail(const char *mailbox, const char *folder)
Determines if the given folder has messages.
void ast_channel_context_set(struct ast_channel *chan, const char *value)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
static void start_poll_thread(void)
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.
ast_app: A registered application
const char * ast_channel_name(const struct ast_channel *chan)
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...
MWI state event interface.
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.
const ast_string_field uniqueid
#define EXISTS(a, b, c, d)
static void free_user_final(struct ast_vm_user *vmu)
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)
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)
static int inboxcount(const char *mailbox, int *newmsgs, int *oldmsgs)
const char * ast_config_option(struct ast_config *cfg, const char *cat, const char *var)
Retrieve a configuration variable within the configuration set.
struct stasis_forward * sub
static void vm_change_password_shell(struct ast_vm_user *vmu, char *newpassword)
Data structure associated with a single frame of data.
struct ast_filestream * ast_readfile(const char *filename, const char *type, const char *comment, int flags, int check, mode_t mode)
Starts reading from a file.
const char * ast_channel_language(const struct ast_channel *chan)
#define VMSTATE_MAX_MSG_ARRAY
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)
unsigned int module_version
The version of this function table.
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)
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.
struct ast_mwi_observer mwi_observer
const char * ast_channel_context(const struct ast_channel *chan)
#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 int is_valid_dtmf(const char *key)
Determines if a DTMF key entered is valid.
#define UPDATE_MSG_ID(a, b, c, d, e, f)
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
static struct ast_vm_mailbox_snapshot * vm_mailbox_snapshot_create(const char *mailbox, const char *context, const char *folder, int descending, enum ast_vm_snapshot_sort_val sort_val, int combine_INBOX_and_OLD)
static int vm_exec(struct ast_channel *chan, const char *data)
const ast_string_field call_context
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.
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]
static int vm_msg_move(const char *mailbox, const char *context, size_t num_msgs, const char *oldfolder, const char *old_msg_ids[], const char *newfolder)
int ast_readstring(struct ast_channel *c, char *s, int len, int timeout, int rtimeout, char *enders)
Reads multiple digits.
#define AST_APP_OPTION(option, flagno)
Declares an application option that does not accept an argument.
#define ast_mutex_destroy(a)
static int acf_vm_info(struct ast_channel *chan, const char *cmd, char *args, char *buf, size_t len)
struct ast_category * ast_category_get(const struct ast_config *config, const char *category_name, const char *filter)
Retrieve a category if it exists.
static unsigned char poll_thread_run
static int message_range_and_existence_check(struct vm_state *vms, const char *msg_ids [], size_t num_msgs, int *msg_nums, struct ast_vm_user *vmu)
common bounds checking and existence check for Voicemail API functions.
#define AST_LIST_INSERT_BEFORE_CURRENT(elm, field)
Inserts a list entry before the current entry during a traversal.
int ast_adsi_unload_session(struct ast_channel *chan)
static int vm_test_create_user(const char *context, const char *mailbox)
const char * ast_channel_macrocontext(const struct ast_channel *chan)
void ast_odbc_release_obj(struct odbc_obj *obj)
Releases an ODBC object previously allocated by ast_odbc_request_obj()
The structure that contains MWI state.
static struct ast_frame * fake_read(struct ast_channel *ast)
struct ast_app * pbx_findapp(const char *app)
Look up an application.
void ast_party_caller_init(struct ast_party_caller *init)
Initialize the given caller structure.
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Say numbers and dates (maybe words one day too)
static void adsi_delete(struct ast_channel *chan, struct vm_state *vms)
#define ASTERISK_GPL_KEY
The text the key() function should return.
#define DEBUG_ATLEAST(level)
static char vm_newpassword[80]
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, const char *msg_id)
Creates the email file to be sent to indicate a new voicemail exists for a user.
void ast_channel_priority_set(struct ast_channel *chan, int value)
#define ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag,...)
Create a channel structure.
static const 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.
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.
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Asterisk module definitions.
Voicemail function table definition.
static void delete_file(struct phoneprov_file *file)
static int msg_id_incrementor
static snd_pcm_format_t format
static int vmauthenticate(struct ast_channel *chan, const char *data)
char mailbox[MAX_VM_MBOX_ID_LEN]
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
static char serveremail[80]
#define ast_vm_greeter_register(vm_table)
See __ast_vm_greeter_register()
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
static struct alias_mailbox_mapping * alias_mailbox_mapping_create(const char *alias, const char *mailbox)
static int play_message_by_id(struct ast_channel *chan, const char *mailbox, const char *context, const char *msg_id)
Finds a message in a specific mailbox by msg_id and plays it to the channel.
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 ...
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#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]
#define ast_custom_function_register(acf)
Register a custom function.
#define AST_MUTEX_DEFINE_STATIC(mutex)
int ast_stopstream(struct ast_channel *c)
Stops a stream.
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
static int 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.
const ast_string_field call_extension
static int reset_user_pw(const char *context, const char *mailbox, const char *newpass)
Resets a user password to a specified password.
#define MAX_VM_MAILBOX_LEN
#define DEFAULT_LISTEN_CONTROL_RESTART_KEY
static unsigned int poll_freq
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
struct ao2_container * inprocess_container
int ast_app_inboxcount(const char *mailboxes, int *newmsgs, int *oldmsgs)
Determine number of new/old messages in a mailbox.
#define ast_mutex_unlock(a)
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'.
#define AST_APP_ARG(name)
Define an application argument.
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)
#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)
#define MAX_MAIL_BODY_CONTENT_SIZE
static int play_message_datetime(struct ast_channel *chan, struct ast_vm_user *vmu, const char *origtime, const char *filename)
void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag)
Send ack in manager transaction to begin a list.
struct ast_party_number number
Subscriber phone number.
#define ao2_link(container, obj)