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__)
568static char imapserver[48] =
"localhost";
569static char imapport[8] =
"143";
570static char imapflags[128];
571static char imapfolder[64] =
"INBOX";
572static char imapparentfolder[64];
573static char greetingfolder[64] =
"INBOX";
574static char authuser[32];
575static char authpassword[42];
576static int imapversion = 1;
578static int expungeonhangup = 1;
579static int imapgreetings;
580static int imap_poll_logout;
581static char delimiter;
592static int init_mailstream(
struct vm_state *vms,
int box);
593static void write_file(
char *filename,
char *buffer,
unsigned long len);
594static char *get_header_by_tag(
char *
header,
char *tag,
char *
buf,
size_t len);
595static void vm_imap_delete(
char *
file,
int msgnum,
struct ast_vm_user *vmu);
596static char *get_user_by_mailbox(
char *
mailbox,
char *
buf,
size_t len);
597static struct vm_state *get_vm_state_by_imapuser(
const char *
user,
int interactive);
598static struct vm_state *get_vm_state_by_mailbox(
const char *
mailbox,
const char *
context,
int interactive);
600static void vmstate_insert(
struct vm_state *vms);
601static void vmstate_delete(
struct vm_state *vms);
602static void set_update(MAILSTREAM * stream);
603static void init_vm_state(
struct vm_state *vms);
604static int save_body(BODY *body,
struct vm_state *vms,
char *section,
char *format,
int is_intro);
605static void get_mailbox_delimiter(
struct vm_state *vms, MAILSTREAM *stream);
606static void mm_parsequota (MAILSTREAM *stream,
unsigned char *msg, QUOTALIST *pquota);
607static void imap_mailbox_name(
char *spec,
size_t len,
struct vm_state *vms,
int box,
int target);
608static 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);
609static 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);
610static void update_messages_by_imapuser(
const char *
user,
unsigned long number);
613static int imap_remove_file (
char *dir,
int msgnum);
614static int imap_retrieve_file (
const char *dir,
const int msgnum,
const char *
mailbox,
const char *
context);
615static int imap_delete_old_greeting (
char *dir,
struct vm_state *vms);
618static void imap_logout(
const char *mailbox_id);
629#define SMDI_MWI_WAIT_TIMEOUT 1000
631#define COMMAND_TIMEOUT 5000
633#define VOICEMAIL_DIR_MODE 0777
634#define VOICEMAIL_FILE_MODE 0666
635#define CHUNKSIZE 65536
637#define VOICEMAIL_CONFIG "voicemail.conf"
638#define ASTERISK_USERNAME "asterisk"
643#define DEFAULT_LISTEN_CONTROL_FORWARD_KEY "#"
644#define DEFAULT_LISTEN_CONTROL_REVERSE_KEY "*"
645#define DEFAULT_LISTEN_CONTROL_PAUSE_KEY "0"
646#define DEFAULT_LISTEN_CONTROL_RESTART_KEY "2"
647#define DEFAULT_LISTEN_CONTROL_STOP_KEY "13456789"
648#define VALID_DTMF "1234567890*#"
652#define SENDMAIL "/usr/sbin/sendmail -t"
653#define INTRO "vm-intro"
655#define MAX_MAIL_BODY_CONTENT_SIZE 134217728L
658#define MAXMSGLIMIT 9999
668#define MAX_DATETIME_FORMAT 512
669#define MAX_NUM_CID_CONTEXTS 10
671#define VM_REVIEW (1 << 0)
672#define VM_OPERATOR (1 << 1)
673#define VM_SAYCID (1 << 2)
674#define VM_SVMAIL (1 << 3)
675#define VM_ENVELOPE (1 << 4)
676#define VM_SAYDURATION (1 << 5)
677#define VM_SKIPAFTERCMD (1 << 6)
678#define VM_FORCENAME (1 << 7)
679#define VM_FORCEGREET (1 << 8)
680#define VM_PBXSKIP (1 << 9)
681#define VM_DIRECTFORWARD (1 << 10)
682#define VM_ATTACH (1 << 11)
683#define VM_DELETE (1 << 12)
684#define VM_ALLOCED (1 << 13)
685#define VM_SEARCH (1 << 14)
686#define VM_TEMPGREETWARN (1 << 15)
687#define VM_MOVEHEARD (1 << 16)
688#define VM_MESSAGEWRAP (1 << 17)
689#define VM_FWDURGAUTO (1 << 18)
690#define VM_EMAIL_EXT_RECS (1 << 19)
691#define VM_MARK_URGENT (1 << 20)
692#define VM_ODBC_AUDIO_ON_DISK (1 << 21)
694#define ERROR_LOCK_PATH -100
695#define ERROR_MAX_MSGS -101
696#define OPERATOR_EXIT 300
698#define MSGFILE_LEN (7)
785#define force_reload_config() load_config_force(1, 1)
885#define MAX_VM_MBOX_ID_LEN (AST_MAX_EXTENSION)
886#define MAX_VM_CONTEXT_LEN (AST_MAX_CONTEXT)
888#define MAX_VM_MAILBOX_LEN (MAX_VM_MBOX_ID_LEN + MAX_VM_CONTEXT_LEN)
923 char imappassword[80];
925 char imapvmshareid[80];
940#define VMSTATE_MAX_MSG_ARRAY 256
965 unsigned msg_array_max;
966 MAILSTREAM *mailstream;
976 unsigned int quota_limit;
977 unsigned int quota_usage;
983static char odbc_database[80] =
"asterisk";
984static char odbc_table[80] =
"voicemessages";
985size_t odbc_table_len =
sizeof(odbc_table);
986#define COUNT(a, b) odbc_count_messages(a,b)
987#define LAST_MSG_INDEX(a) odbc_last_message_index(a)
988#define RETRIEVE(a,b,c,d) odbc_retrieve_message(a,b)
989#define DISPOSE(a,b) odbc_remove_files(a,b)
990#define STORE(a,b,c,d,e,f,g,h,i,j,k) odbc_store_message(a,b,c,d)
991#define EXISTS(a,b,c,d) (odbc_message_exists(a,b))
992#define RENAME(a,b,c,d,e,f,g,h) (odbc_rename_message(a,b,c,d,e,f))
993#define COPY(a,b,c,d,e,f,g,h) (odbc_copy_message(a,b,c,d,e,f))
994#define DELETE(a,b,c,d) (odbc_delete_message(a,b))
995#define UPDATE_MSG_ID(a, b, c, d, e, f) (odbc_update_msg_id((a), (b), (c)))
998#define DISPOSE(a,b) (imap_remove_file(a,b))
999#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))
1000#define RETRIEVE(a,b,c,d) imap_retrieve_file(a,b,c,d)
1001#define EXISTS(a,b,c,d) (ast_fileexists(c,NULL,d) > 0)
1002#define RENAME(a,b,c,d,e,f,g,h) (rename_file(g,h));
1003#define COPY(a,b,c,d,e,f,g,h) (copy_file(g,h));
1004#define DELETE(a,b,c,d) (vm_imap_delete(a,b,d))
1005#define UPDATE_MSG_ID(a, b, c, d, e, f) (vm_imap_update_msg_id((a), (b), (c), (d), (e), (f)))
1007#define COUNT(a, b) count_messages(a,b)
1008#define LAST_MSG_INDEX(a) last_message_index(a)
1009#define RETRIEVE(a,b,c,d)
1011#define STORE(a,b,c,d,e,f,g,h,i,j,k)
1012#define EXISTS(a,b,c,d) (ast_fileexists(c,NULL,d) > 0)
1013#define RENAME(a,b,c,d,e,f,g,h) (rename_file(g,h));
1014#define COPY(a,b,c,d,e,f,g,h) (copy_plain_file(g,h));
1015#define DELETE(a,b,c,d) (vm_delete(c))
1016#define UPDATE_MSG_ID(a, b, c, d, e, f)
1027#define PWDCHANGE_INTERNAL (1 << 1)
1028#define PWDCHANGE_EXTERNAL (1 << 2)
1032#define tdesc "Comedian Mail (Voicemail System) with ODBC Storage"
1035# define tdesc "Comedian Mail (Voicemail System) with IMAP Storage"
1037# define tdesc "Comedian Mail (Voicemail System)"
1085#define DEFAULT_POLL_FREQ 30
1108#define MAPPING_BUCKETS 511
1166static unsigned char adsifdn[4] =
"\x00\x00\x00\x0F";
1167static unsigned char adsisec[4] =
"\x9B\xDB\xF7\xAC";
1178 char *fmt,
int outsidecaller,
struct ast_vm_user *vmu,
int *duration,
int *sound_duration,
const char *unlockdir,
1179 signed char record_gain,
struct vm_state *vms,
char *
flag,
const char *msg_id,
int forwardintro);
1183static 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);
1215static 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);
1216static 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);
1220#ifdef TEST_FRAMEWORK
1221static int vm_test_destroy_user(
const char *
context,
const char *
mailbox);
1222static int vm_test_create_user(
const char *
context,
const char *
mailbox);
1270 if (strcmp(i->
mailbox, j->mailbox)) {
1278 int context_len = strlen(
context) + 1;
1279 int mailbox_len = strlen(
mailbox) + 1;
1294 if (!(i =
ao2_alloc(
sizeof(*i) + context_len + mailbox_len,
NULL))) {
1308#if !(defined(ODBC_STORAGE) || defined(IMAP_STORAGE))
1326 if (bufptr ==
buf + buflen - 1) {
1353static size_t get_msg_path_len(
const char *dir)
1367#define MAX_SOUND_EXTEN_LEN 12
1380static size_t get_msg_path_ext_len(
const char *dir)
1386 return strlen(dir) + 1 +
MSGFILE_LEN + MAX_SOUND_EXTEN_LEN + 1;
1410#define MAKE_FILE_PTRA(dir, msgnum) \
1412 size_t __len = get_msg_path_len(dir); \
1415 __var = ast_strdupa(dir); \
1417 __var = ast_alloca(__len); \
1418 snprintf(__var, __len, "%s/msg%04d", dir, msgnum); \
1452#define MAKE_FILE_EXT_PTRA(dir, msgnum, ext) \
1454 size_t __len = get_msg_path_ext_len(dir); \
1455 char *__var = ast_alloca(__len); \
1457 snprintf(__var, __len, "%s.%s", dir, ext); \
1459 snprintf(__var, __len, "%s/msg%04d.%s", dir, msgnum, ext); \
1510 ast_copy_string(vmu->imapfolder, imapfolder,
sizeof(vmu->imapfolder));
1511 ast_copy_string(vmu->imapserver, imapserver,
sizeof(vmu->imapserver));
1528 if (!strcasecmp(
var,
"attach")) {
1530 }
else if (!strcasecmp(
var,
"attachfmt")) {
1532 }
else if (!strcasecmp(
var,
"attachextrecs")) {
1534 }
else if (!strcasecmp(
var,
"serveremail")) {
1536 }
else if (!strcasecmp(
var,
"fromstring")) {
1538 }
else if (!strcasecmp(
var,
"emailbody")) {
1541 }
else if (!strcasecmp(
var,
"emailsubject")) {
1544 }
else if (!strcasecmp(
var,
"language")) {
1546 }
else if (!strcasecmp(
var,
"tz")) {
1548 }
else if (!strcasecmp(
var,
"locale")) {
1551 }
else if (!strcasecmp(
var,
"imapuser")) {
1553 vmu->imapversion = imapversion;
1554 }
else if (!strcasecmp(
var,
"imapserver")) {
1556 vmu->imapversion = imapversion;
1557 }
else if (!strcasecmp(
var,
"imapport")) {
1559 vmu->imapversion = imapversion;
1560 }
else if (!strcasecmp(
var,
"imapflags")) {
1562 vmu->imapversion = imapversion;
1563 }
else if (!strcasecmp(
var,
"imappassword") || !strcasecmp(
var,
"imapsecret")) {
1565 vmu->imapversion = imapversion;
1566 }
else if (!strcasecmp(
var,
"imapfolder")) {
1568 vmu->imapversion = imapversion;
1569 }
else if (!strcasecmp(
var,
"imapvmshareid")) {
1571 vmu->imapversion = imapversion;
1573 }
else if (!strcasecmp(
var,
"delete") || !strcasecmp(
var,
"deletevoicemail")) {
1575 }
else if (!strcasecmp(
var,
"saycid")){
1577 }
else if (!strcasecmp(
var,
"sendvoicemail")){
1579 }
else if (!strcasecmp(
var,
"review")){
1581 }
else if (!strcasecmp(
var,
"leaveurgent")){
1583 }
else if (!strcasecmp(
var,
"tempgreetwarn")){
1585 }
else if (!strcasecmp(
var,
"messagewrap")){
1587 }
else if (!strcasecmp(
var,
"operator")) {
1589 }
else if (!strcasecmp(
var,
"envelope")){
1591 }
else if (!strcasecmp(
var,
"moveheard")){
1593 }
else if (!strcasecmp(
var,
"sayduration")){
1595 }
else if (!strcasecmp(
var,
"saydurationm")){
1596 if (sscanf(
value,
"%30d", &x) == 1) {
1601 }
else if (!strcasecmp(
var,
"forcename")){
1603 }
else if (!strcasecmp(
var,
"forcegreetings")){
1605 }
else if (!strcasecmp(
var,
"callback")) {
1607 }
else if (!strcasecmp(
var,
"dialout")) {
1609 }
else if (!strcasecmp(
var,
"exitcontext")) {
1611 }
else if (!strcasecmp(
var,
"minsecs")) {
1612 if (sscanf(
value,
"%30d", &x) == 1 && x >= 0) {
1618 }
else if (!strcasecmp(
var,
"maxmessage") || !strcasecmp(
var,
"maxsecs")) {
1626 if (!strcasecmp(
var,
"maxmessage"))
1627 ast_log(
AST_LOG_WARNING,
"Option 'maxmessage' has been deprecated in favor of 'maxsecs'. Please make that change in your voicemail config.\n");
1628 }
else if (!strcasecmp(
var,
"maxmsg")) {
1638 }
else if (!strcasecmp(
var,
"nextaftercmd")) {
1640 }
else if (!strcasecmp(
var,
"backupdeleted")) {
1641 if (sscanf(
value,
"%30d", &x) == 1)
1655 }
else if (!strcasecmp(
var,
"volgain")) {
1657 }
else if (!strcasecmp(
var,
"passwordlocation")) {
1658 if (!strcasecmp(
value,
"spooldir")) {
1663 }
else if (!strcasecmp(
var,
"options")) {
1670 int fds[2], pid = 0;
1675 snprintf(
buf,
len,
"FAILURE: Pipe failed: %s", strerror(
errno));
1684 snprintf(
buf,
len,
"FAILURE: Fork failed");
1688 if (read(fds[0],
buf,
len) < 0) {
1700 dup2(fds[1], STDOUT_FILENO);
1706 execv(arg.v[0], arg.v);
1707 printf(
"FAILURE: %s", strerror(
errno));
1730 char cmd[255],
buf[255];
1732 ast_debug(1,
"Verify password policies for %s\n", password);
1737 if (!strncasecmp(
buf,
"VALID", 5)) {
1740 }
else if (!strncasecmp(
buf,
"FAILURE", 7)) {
1765 if (!strcmp(vmu->
password, password)) {
1770 if (strlen(password) > 10) {
1790 while ((s =
strsep(&stringp,
"|"))) {
1806 if (!strcasecmp(
var->name,
"vmsecret")) {
1808 }
else if (!strcasecmp(
var->name,
"secret") || !strcasecmp(
var->name,
"password")) {
1812 "\n\tmust be reset in voicemail.conf.\n",
retval->mailbox);
1817 }
else if (!strcasecmp(
var->name,
"uniqueid")) {
1819 }
else if (!strcasecmp(
var->name,
"pager")) {
1821 }
else if (!strcasecmp(
var->name,
"email")) {
1824 }
else if (!strcasecmp(
var->name,
"fullname")) {
1826 }
else if (!strcasecmp(
var->name,
"context")) {
1828 }
else if (!strcasecmp(
var->name,
"emailsubject")) {
1831 }
else if (!strcasecmp(
var->name,
"emailbody")) {
1835 }
else if (!strcasecmp(
var->name,
"imapuser")) {
1837 retval->imapversion = imapversion;
1838 }
else if (!strcasecmp(
var->name,
"imapserver")) {
1840 retval->imapversion = imapversion;
1841 }
else if (!strcasecmp(
var->name,
"imapport")) {
1843 retval->imapversion = imapversion;
1844 }
else if (!strcasecmp(
var->name,
"imapflags")) {
1846 retval->imapversion = imapversion;
1847 }
else if (!strcasecmp(
var->name,
"imappassword") || !strcasecmp(
var->name,
"imapsecret")) {
1849 retval->imapversion = imapversion;
1850 }
else if (!strcasecmp(
var->name,
"imapfolder")) {
1852 retval->imapversion = imapversion;
1853 }
else if (!strcasecmp(
var->name,
"imapvmshareid")) {
1855 retval->imapversion = imapversion;
1874 for (i = 0; i < strlen(key); ++i) {
1946 if (cur->imapversion != imapversion) {
1957 if ((vmu = (ivm ? ivm :
ast_calloc(1,
sizeof(*vmu))))) {
1984 char *search_mailbox =
NULL;
1985 char *search_context =
NULL;
1989 vmu =
find_user(ivm, search_mailbox, search_context);
2028 "NewPassword", newpass);
2055 char *category =
NULL;
2070 ast_verb(4,
"Writing voicemail password to file %s succeeded\n", secretfn);
2075 ast_log(
LOG_WARNING,
"Writing voicemail password to file %s failed, falling back to config file\n", secretfn);
2081 if (!strcasecmp(category, vmu->
context)) {
2091 sprintf(
new,
"%s", newpassword);
2094 sprintf(
new,
"%s%s", newpassword,
value);
2108 ast_test_suite_event_notify(
"PASSWORDCHANGED",
"Message: voicemail.conf updated with new password\r\nPasswordSource: voicemail.conf");
2125 ast_debug(4,
"users.conf: %s\n", category);
2126 if (!strcasecmp(category, vmu->
mailbox)) {
2127 char new[strlen(newpassword) + 1];
2129 ast_debug(3,
"looks like we need to make vmsecret!\n");
2135 sprintf(
new,
"%s", newpassword);
2137 ast_debug(4,
"failed to get category!\n");
2206static int make_file(
char *dest,
const int len,
const char *dir,
const int num)
2208 return snprintf(dest,
len,
"%s/msg%04d", dir, num);
2235 if (vmu &&
id == 0) {
2236 return vmu->imapfolder;
2294 int arraysize = (vmu->
maxmsg > count_msg ? vmu->
maxmsg : count_msg);
2307 if (arraysize > 0) {
2325static void vm_imap_delete(
char *
file,
int msgnum,
struct ast_vm_user *vmu)
2329 unsigned long messageNum;
2332 if (msgnum < 0 && !imapgreetings) {
2337 if (!(vms = get_vm_state_by_mailbox(vmu->
mailbox, vmu->
context, 1)) && !(vms = get_vm_state_by_mailbox(vmu->
mailbox, vmu->
context, 0))) {
2338 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);
2343 imap_delete_old_greeting(
file, vms);
2349 messageNum = vms->msgArray[msgnum];
2350 if (messageNum == 0) {
2351 ast_log(
LOG_WARNING,
"msgnum %d, mailbox message %lu is zero.\n", msgnum, messageNum);
2354 ast_debug(3,
"deleting msgnum %d, which is mailbox message %lu\n", msgnum, messageNum);
2356 snprintf (arg,
sizeof(arg),
"%lu", messageNum);
2358 mail_setflag (vms->mailstream, arg,
"\\DELETED");
2359 mail_expunge(vms->mailstream);
2363static 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)
2370 const char *duration_str;
2414 sscanf(duration_str,
"%30d", &duration);
2430 vm_imap_delete(dir, msgnum, vmu);
2436static int imap_retrieve_greeting(
const char *dir,
const int msgnum,
struct ast_vm_user *vmu)
2439 char *
file, *filename;
2449 if (msgnum > -1 || !imapgreetings) {
2456 ast_debug(1,
"Failed to procure file name from directory passed.\n");
2462 if (!(vms_p = get_vm_state_by_mailbox(vmu->
mailbox, vmu->
context, 1)) &&
2463 !(vms_p = get_vm_state_by_mailbox(vmu->
mailbox, vmu->
context, 0))) {
2468 if (!(vms_p = create_vm_state_from_user(vmu))) {
2475 *vms_p->introfn =
'\0';
2489 for (i = 0; i < vms_p->mailstream->nmsgs; i++) {
2490 mail_fetchstructure(vms_p->mailstream, i + 1, &body);
2492 if (body->nested.part && body->nested.part->next && body->nested.part->next->body.parameter->value) {
2493 char *attachment = body->nested.part->next->body.parameter->value;
2494 char copy[strlen(attachment) + 1];
2496 strcpy(
copy, attachment);
2499 filename =
strsep(&attachment,
".");
2500 if (!strcmp(filename,
file)) {
2502 vms_p->msgArray[vms_p->
curmsg] = i + 1;
2504 save_body(body, vms_p,
"2", attachment, 0);
2515 if (curr_mbox != -1) {
2517 if (init_mailstream(vms_p, curr_mbox) || !vms_p->mailstream) {
2526static int imap_retrieve_file(
const char *dir,
const int msgnum,
const char *
mailbox,
const char *
context)
2529 char *header_content;
2530 char *attachedfilefmt;
2534 FILE *text_file_ptr;
2545 if (imapgreetings) {
2546 res = imap_retrieve_greeting(dir, msgnum, vmu);
2557 if (!(vms = get_vm_state_by_mailbox(vmu->
mailbox, vmu->
context, 1)) && !(vms = get_vm_state_by_mailbox(vmu->
mailbox, vmu->
context, 0))) {
2572 if (curr_mbox < 0) {
2573 ast_debug(3,
"Mailbox folder curbox not set, defaulting to Inbox\n");
2576 init_mailstream(vms, curr_mbox);
2577 if (!vms->mailstream) {
2584 snprintf(vms->introfn,
sizeof(vms->introfn),
"%sintro", vms->
fn);
2592 ast_debug(3,
"Before mail_fetchheaders, curmsg is: %d, imap messages is %lu\n", msgnum, vms->msgArray[msgnum]);
2593 if (vms->msgArray[msgnum] == 0) {
2601 header_content = mail_fetchheader (vms->mailstream, vms->msgArray[msgnum]);
2605 ast_log(
LOG_ERROR,
"Could not fetch header for message number %ld\n", vms->msgArray[msgnum]);
2611 mail_fetchstructure(vms->mailstream, vms->msgArray[msgnum], &body);
2615 if (body->nested.part && body->nested.part->next && body->nested.part->next->body.parameter->value) {
2616 attachedfilefmt =
ast_strdupa(body->nested.part->next->body.parameter->value);
2625 strsep(&attachedfilefmt,
".");
2626 if (!attachedfilefmt) {
2627 ast_log(
LOG_ERROR,
"File format could not be obtained from IMAP message attachment\n");
2632 save_body(body, vms,
"2", attachedfilefmt, 0);
2633 if (save_body(body, vms,
"3", attachedfilefmt, 1)) {
2634 *vms->introfn =
'\0';
2638 snprintf(text_file,
sizeof(text_file),
"%s.%s", vms->
fn,
"txt");
2640 if (!(text_file_ptr = fopen(text_file,
"w"))) {
2645 fprintf(text_file_ptr,
"%s\n",
"[message]");
2647 if (get_header_by_tag(header_content,
"X-Asterisk-VM-Caller-ID-Name:",
buf,
sizeof(
buf))) {
2648 fprintf(text_file_ptr,
"callerid=\"%s\" ",
S_OR(
buf,
""));
2650 if (get_header_by_tag(header_content,
"X-Asterisk-VM-Caller-ID-Num:",
buf,
sizeof(
buf))) {
2651 fprintf(text_file_ptr,
"<%s>\n",
S_OR(
buf,
""));
2653 if (get_header_by_tag(header_content,
"X-Asterisk-VM-Context:",
buf,
sizeof(
buf))) {
2654 fprintf(text_file_ptr,
"context=%s\n",
S_OR(
buf,
""));
2656 if (get_header_by_tag(header_content,
"X-Asterisk-VM-Orig-time:",
buf,
sizeof(
buf))) {
2657 fprintf(text_file_ptr,
"origtime=%s\n",
S_OR(
buf,
""));
2659 if (get_header_by_tag(header_content,
"X-Asterisk-VM-Duration:",
buf,
sizeof(
buf))) {
2660 fprintf(text_file_ptr,
"duration=%s\n",
S_OR(
buf,
""));
2662 if (get_header_by_tag(header_content,
"X-Asterisk-VM-Category:",
buf,
sizeof(
buf))) {
2663 fprintf(text_file_ptr,
"category=%s\n",
S_OR(
buf,
""));
2665 if (get_header_by_tag(header_content,
"X-Asterisk-VM-Flag:",
buf,
sizeof(
buf))) {
2666 fprintf(text_file_ptr,
"flag=%s\n",
S_OR(
buf,
""));
2668 if (get_header_by_tag(header_content,
"X-Asterisk-VM-Message-ID:",
buf,
sizeof(
buf))) {
2669 fprintf(text_file_ptr,
"msg_id=%s\n",
S_OR(
buf,
""));
2671 fclose(text_file_ptr);
2678static int folder_int(
const char *folder)
2684 if (!strcasecmp(folder, imapfolder)) {
2686 }
else if (!strcasecmp(folder,
"Old")) {
2688 }
else if (!strcasecmp(folder,
"Work")) {
2690 }
else if (!strcasecmp(folder,
"Family")) {
2692 }
else if (!strcasecmp(folder,
"Friends")) {
2694 }
else if (!strcasecmp(folder,
"Cust1")) {
2696 }
else if (!strcasecmp(folder,
"Cust2")) {
2698 }
else if (!strcasecmp(folder,
"Cust3")) {
2700 }
else if (!strcasecmp(folder,
"Cust4")) {
2702 }
else if (!strcasecmp(folder,
"Cust5")) {
2704 }
else if (!strcasecmp(folder,
"Urgent")) {
2711static int __messagecount(
const char *
context,
const char *
mailbox,
const char *folder)
2719 int fold = folder_int(folder);
2732 memset(&vmus, 0,
sizeof(vmus));
2740 if (vmu->imapuser[0] ==
'\0') {
2748 if (vmu->imapuser[0] ==
'\0') {
2755 vms_p = get_vm_state_by_imapuser(vmu->imapuser, 1);
2760 ast_debug(3,
"Returning before search - user is logged in\n");
2772 vms_p = get_vm_state_by_imapuser(vmu->imapuser, 0);
2778 vms_p = create_vm_state_from_user(vmu);
2780 ret = init_mailstream(vms_p, fold);
2781 if (!vms_p->mailstream) {
2788 pgm = mail_newsearchpgm ();
2789 hdr = mail_newsearchheader (
"X-Asterisk-VM-Extension", (
char *)(!
ast_strlen_zero(vmu->imapvmshareid) ? vmu->imapvmshareid :
mailbox));
2790 hdr->next = mail_newsearchheader(
"X-Asterisk-VM-Context", (
char *)
S_OR(
context,
"default"));
2816 vms_p->vmArrayIndex = 0;
2817 mail_search_full (vms_p->mailstream,
NULL, pgm, NIL);
2818 if (fold == 0 && urgent == 0)
2822 if (fold == 0 && urgent == 1)
2825 mail_free_searchpgm(&pgm);
2829 return vms_p->vmArrayIndex;
2832 mail_ping(vms_p->mailstream);
2842 check_quota(vms, vmu->imapfolder);
2843 if (vms->quota_limit && vms->quota_usage >= vms->quota_limit) {
2844 ast_debug(1,
"*** QUOTA EXCEEDED!! %u >= %u\n", vms->quota_usage, vms->quota_limit);
2854 ast_log(
LOG_WARNING,
"Unable to leave message since we will exceed the maximum number of messages allowed (%u >= %u)\n", msgnum, vmu->
maxmsg);
2873static int messagecount(
const char *mailbox_id,
const char *folder)
2889 return count < 0 ? 0 : count;
2892static 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)
2900 char tmp[80] =
"/tmp/astmail-XXXXXX";
2906 char *imap_flags = NIL;
2915 if(!imapgreetings) {
2922 if (imap_check_limits(chan, vms, vmu, msgcount)) {
2928 ast_debug(3,
"Setting message flag \\\\FLAGGED.\n");
2929 imap_flags =
"\\FLAGGED";
2945 snprintf(introfn,
sizeof(introfn),
"%sintro",
fn);
2960 if (!strcmp(fmt,
"wav49"))
2962 ast_debug(3,
"Storing file '%s', format '%s'\n",
fn, fmt);
2975 if (msgnum < 0 && imapgreetings) {
2980 imap_delete_old_greeting(
fn, vms);
2986 fn, introfn, fmt, duration, 1, chan,
NULL, 1,
flag, msg_id);
2994 *(vmu->
email) =
'\0';
3003 ((
char *)
buf)[
len] =
'\0';
3005 ret = init_mailstream(vms, box);
3009 if(!mail_append_full(vms->mailstream,
mailbox, imap_flags, NIL, &
str))
3025 *(vmu->
email) =
'\0';
3044static int inboxcount2(
const char *mailbox_context,
int *urgentmsgs,
int *newmsgs,
int *oldmsgs)
3059 ast_debug(3,
"Mailbox is set to %s\n", mailbox_context);
3066 if (strchr(mailbox_context,
',')) {
3067 int tmpnew, tmpold, tmpurgent;
3070 while ((cur =
strsep(&mb,
", "))) {
3080 *urgentmsgs += tmpurgent;
3092 mailboxnc = (
char *) mailbox_context;
3101 if ((count = __messagecount(
context, mailboxnc, vmu->imapfolder)) < 0) {
3109 if ((count = __messagecount(
context, mailboxnc,
"Old")) < 0) {
3115 if ((count = __messagecount(
context, mailboxnc,
"Urgent")) < 0) {
3118 *urgentmsgs = count;
3138 if (strchr(tmp2,
',') || strchr(tmp2,
'&')) {
3139 while ((box =
strsep(&tmp2,
",&"))) {
3152 return __messagecount(
context,
tmp, folder) > 0 ? 1 : 0;
3174 char messagestring[10];
3175 if (msgnum >= recip->
maxmsg) {
3179 if (!(sendvms = get_vm_state_by_imapuser(vmu->imapuser, 0))) {
3183 if (!get_vm_state_by_imapuser(recip->imapuser, 0)) {
3187 snprintf(messagestring,
sizeof(messagestring),
"%ld", sendvms->msgArray[msgnum]);
3189 if ((mail_copy(sendvms->mailstream, messagestring, (
char *)
mbox(vmu, imbox)) == T)) {
3198static void imap_mailbox_name(
char *spec,
size_t len,
struct vm_state *vms,
int box,
int use_folder)
3201 size_t left =
sizeof(
tmp);
3234 snprintf(spec,
len,
"%s%s",
tmp, use_folder? vms->imapfolder:
"INBOX");
3236 snprintf(spec,
len,
"%s%s",
tmp, greetingfolder);
3240 snprintf(spec,
len,
"%s%s%c%s",
tmp, imapparentfolder, delimiter,
mbox(
NULL, box));
3247static int init_mailstream(
struct vm_state *vms,
int box)
3249 MAILSTREAM *stream = NIL;
3257 ast_debug(3,
"vm_state user is:%s\n", vms->imapuser);
3258 if (vms->mailstream == NIL || !vms->mailstream) {
3261 stream = vms->mailstream;
3266 if (delimiter ==
'\0') {
3268#ifdef USE_SYSTEM_IMAP
3269#include <imap/linkage.c>
3270#elif defined(USE_SYSTEM_CCLIENT)
3271#include <c-client/linkage.c>
3276 imap_mailbox_name(
tmp,
sizeof(
tmp), vms, 0, 1);
3279 stream = mail_open (stream,
tmp,
debug ? OP_DEBUG : NIL);
3282 if (stream == NIL) {
3286 get_mailbox_delimiter(vms, stream);
3288 for (cp = vms->imapfolder; *cp; cp++)
3293 imap_mailbox_name(
tmp,
sizeof(
tmp), vms, box, 1);
3294 ast_debug(3,
"Before mail_open, server: %s, box:%d\n",
tmp, box);
3297 vms->mailstream = mail_open (stream,
tmp,
debug ? OP_DEBUG : NIL);
3299 if (vms->mailstream && !mail_status(vms->mailstream,
tmp, SA_UIDNEXT)) {
3300 mail_create(vms->mailstream,
tmp);
3304 if (vms->mailstream == NIL) {
3324 ast_copy_string(vms->imapfolder, vmu->imapfolder,
sizeof(vms->imapfolder));
3325 ast_copy_string(vms->imapserver, vmu->imapserver,
sizeof(vms->imapserver));
3327 ast_copy_string(vms->imapflags, vmu->imapflags,
sizeof(vms->imapflags));
3328 vms->imapversion = vmu->imapversion;
3329 ast_debug(3,
"Before init_mailstream, user is %s\n", vmu->imapuser);
3331 if (init_mailstream(vms, box) || !vms->mailstream) {
3340 ast_debug(3,
"Mailbox name set to: %s, about to check quotas\n",
mbox(vmu, box));
3341 check_quota(vms, (
char *)
mbox(vmu, box));
3345 pgm = mail_newsearchpgm();
3348 hdr = mail_newsearchheader(
"X-Asterisk-VM-Extension", (!
ast_strlen_zero(vmu->imapvmshareid) ? vmu->imapvmshareid : vmu->
mailbox));
3349 hdr->next = mail_newsearchheader(
"X-Asterisk-VM-Context", vmu->
context);
3360 }
else if (box ==
NEW_FOLDER && urgent == 0) {
3370 ast_debug(3,
"Before mail_search_full, user is %s\n", vmu->imapuser);
3372 vms->vmArrayIndex = 0;
3373 mail_search_full (vms->mailstream,
NULL, pgm, NIL);
3374 vms->
lastmsg = vms->vmArrayIndex - 1;
3375 mail_free_searchpgm(&pgm);
3381 ast_log(
LOG_WARNING,
"The code expects the old messages to be checked first, fix the code.\n");
3392static void write_file(
char *filename,
char *buffer,
unsigned long len)
3396 if (!filename || !buffer) {
3400 if (!(output = fopen(filename,
"w"))) {
3405 if (fwrite(buffer,
len, 1, output) != 1) {
3406 if (ferror(output)) {
3413static void update_messages_by_imapuser(
const char *
user,
unsigned long number)
3415 struct vm_state *vms = get_vm_state_by_imapuser(
user, 1);
3417 if (!vms && !(vms = get_vm_state_by_imapuser(
user, 0))) {
3421 ast_debug(3,
"saving mailbox message number %lu as message %d. Interactive set to %d\n",
number, vms->vmArrayIndex, vms->interactive);
3424 if (vms->vmArrayIndex >= vms->msg_array_max) {
3425 long *new_mem =
ast_realloc(vms->msgArray, 2 * vms->msg_array_max *
sizeof(
long));
3429 vms->msgArray = new_mem;
3430 vms->msg_array_max *= 2;
3433 vms->msgArray[vms->vmArrayIndex++] =
number;
3436void mm_searched(MAILSTREAM *stream,
unsigned long number)
3446static struct ast_vm_user *find_user_realtime_imapuser(
const char *imapuser)
3471void mm_exists(MAILSTREAM * stream,
unsigned long number)
3480void mm_expunged(MAILSTREAM * stream,
unsigned long number)
3489void mm_flags(MAILSTREAM * stream,
unsigned long number)
3498void mm_notify(MAILSTREAM * stream,
char *
string,
long errflg)
3500 ast_debug(5,
"Entering NOTIFY callback, errflag is %ld, string is %s\n", errflg,
string);
3501 mm_log (
string, errflg);
3505void mm_list(MAILSTREAM * stream,
int delim,
char *
mailbox,
long attributes)
3507 if (delimiter ==
'\0') {
3512 if (attributes & LATT_NOINFERIORS)
3514 if (attributes & LATT_NOSELECT)
3516 if (attributes & LATT_MARKED)
3518 if (attributes & LATT_UNMARKED)
3523void mm_lsub(MAILSTREAM * stream,
int delim,
char *
mailbox,
long attributes)
3526 if (attributes & LATT_NOINFERIORS)
3528 if (attributes & LATT_NOSELECT)
3530 if (attributes & LATT_MARKED)
3532 if (attributes & LATT_UNMARKED)
3537void mm_status(MAILSTREAM * stream,
char *
mailbox, MAILSTATUS *
status)
3546 if (
status->flags & SA_MESSAGES) {
3549 if (
status->flags & SA_RECENT) {
3552 if (
status->flags & SA_UNSEEN) {
3555 if (
status->flags & SA_UIDVALIDITY) {
3558 if (
status->flags & SA_UIDNEXT) {
3567void mm_log(
char *
string,
long errflg)
3569 switch ((
short) errflg) {
3571 ast_debug(1,
"IMAP Info: %s\n",
string);
3584void mm_dlog(
char *
string)
3590void mm_login(NETMBX * mb,
char *
user,
char *pwd,
long trial)
3594 ast_debug(4,
"Entering callback mm_login\n");
3603 if (!strcasecmp(mb->user, vmu->imapuser)) {
3609 if ((vmu = find_user_realtime_imapuser(mb->user))) {
3618void mm_critical(MAILSTREAM * stream)
3623void mm_nocritical(MAILSTREAM * stream)
3628long mm_diskerror(MAILSTREAM * stream,
long errcode,
long serious)
3630 kill (getpid (), SIGSTOP);
3635void mm_fatal(
char *
string)
3641static void mm_parsequota(MAILSTREAM *stream,
unsigned char *msg, QUOTALIST *pquota)
3645 char buf[1024] =
"";
3646 unsigned long usage = 0, limit = 0;
3649 usage = pquota->usage;
3650 limit = pquota->limit;
3651 pquota = pquota->next;
3654 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)))) {
3661 vms->quota_usage =
usage;
3662 vms->quota_limit = limit;
3665static char *get_header_by_tag(
char *
header,
char *tag,
char *
buf,
size_t len)
3667 char *start, *eol_pnt;
3673 taglen = strlen(tag) + 1;
3684 if ((eol_pnt = strchr(
buf,
'\r')) || (eol_pnt = strchr(
buf,
'\n')))
3689static char *get_user_by_mailbox(
char *
mailbox,
char *
buf,
size_t len)
3691 char *start, *eol_pnt, *
quote;
3696 if (!(start = strstr(
mailbox,
"/user=")))
3702 if ((eol_pnt = strchr(
buf,
'/')) || (eol_pnt = strchr(
buf,
'}'))) {
3707 if ((eol_pnt = strchr(
quote + 1,
'"'))) {
3718 pthread_once(&ts_vmstate.once, ts_vmstate.key_init);
3719 if ((vms_p = pthread_getspecific(ts_vmstate.key)) && !strcmp(vms_p->imapuser, vmu->imapuser) && !strcmp(vms_p->
username, vmu->
mailbox)) {
3722 ast_debug(5,
"Adding new vmstate for %s\n", vmu->imapuser);
3724 if (!(vms_p =
ast_calloc(1,
sizeof(*vms_p))))
3726 ast_copy_string(vms_p->imapuser, vmu->imapuser,
sizeof(vms_p->imapuser));
3727 ast_copy_string(vms_p->imapfolder, vmu->imapfolder,
sizeof(vms_p->imapfolder));
3728 ast_copy_string(vms_p->imapserver, vmu->imapserver,
sizeof(vms_p->imapserver));
3729 ast_copy_string(vms_p->imapport, vmu->imapport,
sizeof(vms_p->imapport));
3730 ast_copy_string(vms_p->imapflags, vmu->imapflags,
sizeof(vms_p->imapflags));
3733 vms_p->mailstream = NIL;
3734 vms_p->imapversion = vmu->imapversion;
3735 ast_debug(5,
"Copied %s to %s\n", vmu->imapuser, vms_p->imapuser);
3739 init_vm_state(vms_p);
3740 vmstate_insert(vms_p);
3744static struct vm_state *get_vm_state_by_imapuser(
const char *
user,
int interactive)
3746 struct vmstate *vlist =
NULL;
3750 pthread_once(&ts_vmstate.once, ts_vmstate.key_init);
3751 if ((vms = pthread_getspecific(ts_vmstate.key)) && !strcmp(vms->imapuser,
user)) {
3762 if (vlist->vms->imapversion != imapversion) {
3766 if (!strcmp(vlist->vms->imapuser,
user) && (interactive == 2 || vlist->vms->interactive == interactive)) {
3778static struct vm_state *get_vm_state_by_mailbox(
const char *
mailbox,
const char *
context,
int interactive)
3781 struct vmstate *vlist =
NULL;
3782 const char *local_context =
S_OR(
context,
"default");
3786 pthread_once(&ts_vmstate.once, ts_vmstate.key_init);
3787 if ((vms = pthread_getspecific(ts_vmstate.key)) &&
3799 if (vlist->vms->imapversion != imapversion) {
3803 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);
3805 if (!strcmp(vlist->vms->username,
mailbox) && !strcmp(vlist->vms->context, local_context) && vlist->vms->interactive == interactive) {
3818static void vmstate_insert(
struct vm_state *vms)
3826 if (vms->interactive == 1) {
3832 vms->vmArrayIndex = altvms->vmArrayIndex;
3837 vms->persist_vms = altvms;
3839#ifdef REALLY_FAST_EVEN_IF_IT_MEANS_RESOURCE_LEAKS
3840 vms->mailstream = altvms->mailstream;
3842 vms->mailstream = NIL;
3853 ast_debug(3,
"Inserting vm_state for user:%s, mailbox %s\n", vms->imapuser, vms->
username);
3860static void vmstate_delete(
struct vm_state *vms)
3862 struct vmstate *vc =
NULL;
3867 if (vms->interactive == 1 && (altvms = vms->persist_vms)) {
3871 altvms->updated = 1;
3872 vms->mailstream = mail_close(vms->mailstream);
3878 ast_debug(3,
"Removing vm_state for user:%s, mailbox %s\n", vms->imapuser, vms->
username);
3882 if (vc->vms == vms) {
3893 vc->vms->msgArray =
NULL;
3894 vc->vms->msg_array_max = 0;
3902static void set_update(MAILSTREAM * stream)
3906 char buf[1024] =
"";
3908 if (!(
user = get_user_by_mailbox(
mailbox,
buf,
sizeof(
buf))) || !(vms = get_vm_state_by_imapuser(
user, 0))) {
3919static void init_vm_state(
struct vm_state *vms)
3922 vms->msgArray =
ast_calloc(vms->msg_array_max,
sizeof(
long));
3923 if (!vms->msgArray) {
3925 vms->msg_array_max = 0;
3927 vms->vmArrayIndex = 0;
3931static int save_body(BODY *body,
struct vm_state *vms,
char *section,
char *format,
int is_intro)
3935 char *
fn = is_intro ? vms->introfn : vms->
fn;
3936 unsigned long len = 0;
3937 unsigned long newlen = 0;
3940 if (!body || body == NIL)
3944 body_content = mail_fetchbody(vms->mailstream, vms->msgArray[vms->
curmsg], section, &
len);
3948 "Msgno %ld, section %s. The body's content size %ld is huge (max %ld). User:%s, mailbox %s\n",
3952 if (body_content != NIL &&
len) {
3953 snprintf(filename,
sizeof(filename),
"%s.%s",
fn, format);
3955 body_decoded = rfc822_base64((
unsigned char *) body_content,
len, &newlen);
3957 if (!newlen || !body_decoded) {
3960 write_file(filename, (
char *) body_decoded, newlen);
3962 ast_debug(5,
"Body of message is NULL.\n");
3976static void get_mailbox_delimiter(
struct vm_state *vms, MAILSTREAM *stream) {
3978 snprintf(
tmp,
sizeof(
tmp),
"{%s}",
S_OR(vms->imapserver, imapserver));
3979 mail_list(stream,
tmp,
"*");
3991 mail_parameters(
NULL, SET_QUOTA, (
void *) mm_parsequota);
3993 if (vms && vms->mailstream !=
NULL) {
3994 imap_getquotaroot(vms->mailstream,
mailbox);
4017#define MSG_ID_LEN 256
4040#define MAKE_SQL_PTRA(__sql_fmt) \
4043 char *__sql = ast_alloca(strlen(__sql_fmt) + odbc_table_len); \
4044 sprintf(__sql, __sql_fmt, odbc_table); \
4058#define MAKE_SQL_PTRA2(__sql_fmt) \
4061 char *__sql = ast_alloca(strlen(__sql_fmt) + (odbc_table_len * 2)); \
4062 sprintf(__sql, __sql_fmt, odbc_table, odbc_table); \
4066struct generic_prepare_struct {
4074 struct generic_prepare_struct *gps = data;
4078 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->
con, &stmt);
4079 if (!SQL_SUCCEEDED(res)) {
4084 if (!SQL_SUCCEEDED(res)) {
4086 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
4089 for (i = 0; i < gps->argc; i++)
4090 SQLBindParameter(stmt, i + 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(gps->argv[i]), 0, gps->argv[i], 0,
NULL);
4095static void odbc_update_msg_id(
char *dir,
int msg_num,
char *msg_id)
4098 char *sql = MAKE_SQL_PTRA(
"UPDATE %s SET msg_id=? WHERE dir=? AND msgnum=?");
4100 char msg_num_str[20];
4101 char *argv[] = { msg_id, dir, msg_num_str };
4102 struct generic_prepare_struct gps = { .sql = sql, .argc = 3, .argv = argv };
4103 SCOPE_ENTER(3,
"dir: %s msg_num: %d msg_id: %s\n", dir, msg_num, msg_id);
4110 snprintf(msg_num_str,
sizeof(msg_num_str),
"%d", msg_num);
4115 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
4121#define AUDIO_ON_DISK_MAGIC "AUDMAGIC"
4122#define AUDIO_ON_DISK_MAGIC_LEN 8
4124static void odbc_update_set_audmagic(
char *dir,
int msg_num)
4127 char *sql = MAKE_SQL_PTRA(
"UPDATE %s SET recording=? WHERE dir=? AND msgnum=?");
4129 SQLLEN datalen = AUDIO_ON_DISK_MAGIC_LEN;
4130 SQLLEN indlen = datalen;
4132 char msg_num_str[20];
4133 SCOPE_ENTER(3,
"dir: %s msg_num: %d\n", dir, msg_num);
4140 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->
con, &stmt);
4141 if (!SQL_SUCCEEDED(res)) {
4146 snprintf(msg_num_str,
sizeof(msg_num_str),
"%d", msg_num);
4148 SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_BINARY, SQL_LONGVARBINARY,
4149 datalen, 0, (
void *) AUDIO_ON_DISK_MAGIC,
4152 SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR,
4153 strlen(dir), 0, (
void *) dir, 0,
NULL);
4155 SQLBindParameter(stmt, 3, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR,
4156 strlen(msg_num_str), 0, (
void *) msg_num_str, 0,
NULL);
4159 if (!SQL_SUCCEEDED(res)) {
4163 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
4170static int odbc_store_message(
const char *dir,
const char *mailboxuser,
const char *mailboxcontext,
int msgnum);
4186static int odbc_retrieve_message(
char *dir,
int msgnum)
4192 void *fdm = MAP_FAILED;
4193 SQLSMALLINT colcount = 0;
4195 char *sql = MAKE_SQL_PTRA(
"SELECT * FROM %s WHERE dir=? AND msgnum=?");
4200 SQLSMALLINT datatype;
4201 SQLSMALLINT decimaldigits;
4202 SQLSMALLINT nullable;
4207 char *fn = MAKE_FILE_PTRA(dir, msgnum);
4208 char *full_fn = MAKE_FILE_EXT_PTRA(dir, msgnum,
"txt");
4210 char *mailboxuser =
NULL;
4211 char *mailboxcontext =
NULL;
4213 char *argv[] = { dir, msgnums };
4214 struct generic_prepare_struct gps = { .sql = sql, .argc = 2, .argv = argv };
4216 int storage_conversion_to_disk = 0;
4217 int storage_conversion_to_odbc = 0;
4218 SCOPE_ENTER(3,
"dir: %s msgnum: %d msgtype: %s\n", dir, msgnum, msgnum < 0 ?
"Greeting" :
"Message");
4226 c = strchr(fmt,
'|');
4229 if (!strcasecmp(fmt,
"wav49"))
4232 snprintf(msgnums,
sizeof(msgnums),
"%d", msgnum);
4234 ast_trace(-1,
"Opening '%s' for writing\n", full_fn);
4235 if (!(f = fopen(full_fn,
"w+"))) {
4240 sprintf(full_fn,
"%s.%s", fn, fmt);
4248 res = SQLFetch(stmt);
4249 if (!SQL_SUCCEEDED(res)) {
4250 if (res != SQL_NO_DATA) {
4253 goto bail_with_handle;
4256 res = SQLNumResultCols(stmt, &colcount);
4257 if (!SQL_SUCCEEDED(res)) {
4259 goto bail_with_handle;
4262 fprintf(f,
"[message]\n");
4263 for (x = 0; x < colcount; x++) {
4266 collen =
sizeof(coltitle);
4267 res = SQLDescribeCol(stmt, x + 1, (
unsigned char *) coltitle,
sizeof(coltitle), &collen,
4268 &datatype, &colsize, &decimaldigits, &nullable);
4269 if (!SQL_SUCCEEDED(res)) {
4271 goto bail_with_handle;
4274 if (!strcasecmp(coltitle,
"recording")) {
4278 res = SQLGetData(stmt, x + 1, SQL_BINARY, rowdata, 0, &colsize2);
4280 ast_trace(-1,
"Audio size: %ld\n", colsize2);
4281 if (colsize2 == AUDIO_ON_DISK_MAGIC_LEN) {
4282 res = SQLGetData(stmt, x + 1, SQL_BINARY, rowdata, AUDIO_ON_DISK_MAGIC_LEN,
NULL);
4283 if (memcmp(rowdata, AUDIO_ON_DISK_MAGIC, AUDIO_ON_DISK_MAGIC_LEN) != 0) {
4285 rowdata[0], rowdata[1], rowdata[2], rowdata[3], rowdata[4], rowdata[5], rowdata[6],
4286 rowdata[7], full_fn);
4287 goto bail_with_handle;
4289 ast_trace(-1,
"Audio is stored on disk. No need to write '%s'\n", full_fn);
4291 storage_conversion_to_odbc = 1;
4297 ast_trace(-1,
"Opening '%s' for writing\n", full_fn);
4301 goto bail_with_handle;
4304 storage_conversion_to_disk = 1;
4307 lseek(fd, fdlen - 1, SEEK_SET);
4308 if (write(fd,
tmp, 1) != 1) {
4314 for (offset = 0; offset < colsize2; offset +=
CHUNKSIZE) {
4315 if ((fdm = mmap(
NULL,
CHUNKSIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset)) == MAP_FAILED) {
4317 goto bail_with_handle;
4319 res = SQLGetData(stmt, x + 1, SQL_BINARY, fdm,
CHUNKSIZE,
NULL);
4321 if (!SQL_SUCCEEDED(res)) {
4324 goto bail_with_handle;
4327 if (truncate(full_fn, fdlen) < 0) {
4330 ast_trace(-1,
"Wrote %d bytes to '%s'\n", (
int)fdlen, full_fn);
4332 res = SQLGetData(stmt, x + 1, SQL_CHAR, rowdata,
sizeof(rowdata),
NULL);
4333 if (res == SQL_NULL_DATA && !strcasecmp(coltitle,
"msg_id")) {
4339 ast_trace(-1,
"msg_id was NULL. Generating new one: %s\n", msg_id);
4340 snprintf(rowdata,
sizeof(rowdata),
"%s", msg_id);
4341 }
else if (!strcasecmp(coltitle,
"mailboxuser")) {
4343 }
else if (!strcasecmp(coltitle,
"mailboxcontext")) {
4345 }
else if (res == SQL_NULL_DATA && !strcasecmp(coltitle,
"category")) {
4347 ast_trace(-1,
"Ignoring null category column in ODBC voicemail retrieve_file.\n");
4349 }
else if (!SQL_SUCCEEDED(res)) {
4351 goto bail_with_handle;
4353 if (strcasecmp(coltitle,
"msgnum") && strcasecmp(coltitle,
"dir")) {
4354 fprintf(f,
"%s=%s\n", coltitle, rowdata);
4360 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
4374 odbc_update_msg_id(dir, msgnum, msg_id);
4377 if (SQL_SUCCEEDED(res)) {
4378 if (storage_conversion_to_disk) {
4384 SCOPE_CALL(-1, odbc_update_set_audmagic, dir, msgnum);
4386 if (storage_conversion_to_odbc) {
4393 SCOPE_CALL(-1, odbc_store_message, dir, mailboxuser, mailboxcontext, msgnum);
4409static int odbc_last_message_index(
char *dir)
4414 char *sql = MAKE_SQL_PTRA(
"SELECT msgnum FROM %s WHERE dir=? order by msgnum desc");
4416 char *argv[] = { dir };
4417 struct generic_prepare_struct gps = { .sql = sql, .argc = 1, .argv = argv };
4432 res = SQLFetch(stmt);
4433 if (!SQL_SUCCEEDED(res)) {
4434 if (res == SQL_NO_DATA) {
4435 ast_trace(-1,
"Directory '%s' has no messages and therefore no index was retrieved.\n", dir);
4439 goto bail_with_handle;
4442 res = SQLGetData(stmt, 1, SQL_CHAR, rowdata,
sizeof(rowdata),
NULL);
4443 if (!SQL_SUCCEEDED(res)) {
4445 goto bail_with_handle;
4448 if (sscanf(rowdata,
"%30d", &x) != 1) {
4453 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
4470static int odbc_message_exists(
char *dir,
int msgnum)
4475 char *sql = MAKE_SQL_PTRA(
"SELECT COUNT(*) FROM %s WHERE dir=? AND msgnum=?");
4478 char *argv[] = { dir, msgnums };
4479 struct generic_prepare_struct gps = { .sql = sql, .argc = 2, .argv = argv };
4481 SCOPE_ENTER(3,
"dir: %s msgnum: %d\n", dir, msgnum);
4488 snprintf(msgnums,
sizeof(msgnums),
"%d", msgnum);
4495 res = SQLFetch(stmt);
4496 if (!SQL_SUCCEEDED(res)) {
4498 goto bail_with_handle;
4501 res = SQLGetData(stmt, 1, SQL_CHAR, rowdata,
sizeof(rowdata),
NULL);
4502 if (!SQL_SUCCEEDED(res)) {
4504 goto bail_with_handle;
4507 if (sscanf(rowdata,
"%30d", &x) != 1) {
4512 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
4528static int odbc_count_messages(
struct ast_vm_user *vmu,
char *dir)
4533 char *sql = MAKE_SQL_PTRA(
"SELECT COUNT(*) FROM %s WHERE dir=?");
4535 char *argv[] = { dir };
4536 struct generic_prepare_struct gps = { .sql = sql, .argc = 1, .argv = argv };
4551 res = SQLFetch(stmt);
4552 if (!SQL_SUCCEEDED(res)) {
4554 goto bail_with_handle;
4557 res = SQLGetData(stmt, 1, SQL_CHAR, rowdata,
sizeof(rowdata),
NULL);
4558 if (!SQL_SUCCEEDED(res)) {
4560 goto bail_with_handle;
4563 if (sscanf(rowdata,
"%30d", &x) != 1) {
4568 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
4583#define DELETE_SQL_FMT "DELETE FROM %s WHERE dir=? AND msgnum=?"
4584static void odbc_delete_message(
const char *sdir,
int smsg)
4587 char *sql = MAKE_SQL_PTRA(DELETE_SQL_FMT);
4589 char *argv[] = {
NULL, msgnums };
4590 struct generic_prepare_struct gps = { .sql = sql, .argc = 2, .argv = argv };
4592 SCOPE_ENTER(3,
"sdir: %s smsg: %d\n", sdir, smsg);
4601 snprintf(msgnums,
sizeof(msgnums),
"%d", smsg);
4606 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
4611 char *src_fn = MAKE_FILE_PTRA(sdir, smsg);
4612 ast_trace(-1,
"Audio stored on disk. Deleting '%s'\n", src_fn);
4630#define COPY_SQL_FMT "INSERT INTO %s (dir, msgnum, msg_id, context, callerid, origtime, " \
4631 "duration, recording, flag, mailboxuser, mailboxcontext) " \
4632 "SELECT ?,?,msg_id,context,callerid,origtime,duration,recording,flag,?,? " \
4633 "FROM %s WHERE dir=? AND msgnum=?"
4634static void odbc_copy_message(
char *sdir,
int smsg,
char *ddir,
int dmsg,
char *dmailboxuser,
char *dmailboxcontext)
4637 char *sql = MAKE_SQL_PTRA2(COPY_SQL_FMT);
4641 char *argv[] = { ddir, msgnumd, dmailboxuser, dmailboxcontext, sdir, msgnums };
4642 struct generic_prepare_struct gps = { .sql = sql, .argc = 6, .argv = argv };
4643 SCOPE_ENTER(3,
"sdir: %s smsg: %d duser: %s dcontext: %s ddir: %s dmsg: %d\n",
4644 sdir, smsg, dmailboxuser, dmailboxcontext, ddir, dmsg);
4646 SCOPE_CALL(-1, odbc_delete_message, ddir, dmsg);
4653 snprintf(msgnums,
sizeof(msgnums),
"%d", smsg);
4654 snprintf(msgnumd,
sizeof(msgnumd),
"%d", dmsg);
4658 ast_log(
AST_LOG_WARNING,
"SQL Execute error!\n[%s] (You probably don't have MySQL 4.1 or later installed)\n\n", sql);
4660 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
4664 char *src_fn = MAKE_FILE_PTRA(sdir, smsg);
4665 char *dst_fn = MAKE_FILE_PTRA(ddir, dmsg);
4667 ast_trace(-1,
"Audio stored on disk. Copying '%s' to '%s'\n", src_fn, dst_fn);
4677 const char *msgnums;
4682 const char *callerid;
4683 const char *origtime;
4684 const char *duration;
4685 const char *mailboxuser;
4686 const char *mailboxcontext;
4687 const char *category;
4692#define STORE_SQL_FMT_CAT "INSERT INTO %s (dir, msgnum, recording, context, callerid, " \
4693 "origtime, duration, mailboxuser, mailboxcontext, flag, msg_id, category) " \
4694 "VALUES (?,?,?,?,?,?,?,?,?,?,?,?)"
4695#define STORE_SQL_FMT "INSERT INTO %s (dir, msgnum, recording, context, callerid, "\
4696 "origtime, duration, mailboxuser, mailboxcontext, flag, msg_id) "\
4697 "VALUES (?,?,?,?,?,?,?,?,?,?,?)"
4699static SQLHSTMT odbc_insert_data_cb(
struct odbc_obj *obj,
void *vdata)
4701 struct insert_data *data = vdata;
4706 SCOPE_ENTER(3,
"dir: %s msgnums: %s msg_id: %s\n", data->dir, data->msgnums,
4709 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->
con, &stmt);
4710 if (!SQL_SUCCEEDED(res)) {
4715 delete_sql = MAKE_SQL_PTRA(DELETE_SQL_FMT);
4716 SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->dir), 0, (
void *) data->dir, 0,
NULL);
4717 SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->msgnums), 0, (
void *) data->msgnums, 0,
NULL);
4719 if (!SQL_SUCCEEDED(res)) {
4720 ast_trace(-1,
"There wasn't an existing row. Good.\n");
4722 ast_trace(-1,
"There WAS an existing row. This is OK if we're replacing a message.\n");
4724 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
4727 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->
con, &stmt);
4728 if (!SQL_SUCCEEDED(res)) {
4732 SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->dir), 0, (
void *) data->dir, 0,
NULL);
4733 SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->msgnums), 0, (
void *) data->msgnums, 0,
NULL);
4734 SQLBindParameter(stmt, 3, SQL_PARAM_INPUT, SQL_C_BINARY, SQL_LONGVARBINARY, data->datalen, 0, (
void *) data->data, data->datalen, &data->indlen);
4735 SQLBindParameter(stmt, 4, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->context), 0, (
void *) data->context, 0,
NULL);
4736 SQLBindParameter(stmt, 5, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->callerid), 0, (
void *) data->callerid, 0,
NULL);
4737 SQLBindParameter(stmt, 6, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->origtime), 0, (
void *) data->origtime, 0,
NULL);
4738 SQLBindParameter(stmt, 7, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->duration), 0, (
void *) data->duration, 0,
NULL);
4739 SQLBindParameter(stmt, 8, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->mailboxuser), 0, (
void *) data->mailboxuser, 0,
NULL);
4740 SQLBindParameter(stmt, 9, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->mailboxcontext), 0, (
void *) data->mailboxcontext, 0,
NULL);
4741 SQLBindParameter(stmt, 10, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->flag), 0, (
void *) data->flag, 0,
NULL);
4742 SQLBindParameter(stmt, 11, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->msg_id), 0, (
void *) data->msg_id, 0,
NULL);
4744 insert_sql = MAKE_SQL_PTRA(STORE_SQL_FMT_CAT);
4745 SQLBindParameter(stmt, 12, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->category), 0, (
void *) data->category, 0,
NULL);
4747 insert_sql = MAKE_SQL_PTRA(STORE_SQL_FMT);
4750 if (!SQL_SUCCEEDED(res)) {
4753 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
4773static int odbc_store_message(
const char *dir,
const char *mailboxuser,
const char *mailboxcontext,
int msgnum)
4777 void *fdm = MAP_FAILED;
4781 char *fn = MAKE_FILE_PTRA(dir, msgnum);
4782 char *full_fn = MAKE_FILE_EXT_PTRA(dir, msgnum,
"txt");
4787 struct insert_data idata = { .msgnums = msgnums, .dir = dir, .mailboxuser = mailboxuser, .mailboxcontext = mailboxcontext,
4788 .context =
"", .callerid =
"", .origtime =
"", .duration =
"", .category =
"", .flag =
"", .msg_id =
"" };
4790 SCOPE_ENTER(3,
"dir: %s user: %s context: %s msgnum: %d msgtype: %s\n",
4791 dir, mailboxuser, mailboxcontext, msgnum, msgnum < 0 ?
"Greeting" :
"Message");
4800 c = strchr(fmt,
'|');
4803 if (!strcasecmp(fmt,
"wav49"))
4807 snprintf(msgnums,
sizeof(msgnums),
"%d", msgnum);
4810 ast_trace(-1,
"Opening '%s'\n", full_fn);
4814 ast_trace(-1,
"No information file found for '%s'. This is a greeting so this is OK.\n", full_fn);
4822 sprintf(full_fn,
"%s.%s", fn, fmt);
4824 ast_trace(-1,
"Audio stored on disk. No need to open '%s'\n", full_fn);
4826 ast_trace(-1,
"Opening '%s'\n", full_fn);
4827 fd = open(full_fn, O_RDWR);
4836 ast_trace(-1,
"Using information file '%s'\n", fn);
4841 idata.callerid =
"";
4844 idata.origtime =
"";
4847 idata.duration =
"";
4850 idata.category =
"";
4861 ast_trace(-1,
"Audio stored on disk. Not reading sound file '%s' but setting magic number.\n", full_fn);
4862 idata.data = AUDIO_ON_DISK_MAGIC;
4863 idata.datalen = idata.indlen = AUDIO_ON_DISK_MAGIC_LEN;
4865 ast_trace(-1,
"Reading sound file '%s'\n", full_fn);
4866 fdlen = lseek(fd, 0, SEEK_END);
4867 if (fdlen < 0 || lseek(fd, 0, SEEK_SET) < 0) {
4872 fdm = mmap(
NULL, fdlen, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
4873 if (fdm == MAP_FAILED) {
4879 idata.datalen = idata.indlen = fdlen;
4883 idata.origtime =
"0";
4887 idata.duration =
"0";
4891 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
4901 if (fdm != MAP_FAILED)
4908#undef STORE_SQL_FMT_CAT
4923static void odbc_rename_message(
char *sdir,
int smsg,
char *mailboxuser,
char *mailboxcontext,
char *ddir,
int dmsg)
4926 char *sql = MAKE_SQL_PTRA(
"UPDATE %s SET dir=?, msgnum=? WHERE mailboxuser=? AND mailboxcontext=? AND dir=? AND msgnum=?");
4930 char *argv[] = { ddir, msgnumd, mailboxuser, mailboxcontext, sdir, msgnums };
4931 struct generic_prepare_struct gps = { .sql = sql, .argc = 6, .argv = argv };
4932 SCOPE_ENTER(3,
"sdir: %s smsg: %d user: %s context: %s ddir: %s dmsg: %d\n", sdir, smsg,
4933 mailboxuser, mailboxcontext, ddir, dmsg);
4935 SCOPE_CALL(-1, odbc_delete_message, ddir, dmsg);
4942 snprintf(msgnums,
sizeof(msgnums),
"%d", smsg);
4943 snprintf(msgnumd,
sizeof(msgnumd),
"%d", dmsg);
4949 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
4953 char *src_fn = MAKE_FILE_PTRA(sdir, smsg);
4954 char *dst_fn = MAKE_FILE_PTRA(ddir, dmsg);
4956 ast_trace(-1,
"Recordings stored on disk. Renaming '%s' to '%s'\n", src_fn, dst_fn);
4974static int odbc_remove_files(
char *dir,
int msgnum)
4976 char *fn = MAKE_FILE_PTRA(dir, msgnum);
4977 char *full_fn = MAKE_FILE_EXT_PTRA(dir, msgnum,
"txt");
4978 SCOPE_ENTER(3,
"dir: %s msgnum: %d\n", dir, msgnum);
4981 ast_trace(-1,
"Audio stored on disk. Keeping '%s' sound files\n", fn);
4983 ast_trace(-1,
"Audio stored in ODBC. Removing '%s' sound files\n", fn);
4988 ast_trace(-1,
"Removing '%s' information file\n", full_fn);
5008 struct dirent *vment =
NULL;
5013 if ((vmdir = opendir(dir))) {
5014 while ((vment = readdir(vmdir))) {
5015 if (strlen(vment->d_name) > 7 && !strncmp(vment->d_name + 7,
".txt", 4)) {
5038 snprintf(stxt,
sizeof(stxt),
"%s.txt", sfn);
5039 snprintf(dtxt,
sizeof(dtxt),
"%s.txt", dfn);
5061 struct dirent *msgdirent;
5070 if (!(msgdir = opendir(dir))) {
5074 while ((msgdirent = readdir(msgdir))) {
5078 ast_debug(4,
"%s map[%d] = %d, count = %d\n", dir, msgdirint, map[msgdirint], stopcount);
5084 stopcount -= map[x];
5103static int copy(
char *infile,
char *outfile)
5111#ifdef HARDLINK_WHEN_POSSIBLE
5113 if (!link(infile, outfile)) {
5118 if ((ifd = open(infile, O_RDONLY)) < 0) {
5143 wrlen = write(ofd,
buf,
len);
5172 const char *origmailbox =
"", *
context =
"", *exten =
"";
5173 const char *
priority =
"", *callerchan =
"", *callerid =
"", *origdate =
"";
5174 const char *origtime =
"", *category =
"", *duration =
"";
5177 snprintf(frompath2,
sizeof(frompath2),
"%s.txt", frompath);
5178 snprintf(topath2,
sizeof(topath2),
"%s.txt", topath);
5184 if (!strcasecmp(
tmp->name,
"origmailbox")) {
5185 origmailbox =
tmp->value;
5186 }
else if (!strcasecmp(
tmp->name,
"context")) {
5188 }
else if (!strcasecmp(
tmp->name,
"exten")) {
5190 }
else if (!strcasecmp(
tmp->name,
"priority")) {
5192 }
else if (!strcasecmp(
tmp->name,
"callerchan")) {
5193 callerchan =
tmp->value;
5194 }
else if (!strcasecmp(
tmp->name,
"callerid")) {
5195 callerid =
tmp->value;
5196 }
else if (!strcasecmp(
tmp->name,
"origdate")) {
5197 origdate =
tmp->value;
5198 }
else if (!strcasecmp(
tmp->name,
"origtime")) {
5199 origtime =
tmp->value;
5200 }
else if (!strcasecmp(
tmp->name,
"category")) {
5201 category =
tmp->value;
5202 }
else if (!strcasecmp(
tmp->name,
"duration")) {
5203 duration =
tmp->value;
5206 ast_store_realtime(
"voicemail_data",
"filename", topath,
"origmailbox", origmailbox,
"context",
context,
"exten", exten,
"priority",
priority,
"callerchan", callerchan,
"callerid", callerid,
"origdate", origdate,
"origtime", origtime,
"category", category,
"duration", duration,
SENTINEL);
5208 copy(frompath2, topath2);
5228 txtsize = (strlen(
file) + 5)*
sizeof(
char);
5236 snprintf(txt, txtsize,
"%s.txt",
file);
5244static 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)
5248 char fromdir[256], fromfile[256];
5250 const char *origcallerid, *origtime;
5251 char origcidname[80], origcidnum[80], origdate[80];
5258 snprintf(num,
sizeof(num),
"%d", msgnum);
5272 make_file(fromfile,
sizeof(fromfile), fromdir, msgnum - 1);
5273 if (strlen(fromfile) <
sizeof(fromfile) - 5) {
5274 strcat(fromfile,
".txt");
5277 ast_debug(1,
"Config load for message text file '%s' failed\n", fromfile);
5283 ast_callerid_split(origcallerid, origcidname,
sizeof(origcidname), origcidnum,
sizeof(origcidnum));
5288 if ((origtime =
ast_variable_retrieve(msg_cfg,
"message",
"origtime")) && sscanf(origtime,
"%30d", &inttime) == 1) {
5289 struct timeval tv = { inttime, };
5312 for (ptr = from; *ptr; ptr++) {
5313 if (*ptr ==
'"' || *ptr ==
'\\') {
5354 if (*
str > 126 || *
str < 32 || strchr(
"()<>@,:;/\"[]?.=", *
str)) {
5381 int first_section = 1;
5385 for (; *start; start++) {
5386 int need_encoding = 0;
5387 if (*start < 33 || *start > 126 || strchr(
"()<>@,:;/\"[]?.=_", *start)) {
5399 if (need_encoding && *start ==
' ') {
5401 }
else if (need_encoding) {
5440 const char *fromfolder,
5447 int attach_user_voicemail,
5449 const char *category,
5460 char enc_cidnum[256] =
"", enc_cidname[256] =
"";
5462 char *greeting_attachment;
5468 if (!str1 || !str2) {
5480 gethostname(host,
sizeof(host) - 1);
5482 if (strchr(srcemail,
'@')) {
5485 snprintf(who,
sizeof(who),
"%s@%s", srcemail, host);
5488 greeting_attachment = strrchr(
ast_strdupa(attach),
'/');
5489 if (greeting_attachment) {
5490 *greeting_attachment++ =
'\0';
5493 snprintf(dur,
sizeof(dur),
"%d:%02d", duration / 60, duration % 60);
5495 fprintf(p,
"Date: %s" ENDL, date);
5505 prep_email_sub_vars(ast, vmu, msgnum + 1,
context,
mailbox, fromfolder, enc_cidnum, enc_cidname, dur, date, category,
flag);
5527 fprintf(p,
"From: Asterisk PBX <%s>" ENDL, who);
5534 char *next = emailsbuf;
5552 fprintf(p,
"Subject: New greeting '%s' on %s." ENDL, greeting_attachment, date);
5557 prep_email_sub_vars(ast, vmu, msgnum + 1,
context,
mailbox, fromfolder, cidnum, cidname, dur, date, category,
flag);
5580 fprintf(p,
"Subject: New message %d in mailbox %s" ENDL, msgnum + 1,
mailbox);
5582 fprintf(p,
"Subject: New %s message %d in mailbox %s" ENDL,
flag, msgnum + 1,
mailbox);
5586 fprintf(p,
"Subject: [PBX]: New message %d in mailbox %s" ENDL, msgnum + 1,
mailbox);
5588 fprintf(p,
"Subject: [PBX]: New %s message %d in mailbox %s" ENDL,
flag, msgnum + 1,
mailbox);
5592 fprintf(p,
"Message-ID: <Asterisk-%d-%u-%s-%d@%s>" ENDL, msgnum + 1,
5596 fprintf(p,
"X-Asterisk-VM-Message-Num: %d" ENDL, msgnum + 1);
5599 fprintf(p,
"X-Asterisk-VM-Context: %s" ENDL,
context);
5603 fprintf(p,
"X-Asterisk-VM-Extension: %s" ENDL,
mailbox);
5606 fprintf(p,
"X-Asterisk-VM-Flag: %s" ENDL,
S_OR(
flag,
""));
5608 fprintf(p,
"X-Asterisk-VM-Caller-ID-Num: %s" ENDL, enc_cidnum);
5609 fprintf(p,
"X-Asterisk-VM-Caller-ID-Name: %s" ENDL, enc_cidname);
5610 fprintf(p,
"X-Asterisk-VM-Duration: %d" ENDL, duration);
5612 fprintf(p,
"X-Asterisk-VM-Category: %s" ENDL, category);
5614 fprintf(p,
"X-Asterisk-VM-Category: " ENDL);
5616 fprintf(p,
"X-Asterisk-VM-Message-Type: %s" ENDL, msgnum > -1 ?
"Message" : greeting_attachment);
5617 fprintf(p,
"X-Asterisk-VM-Orig-date: %s" ENDL, date);
5618 fprintf(p,
"X-Asterisk-VM-Orig-time: %ld" ENDL, (
long) time(
NULL));
5619 fprintf(p,
"X-Asterisk-VM-Message-ID: %s" ENDL, msg_id);
5622 fprintf(p,
"X-Asterisk-CallerID: %s" ENDL, enc_cidnum);
5625 fprintf(p,
"X-Asterisk-CallerIDName: %s" ENDL, enc_cidname);
5627 fprintf(p,
"MIME-Version: 1.0" ENDL);
5628 if (attach_user_voicemail) {
5630 snprintf(bound,
sizeof(bound),
"----voicemail_%d%s%d%u", msgnum + 1,
mailbox,
5631 (
int) getpid(), (
unsigned int)
ast_random());
5633 fprintf(p,
"Content-Type: multipart/mixed; boundary=\"%s\"" ENDL, bound);
5634 fprintf(p,
ENDL ENDL "This is a multi-part message in MIME format." ENDL ENDL);
5635 fprintf(p,
"--%s" ENDL, bound);
5637 fprintf(p,
"Content-Type: text/plain; charset=%s" ENDL "Content-Transfer-Encoding: 8bit" ENDL ENDL,
charset);
5639 fprintf(p,
"This message is to let you know that your greeting '%s' was changed on %s." ENDL
5640 "Please do not delete this message, lest your greeting vanish with it." ENDL ENDL,
5641 greeting_attachment, date);
5646 prep_email_sub_vars(ast, vmu, msgnum + 1,
context,
mailbox, fromfolder, cidnum, cidname, dur, date, category,
flag);
5654 if ((next = strchr(line,
'\n'))) {
5657 fprintf(p,
"%s" ENDL, line);
5674 char fromdir[256], fromfile[256], origdate[80] =
"", origcallerid[80] =
"";
5678 make_file(fromfile,
sizeof(fromfile), fromdir, msgnum);
5679 if (strlen(fromfile) <
sizeof(fromfile) - 5) {
5680 strcat(fromfile,
".txt");
5689 if ((v =
ast_variable_retrieve(msg_cfg,
"message",
"origtime")) && sscanf(v,
"%30d", &inttime) == 1) {
5690 struct timeval tv = { inttime, };
5695 fprintf(p,
"Dear %s:" ENDL ENDL "\tJust wanted to let you know you were just forwarded"
5696 " a %s long message (number %d)" ENDL "in mailbox %s from %s, on %s" ENDL
5697 "(originally sent by %s on %s)" ENDL "so you might want to check it when you get a"
5699 msgnum + 1,
mailbox, (cidname ? cidname : (cidnum ? cidnum :
"an unknown caller")),
5700 date, origcallerid, origdate);
5707 fprintf(p,
"Dear %s:" ENDL ENDL "\tJust wanted to let you know you were just left a "
5708 "%s long message (number %d)" ENDL "in mailbox %s from %s, on %s so you might" ENDL
5709 "want to check it when you get a chance. Thanks!" ENDL ENDL "\t\t\t\t--Asterisk"
5711 (cidname ? cidname : (cidnum ? cidnum :
"an unknown caller")), date);
5715 if (imap || attach_user_voicemail) {
5717 snprintf(filename,
sizeof(filename),
"msg%04d.%s", msgnum, format);
5718 ast_debug(5,
"creating second attachment filename %s\n", filename);
5720 snprintf(filename,
sizeof(filename),
"msgintro%04d.%s", msgnum, format);
5721 ast_debug(5,
"creating attachment filename %s\n", filename);
5724 snprintf(filename,
sizeof(filename),
"msg%04d.%s", msgnum, format);
5725 ast_debug(5,
"creating attachment filename %s, no second attachment.\n", filename);
5737 char *file_to_delete =
NULL, *dir_to_delete =
NULL;
5741 char altformat[80] =
"";
5745 char *mime_type = (!strcasecmp(format,
"ogg")) ?
"application/" :
"audio/x-";
5748 snprintf(fname,
sizeof(fname),
"%s.%s", attach, format);
5751 c = strchr(altformat,
'|');
5756 snprintf(altfname,
sizeof(altfname),
"%s.%s", attach, altformat);
5770 res = snprintf(sox_gain_tmpdir,
sizeof(sox_gain_tmpdir),
"%s/vm-gain-XXXXXX", tmpdir);
5771 if (res >=
sizeof(sox_gain_tmpdir)) {
5772 ast_log(
LOG_ERROR,
"Failed to create temporary directory path %s: Out of buffer space\n", tmpdir);
5776 if (
mkdtemp(sox_gain_tmpdir)) {
5780 ast_debug(3,
"sox_gain_tmpdir: %s\n", sox_gain_tmpdir);
5783 dir_to_delete = sox_gain_tmpdir;
5785 res = snprintf(fname,
sizeof(fname),
"%s/output.%s", sox_gain_tmpdir, format);
5786 if (res >=
sizeof(fname)) {
5787 ast_log(
LOG_ERROR,
"Failed to create filename buffer for %s/output.%s: Too long\n", sox_gain_tmpdir, format);
5792 res = snprintf(sox_gain_cmd,
sizeof(sox_gain_cmd),
"sox -v %.4f %s.%s %s",
5793 vmu->
volgain, attach, format, fname);
5795 if (!strcasecmp(format,
"wav")) {
5797 res = snprintf(sox_gain_cmd,
sizeof(sox_gain_cmd),
"sox -v %.4f %s.%s -e signed-integer -b 16 %s",
5798 vmu->
volgain, attach, altformat, fname);
5800 res = snprintf(sox_gain_cmd,
sizeof(sox_gain_cmd),
"sox %s.%s -e signed-integer -b 16 %s",
5801 attach, altformat, fname);
5805 res = snprintf(sox_gain_cmd,
sizeof(sox_gain_cmd),
"sox -v %.4f %s.%s %s",
5806 vmu->
volgain, attach, altformat, fname);
5808 res = snprintf(sox_gain_cmd,
sizeof(sox_gain_cmd),
"sox %s.%s %s",
5809 attach, altformat, fname);
5814 if (res >=
sizeof(sox_gain_cmd)) {
5815 ast_log(
LOG_ERROR,
"Failed to generate sox command, out of buffer space\n");
5822 file_to_delete = fname;
5825 ast_log(
LOG_WARNING,
"Sox failed to re-encode %s: %s (have you installed support for all sox file formats?)\n",
5827 soxstatus == 1 ?
"Problem with command line options" :
"An error occurred during file processing");
5835 if (!file_to_delete) {
5836 res = snprintf(fname,
sizeof(fname),
"%s.%s", attach, format);
5837 if (res >=
sizeof(fname)) {
5838 ast_log(
LOG_ERROR,
"Failed to create filename buffer for %s.%s: Too long\n", attach, format);
5843 fprintf(p,
"--%s" ENDL, bound);
5845 fprintf(p,
"Content-Type: %s%s; name=\"%s\"" ENDL, mime_type, format, filename);
5847 fprintf(p,
"Content-Type: %s%s; name=\"%s.%s\"" ENDL, mime_type, format, greeting_attachment, format);
5848 fprintf(p,
"Content-Transfer-Encoding: base64" ENDL);
5849 fprintf(p,
"Content-Description: Voicemail sound attachment." ENDL);
5851 fprintf(p,
"Content-Disposition: attachment; filename=\"%s\"" ENDL ENDL, filename);
5853 fprintf(p,
"Content-Disposition: attachment; filename=\"%s.%s\"" ENDL ENDL, greeting_attachment, format);
5858 if (file_to_delete) {
5859 unlink(file_to_delete);
5862 if (dir_to_delete) {
5863 rmdir(dir_to_delete);
5874 const char *fromfolder,
5881 int attach_user_voicemail,
5883 const char *category,
5888 char tmp[80] =
"/tmp/astmail-XXXXXX";
5902 if (!strcmp(format,
"wav49"))
5911 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);
5913 snprintf(tmp2,
sizeof(tmp2),
"( %s < %s ; rm -f %s ) &",
mailcmd,
tmp,
tmp);
5920static 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)
5922 char enc_cidnum[256], enc_cidname[256];
5927 char tmp[80] =
"/tmp/astmail-XXXXXX";
5933 if (!str1 || !str2) {
5952 gethostname(host,
sizeof(host)-1);
5953 if (strchr(srcemail,
'@')) {
5956 snprintf(who,
sizeof(who),
"%s@%s", srcemail, host);
5958 snprintf(dur,
sizeof(dur),
"%d:%02d", duration / 60, duration % 60);
5960 fprintf(p,
"Date: %s\n", date);
5969 prep_email_sub_vars(ast, vmu, msgnum + 1,
context,
mailbox, fromfolder, enc_cidnum, enc_cidname, dur, date, category,
flag);
5991 fprintf(p,
"From: Asterisk PBX <%s>" ENDL, who);
6013 prep_email_sub_vars(ast, vmu, msgnum + 1,
context,
mailbox, fromfolder, cidnum, cidname, dur, date, category,
flag);
6036 fprintf(p,
"Subject: New VM" ENDL);
6038 fprintf(p,
"Subject: New %s VM" ENDL,
flag);
6048 prep_email_sub_vars(ast, vmu, msgnum + 1,
context,
mailbox, fromfolder, cidnum, cidname, dur, date, category,
flag);
6056 fprintf(p,
"New %s long %s msg in box %s\n"
6057 "from %s, on %s", dur,
flag,
mailbox, (cidname ? cidname : (cidnum ? cidnum :
"unknown")), date);
6061 snprintf(tmp2,
sizeof(tmp2),
"( %s < %s ; rm -f %s ) &",
mailcmd,
tmp,
tmp);
6128#define COUNT_MSGS_SQL_FMT "SELECT COUNT(*) FROM %s WHERE dir = '%s%s/%s/%s'"
6129static int count_messages_in_folder(
struct odbc_obj *odbc,
const char *
context,
const char *
mailbox,
const char *folder,
int *messages)
6132 char sql[
sizeof(COUNT_MSGS_SQL_FMT) + odbc_table_len + strlen(
VM_SPOOL_DIR)
6135 SQLHSTMT stmt =
NULL;
6136 struct generic_prepare_struct gps = { .sql = sql, .argc = 0 };
6147 res = SQLFetch(stmt);
6148 if (!SQL_SUCCEEDED(res)) {
6149 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
6152 res = SQLGetData(stmt, 1, SQL_CHAR, rowdata,
sizeof(rowdata),
NULL);
6153 if (!SQL_SUCCEEDED(res)) {
6154 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
6158 *messages = atoi(rowdata);
6159 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
6163#undef COUNT_MSGS_SQL_FMT
6165static int inboxcount2(
const char *
mailbox,
int *urgentmsgs,
int *newmsgs,
int *oldmsgs)
6203 SCOPE_EXIT_RTN_VALUE(0,
"Urgent: %d New: %d Old: %d\n", urgentmsgs ? *urgentmsgs : 0, newmsgs ? *newmsgs : 0, oldmsgs ? *oldmsgs : 0);
6218 if (count_messages_in_folder(obj,
context,
tmp,
"INBOX", newmsgs)
6219 || count_messages_in_folder(obj,
context,
tmp,
"Old", oldmsgs)
6220 || count_messages_in_folder(obj,
context,
tmp,
"Urgent", urgentmsgs)) {
6226 SCOPE_EXIT_RTN_VALUE(0,
"Urgent: %d New: %d Old: %d\n", urgentmsgs ? *urgentmsgs : 0, newmsgs ? *newmsgs : 0, oldmsgs ? *oldmsgs : 0);
6237#define MSGCOUNT_SQL_FMT_INBOX "SELECT COUNT(*) FROM %s WHERE dir = '%s%s/%s/INBOX' OR dir = '%s%s/%s/Urgent'"
6238#define MSGCOUNT_SQL_FMT "SELECT COUNT(*) FROM %s WHERE dir = '%s%s/%s/%s'"
6239static int messagecount(
const char *mailbox_id,
const char *folder)
6246 SQLHSTMT stmt =
NULL;
6248 struct generic_prepare_struct gps = { .argc = 0 };
6249 SCOPE_ENTER(3,
"mb: %s folder: %s", mailbox_id, folder);
6266 if (!strcmp(folder,
"INBOX")) {
6281 res = SQLFetch(stmt);
6282 if (!SQL_SUCCEEDED(res)) {
6284 goto bail_with_handle;
6286 res = SQLGetData(stmt, 1, SQL_CHAR, rowdata,
sizeof(rowdata),
NULL);
6287 if (!SQL_SUCCEEDED(res)) {
6289 goto bail_with_handle;
6291 nummsgs = atoi(rowdata);
6294 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
6301#undef MSGCOUNT_SQL_FMT
6302#undef MSGCOUNT_SQL_FMT_INBOX
6344 long duration,
struct ast_vm_user *recip,
char *fmt,
char *dir,
const char *
flag,
6345 const char *dest_folder)
6348 const char *frombox =
mbox(vmu, imbox);
6349 const char *userfolder;
6352 SCOPE_ENTER(3,
"mb: %s imb: %d msgnum: %d recip: %s dir: %s dest_folder: %s",
6358 userfolder =
"Urgent";
6360 userfolder = dest_folder;
6362 userfolder =
"INBOX";
6373 ast_trace(-1,
"fromdir: %s\n", fromdir);
6375 make_file(frompath,
sizeof(frompath), fromdir, msgnum);
6376 ast_trace(-1,
"frompath: %s\n", frompath);
6386 ast_trace(-1,
"recip msgnum: %d\n", recipmsgnum);
6391 make_file(topath,
sizeof(topath), todir, recipmsgnum);
6399 SCOPE_CALL(-1,
STORE, todir, recip->
mailbox, recip->
context, recipmsgnum, chan, recip, fmt, duration,
NULL,
NULL,
NULL);
6419#if !(defined(IMAP_STORAGE) || defined(ODBC_STORAGE))
6467 snprintf(fn,
sizeof(fn),
"%s%s/%s/%s",
VM_SPOOL_DIR,
c, m, folder);
6469 if (!(dir = opendir(fn)))
6472 while ((de = readdir(dir))) {
6473 if (!strncasecmp(de->d_name,
"msg", 3)) {
6477 }
else if (!strncasecmp(de->d_name + 8,
"txt", 3)) {
6504 while ((box =
strsep(&tmp2,
",&"))) {
6505 if ((
context = strchr(box,
'@')))
6548 int tmpnew, tmpold, tmpurgent;
6553 while ((cur =
strsep(&mb,
", "))) {
6565 *urgentmsgs += tmpurgent;
6602 *newmsgs += urgentmsgs;
6609 char arguments[255];
6610 char ext_context[256] =
"";
6611 int newvoicemails = 0, oldvoicemails = 0, urgentvoicemails = 0;
6627 if (!strncmp(mwi_msg->
cause,
"INV", 3))
6629 else if (!strncmp(mwi_msg->
cause,
"BLK", 3))
6639 if (
inboxcount2(ext_context, &urgentvoicemails, &newvoicemails, &oldvoicemails)) {
6642 snprintf(arguments,
sizeof(arguments),
"%s %s %s %d %d %d &",
6645 oldvoicemails, urgentvoicemails);
6646 ast_debug(1,
"Executing %s\n", arguments);
6671 snprintf(dst,
MSG_ID_LEN,
"%ld-%08x", (
long) time(
NULL), unique_counter);
6705 char ext_context[256] =
"";
6721 const char *category =
NULL;
6730 memset(&svm, 0,
sizeof(svm));
6742 duration = (int) (framelength / sample_rate);
6751 if (duration < recipient->minsecs) {
6752 ast_log(
LOG_NOTICE,
"Copying recording to voicemail %s@%s skipped because duration was shorter than "
6753 "minmessage of recipient\n", recdata->
mailbox, recdata->
context);
6763 snprintf(tmptxtfile,
sizeof(tmptxtfile),
"%s/XXXXXX", tmpdir);
6764 txtdes = mkstemp(tmptxtfile);
6774 txt = fdopen(txtdes,
"w+");
6780 "; Message Information file\n"
6803 date, (
long) time(
NULL),
6828 snprintf(ext_context,
sizeof(ext_context),
"%s@%s", recipient->
mailbox, recipient->
context);
6832 res =
inboxcount(ext_context, &newmsgs, &oldmsgs);
6839 if (!(vms = get_vm_state_by_mailbox(recipient->
mailbox, recipient->
context, 0))) {
6844 if (!(vms = create_vm_state_from_user(recipient))) {
6854 msgnum = newmsgs + oldmsgs;
6855 ast_debug(3,
"Messagecount set to %d\n", msgnum);
6856 snprintf(destination,
sizeof(destination),
"%simap/msg%s%04d",
VM_SPOOL_DIR, recipient->
mailbox, msgnum);
6860 if ((res = imap_check_limits(
NULL, vms, recipient, msgnum))) {
6871 ast_debug(3,
"mailbox = %d : inprocess = %d\n",
COUNT(recipient, dir),
6887 ast_log(
LOG_ERROR,
"Couldn't lock directory %s. Voicemail will be lost.\n", dir);
6895 make_file(destination,
sizeof(destination), dir, msgnum);
6897 make_file(tmpaudiofile,
sizeof(tmpaudiofile), tmpdir, msgnum);
6900 ast_log(
LOG_ERROR,
"Audio file failed to copy to tmp dir. Probably low disk space.\n");
6911 ast_log(
LOG_ERROR,
"Audio file failed to move to destination directory. Permissions/Overlap?\n");
6919 snprintf(desttxtfile,
sizeof(desttxtfile),
"%s.txt", destination);
6920 rename(tmptxtfile, desttxtfile);
6937 char cidnum[80], cidname[80];
6943 "origmailbox", recdata->
mailbox,
6950 "origtime", time(
NULL),
6951 "category",
S_OR(category,
""),
6952 "filename", tmptxtfile,
6953 "duration", duration,
6957 STORE(dir, recipient->
mailbox, recipient->
context, msgnum,
NULL, recipient, fmt, 0, vms,
"", msg_id);
6999 int newmsgs, oldmsgs;
7011 int sound_duration = 0;
7013 int greeting_only = 0;
7022 char ext_context[256] =
"";
7025 char ecodes[17] =
"#";
7030 const char *category =
NULL;
7032 const char *alldtmf =
"0123456789ABCD*#";
7044 tmpptr = strchr(
context,
'&');
7046 tmpptr = strchr(
ext,
'&');
7067 memset(&svm, 0,
sizeof(svm));
7082 if (strcmp(vmu->
context,
"default"))
7083 snprintf(ext_context,
sizeof(ext_context),
"%s@%s",
ext, vmu->
context);
7097 ast_trace(-1,
"prefile: %s\n", prefile);
7103 ast_trace(-1,
"tempfile: %s\n", tempfile);
7113 ast_trace(-1,
"new prefile: %s\n", prefile);
7133 strncat(ecodes,
"0",
sizeof(ecodes) - strlen(ecodes) - 1);
7138 strncat(ecodes,
"0",
sizeof(ecodes) - strlen(ecodes) - 1);
7146 strncat(ecodes,
"*",
sizeof(ecodes) - strlen(ecodes) - 1);
7150 strncat(ecodes,
"*",
sizeof(ecodes) - strlen(ecodes) - 1);
7154 for (code = alldtmf; *code; code++) {
7157 if (strchr(ecodes, e[0]) ==
NULL
7161 strncat(ecodes, e,
sizeof(ecodes) - strlen(ecodes) - 1);
7168#if defined(ODBC_STORAGE)
7170#elif defined(IMAP_STORAGE)
7184 if (success == -1) {
7186 ast_trace(-1,
"Greeting '%s' not retrieved from database, but found in file storage. Inserting into database\n", prefile);
7191 ast_trace(-1,
"%s doesn't exist, doing what we can\n", prefile);
7258 if (greeting_only) {
7259 ast_debug(3,
"Greetings only VM (maxmsg=0), Skipping voicemail recording\n");
7283 res =
inboxcount(ext_context, &newmsgs, &oldmsgs);
7290 if (!(vms = get_vm_state_by_mailbox(
ext,
context, 0))) {
7295 if (!(vms = create_vm_state_from_user(vmu))) {
7305 msgnum = newmsgs + oldmsgs;
7306 ast_debug(3,
"Messagecount set to %d\n", msgnum);
7311 if ((res = imap_check_limits(chan, vms, vmu, msgnum))) {
7326 snprintf(tmptxtfile,
sizeof(tmptxtfile),
"%s/XXXXXX", tmpdir);
7327 ast_trace(-1,
"Tempfile: %s\n", tmptxtfile);
7328 txtdes = mkstemp(tmptxtfile);
7352 snprintf(origtime,
sizeof(origtime),
"%ld", (
long) time(
NULL));
7364 "callerid", callerid,
7366 "origtime", origtime,
7367 "category",
S_OR(category,
""),
7368 "filename", tmptxtfile,
7373 txt = fdopen(txtdes,
"w+");
7383 "; Message Information file\n"
7405 date, (
long) time(
NULL),
7406 category ? category :
"",
7408 ast_trace(-1,
"Saving txt file mbox: %s msg_id: %s\n",
ext, msg_id);
7419 res =
SCOPE_CALL_WITH_INT_RESULT(-1,
play_record_review, chan,
NULL, tmptxtfile, vmu->
maxsecs, fmt, 1, vmu, &duration, &sound_duration,
NULL,
options->record_gain, vms,
flag, msg_id, 0);
7425 if (!strcmp(
flag,
"Urgent")) {
7430 fprintf(txt,
"flag=%s\n",
flag);
7431 if (sound_duration < vmu->
minsecs) {
7433 ast_verb(3,
"Recording was %d seconds long but needs to be at least %d - abandoning\n", sound_duration, vmu->
minsecs);
7441 fprintf(txt,
"duration=%d\n", duration);
7450 ast_debug(1,
"The recorded media file is gone, so we should remove the .txt file too!\n");
7470 snprintf(txtfile,
sizeof(txtfile),
"%s.txt", fn);
7472 ast_trace(-1,
"Renaming recordings '%s' -> fn '%s'\n", tmptxtfile, fn);
7476 ast_trace(-1,
"Renaming txt file '%s' -> fn '%s'\n", tmptxtfile, txtfile);
7477 rename(tmptxtfile, txtfile);
7487 snprintf(tmpdur,
sizeof(tmpdur),
"%d", duration);
7494 SCOPE_CALL(-1,
STORE, dir, vmu->
mailbox, vmu->
context, msgnum, chan, vmu, fmt, duration, vms,
flag, msg_id);
7502 exten =
strsep(&tmpptr,
"&");
7503 cntx = strchr(exten,
'@');
7508 memset(&recipu, 0,
sizeof(recipu));
7509 if ((recip =
find_user(&recipu, cntx, exten))) {
7541 }
else if (res > 0 && res !=
't')
7544 if (sound_duration < vmu->
minsecs)
7556 ast_debug(3,
"*** Checking if we can expunge, expungeonhangup set to %d\n", expungeonhangup);
7557 if (expungeonhangup == 1 && vms->mailstream !=
NULL) {
7559#ifdef HAVE_IMAP_TK2006
7560 if (LEVELUIDPLUS (vms->mailstream)) {
7561 mail_expunge_full(vms->mailstream, NIL, EX_UID);
7564 mail_expunge(vms->mailstream);
7573#if !defined(IMAP_STORAGE)
7586 for (x = 0, dest = 0; dest != stopcount && x <
MAXMSGLIMIT; x++) {
7622 snprintf(sequence,
sizeof(sequence),
"%ld", vms->msgArray[msg]);
7624 ast_debug(3,
"Copying sequence %s to mailbox %s\n", sequence,
mbox(vmu, box));
7628 mail_setflag(vms->mailstream, sequence,
"\\Seen");
7630 mail_clearflag(vms->mailstream, sequence,
"\\Seen");
7642 if (vms->mailstream && !mail_status(vms->mailstream,
mailbox, SA_UIDNEXT)) {
7643 if (mail_create(vms->mailstream,
mailbox) != NIL) {
7649 if (init_mailstream(vms, curr_mbox) || !vms->mailstream) {
7654 res = !mail_move(vms->mailstream, sequence, (
char *)
mbox(vmu, box));
7656 res = !mail_copy(vms->mailstream, sequence, (
char *)
mbox(vmu, box));
7668 const char *dbox =
mbox(vmu, box);
7670 SCOPE_ENTER(3,
"dir: %s msg: %d box: %d dbox: %s move? %d \n", dir, msg, box, dbox, move);
7682 ast_trace(-1,
"Deleting message %d\n", msg);
7684 for (i = 1; i <= x; i++) {
7687 make_file(dfn,
sizeof(dfn), ddir, i - 1);
7701 if (strcmp(sfn, dfn)) {
7702 ast_trace(-1,
"Copying message '%s' to '%s'\n", sfn, dfn);
7724 unsigned char buf[256];
7756 bytes += ast_adsi_logo(
buf);
7800 for (x = 0; x < 5; x++) {
7801 snprintf(num,
sizeof(num),
"%d", x);
7829 ast_debug(1,
"Done downloading scripts...\n");
7837 ast_debug(1,
"Restarting session...\n");
7873 unsigned char buf[256];
7875 unsigned char keys[8];
7880 for (x = 0; x < 8; x++)
7899 unsigned char buf[256];
7901 unsigned char keys[8];
7906 for (x = 0; x < 8; x++)
7921 unsigned char buf[256];
7923 unsigned char keys[8];
7929 for (x = 0; x < 5; x++) {
7951 unsigned char buf[256];
7958 char datetime[21] =
"";
7961 unsigned char keys[8];
7969 snprintf(fn2,
sizeof(fn2),
"%s.txt", vms->
fn);
7970 f = fopen(fn2,
"r");
7973 if (!fgets((
char *)
buf,
sizeof(
buf), f)) {
7977 char *stringp =
NULL;
7978 stringp = (
char *)
buf;
7982 if (!strcmp((
char *)
buf,
"callerid"))
7984 if (!strcmp((
char *)
buf,
"origdate"))
7992 for (x = 0; x < 5; x++)
8019 name =
"Unknown Caller";
8036 strcasecmp(vms->
curbox,
"INBOX") ?
" Messages" :
"");
8053 unsigned char buf[256];
8054 unsigned char keys[8];
8062 for (x = 0; x < 5; x++)
8104 unsigned char buf[256] =
"";
8105 char buf1[256] =
"",
buf2[256] =
"";
8107 unsigned char keys[8];
8110 char *newm = (vms->
newmessages == 1) ?
"message" :
"messages";
8111 char *oldm = (vms->
oldmessages == 1) ?
"message" :
"messages";
8117 strncat(
buf1,
" and",
sizeof(
buf1) - strlen(
buf1) - 1);
8120 snprintf(
buf2,
sizeof(
buf2),
"%s.", newm);
8124 snprintf(
buf2,
sizeof(
buf2),
"%s.", oldm);
8126 strcpy(
buf1,
"You have no messages.");
8134 for (x = 0; x < 6; x++)
8151 unsigned char buf[256] =
"";
8152 char buf1[256] =
"",
buf2[256] =
"";
8154 unsigned char keys[8];
8157 char *mess = (vms->
lastmsg == 0) ?
"message" :
"messages";
8163 for (x = 0; x < 6; x++)
8173 strcasecmp(vms->
curbox,
"INBOX") ?
" folder" :
"");
8178 strcpy(
buf2,
"no messages.");
8207 unsigned char buf[256];
8233 for (x = start; x < 5; x++) {
8239 snprintf(fn,
sizeof(fn),
"vm-%s",
mbox(
NULL, x));
8248 ast_verb(4,
"Failed to find file %s; falling back to INBOX\n", fn);
8276 for (x = start; x < 5; x++) {
8280 snprintf(fn,
sizeof(fn),
"vm-%s",
mbox(
NULL, x));
8316 while (((res <
'0') || (res >
'9')) &&
8317 (res !=
'#') && (res >= 0) &&
8332 isprint(res) ? res :
'?', isprint(res) ? res :
'?');
8355 int curmsg,
char *vm_fmts,
char *
context,
signed char record_gain,
long *duration,
8359 int retries = 0, prepend_duration = 0, already_recorded = 0;
8365 signed char zero_gain = 0;
8367 const char *msg_id =
NULL;
8369 const char *duration_str;
8373 make_file(msgfile,
sizeof(msgfile), curdir, curmsg);
8374 ast_trace(-1,
"msgfile: %s\n", msgfile);
8375 strcpy(textfile, msgfile);
8376 strcpy(backup, msgfile);
8377 strcpy(backup_textfile, msgfile);
8378 strncat(textfile,
".txt",
sizeof(textfile) - strlen(textfile) - 1);
8379 strncat(backup,
"-bak",
sizeof(backup) - strlen(backup) - 1);
8380 strncat(backup_textfile,
"-bak.txt",
sizeof(backup_textfile) - strlen(backup_textfile) - 1);
8383 *duration = atoi(duration_str);
8388 while ((cmd >= 0) && (cmd !=
't') && (cmd !=
'*')) {
8399 make_file(vms->introfn,
sizeof(vms->introfn), curdir, curmsg);
8400 strncat(vms->introfn,
"intro",
sizeof(vms->introfn));
8403 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);
8411 ast_trace(-1,
"Prepending to message %d\n", curmsg);
8413 make_file(msgfile,
sizeof(msgfile), curdir, curmsg);
8414 ast_trace(-1,
"msgfile: %s\n", msgfile);
8416 strcpy(textfile, msgfile);
8417 strncat(textfile,
".txt",
sizeof(textfile) - 1);
8428 if (already_recorded) {
8429 ast_trace(-1,
"Restoring '%s' to '%s'\n", backup, msgfile);
8431 copy(backup_textfile, textfile);
8434 ast_trace(-1,
"Backing up '%s' to '%s'\n", backup, msgfile);
8436 copy(textfile, backup_textfile);
8439 already_recorded = 1;
8444 cmd =
SCOPE_CALL_WITH_INT_RESULT(-1,
ast_play_and_prepend, chan,
NULL, msgfile, 0, vm_fmts, &prepend_duration,
NULL, 1,
silencethreshold,
maxsilence);
8457 *duration = atoi(duration_str);
8459 if (prepend_duration) {
8462 char duration_buf[12];
8464 *duration += prepend_duration;
8465 ast_trace(-1,
"Prepending duration: %d total duration: %ld\n", prepend_duration, *duration);
8467 snprintf(duration_buf,
sizeof(duration_buf),
"%ld", *duration);
8478 *vms->introfn =
'\0';
8487 already_recorded = 0;
8505 isprint(cmd) ? cmd :
'?', isprint(cmd) ? cmd :
'?');
8511 if (prepend_duration)
8512 *duration = prepend_duration;
8514 if (already_recorded && cmd == -1) {
8516 ast_trace(-1,
"Restoring '%s' to '%s'\n", backup, msgfile);
8518 rename(backup_textfile, textfile);
8521 if (cmd ==
't' || cmd ==
'S') {
8527static void queue_mwi_event(
const char *channel_id,
const char *box,
int urgent,
int new,
int old)
8536 ast_debug(3,
"Queueing event for mailbox %s New: %d Old: %d\n", box,
new + urgent, old);
8549 ast_debug(3,
"Found alias mapping: %s -> %s\n", mapping->
alias, box);
8575 int newmsgs = 0, oldmsgs = 0, urgentmsgs = 0;
8576 const char *category;
8588 snprintf(todir,
sizeof(todir),
"%simap",
VM_SPOOL_DIR);
8590 make_file(fn,
sizeof(fn), todir, msgnum);
8591 snprintf(ext_context,
sizeof(ext_context),
"%s@%s", vmu->
mailbox, vmu->
context);
8610 char *msg_id =
NULL;
8616 snprintf(filename,
sizeof(filename),
"%s.txt", fn);
8624 if (attach_user_voicemail)
8628 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);
8630 if (attach_user_voicemail)
8635 sendpage(myserveremail, vmu->
pager, msgnum, vmu->
context, vmu->
mailbox,
mbox(vmu, 0), cidnum, cidname, duration, vmu, category,
flag);
8639 DELETE(todir, msgnum, fn, vmu);
8694 char ecodes[16] =
"#";
8695 int res = 0, cmd = 0;
8700 const char mailbox_context[256];
8701 int saved_messages = 0;
8702 int valid_extensions = 0;
8705 char urgent_str[7] =
"";
8706 int prompt_played = 0;
8714 ast_copy_string(urgent_str, urgent ?
"Urgent" :
"",
sizeof(urgent_str));
8724 while (!res && !valid_extensions) {
8725 int use_directory = 0;
8730 while ((cmd >= 0) && !
done ){
8760 isprint(cmd) ? cmd :
'?', isprint(cmd) ? cmd :
'?');
8763 if (cmd < 0 || cmd ==
't')
8767 if (use_directory) {
8770 struct ast_app* directory_app;
8773 if (directory_app) {
8774 char vmcontext[256];
8784 snprintf(vmcontext,
sizeof(vmcontext),
"%s,,v",
context ?
context :
"default");
8785 res =
pbx_exec(chan, directory_app, vmcontext);
8801 if (res || prompt_played > 4)
8803 if ((res =
ast_readstring(chan, username,
sizeof(username) - 1, 2000, 10000,
"#")) < 0)
8811 s =
strsep(&stringp,
"*");
8813 valid_extensions = 1;
8815 snprintf((
char*)mailbox_context,
sizeof(mailbox_context),
"%s@%s", s,
context ?
context :
"default");
8821 if (
inboxcount(mailbox_context, &newmsgs, &oldmsgs)) {
8822 ast_log(
LOG_ERROR,
"Problem in calculating number of voicemail messages available for extension %s\n", mailbox_context);
8825 valid_extensions = 0;
8829 if (!(dstvms = get_vm_state_by_mailbox(s,
context, 0))) {
8830 if (!(dstvms = create_vm_state_from_user(receiver))) {
8834 valid_extensions = 0;
8838 check_quota(dstvms, imapfolder);
8839 if (dstvms->quota_limit && dstvms->quota_usage >= dstvms->quota_limit) {
8840 ast_log(
LOG_NOTICE,
"Mailbox '%s' is exceeded quota %u >= %u\n", mailbox_context, dstvms->quota_usage, dstvms->quota_limit);
8842 valid_extensions = 0;
8851 if ((newmsgs + oldmsgs) >= capacity) {
8852 ast_log(
LOG_NOTICE,
"Mailbox '%s' is full with capacity of %d, prompting for another extension.\n", mailbox_context, capacity);
8854 valid_extensions = 0;
8875 valid_extensions = 0;
8893 s =
strsep(&stringp,
"*");
8896 if (valid_extensions)
8902 if (is_new_message == 1) {
8908 memset(&leave_options, 0,
sizeof(leave_options));
8916 int copy_msg_result = 0;
8920 const char *msg_id =
NULL;
8923 memcpy(&vmstmp, vms,
sizeof(vmstmp));
8927 make_file(filename,
sizeof(filename), dir, curmsg);
8928 strncat(filename,
".txt",
sizeof(filename) - strlen(filename) - 1);
8936 cmd =
SCOPE_CALL_WITH_INT_RESULT(-1,
vm_forwardoptions, chan, sender, vmstmp.
curdir, curmsg,
vmfmts,
S_OR(
context,
"default"), record_gain, &duration, &vmstmp, urgent_str);
8940 int attach_user_voicemail;
8944 dstvms = get_vm_state_by_mailbox(vmtmp->mailbox, vmtmp->context, 0);
8946 dstvms = create_vm_state_from_user(vmtmp);
8949 init_mailstream(dstvms, 0);
8950 if (!dstvms->mailstream) {
8953 copy_msg_result =
STORE(vmstmp.
curdir, vmtmp->mailbox, vmtmp->context, curmsg, chan, vmtmp, fmt, duration, dstvms, urgent_str, msg_id);
8960 myserveremail = vmtmp->serveremail;
8963 sendmail(myserveremail, vmtmp, todircount, vmtmp->context, vmtmp->mailbox,
8967 vmstmp.
fn, vmstmp.introfn, fmt, duration, attach_user_voicemail, chan,
8968 NULL, urgent_str, msg_id);
8970 copy_msg_result =
SCOPE_CALL_WITH_INT_RESULT(-1,
copy_message, chan, sender, 0, curmsg, duration, vmtmp, fmt, dir, urgent_str,
NULL);
8980 if (saved_messages > 0 && !copy_msg_result) {
8997 make_file(msgfile,
sizeof(msgfile), dir, curmsg);
8998 strcpy(textfile, msgfile);
8999 strcpy(backup, msgfile);
9000 strcpy(backup_textfile, msgfile);
9001 strncat(textfile,
".txt",
sizeof(textfile) - strlen(textfile) - 1);
9002 strncat(backup,
"-bak",
sizeof(backup) - strlen(backup) - 1);
9003 strncat(backup_textfile,
"-bak.txt",
sizeof(backup_textfile) - strlen(backup_textfile) - 1);
9006 rename(backup_textfile, textfile);
9013 make_file(msgfile,
sizeof(msgfile), dir, curmsg);
9014 strcpy(textfile, msgfile);
9015 strcpy(backup_textfile, msgfile);
9016 strncat(textfile,
".txt",
sizeof(textfile) - strlen(textfile) - 1);
9017 strncat(backup_textfile,
"-bak.txt",
sizeof(backup_textfile) - strlen(backup_textfile) - 1);
9018 rename(backup_textfile, textfile);
9093 if (time_now.tm_year == time_then.tm_year)
9094 snprintf(temp,
sizeof(temp),
"%d", time_now.tm_yday);
9096 snprintf(temp,
sizeof(temp),
"%d", (time_now.tm_year - time_then.tm_year) * 365 + (time_now.tm_yday - time_then.tm_yday));
9142 char *callerid, *
name;
9156 ast_debug(1,
"VM-CID: composite caller ID received: %s, context: %s\n", cid,
context);
9173 ast_verb(3,
"Playing envelope info: CID number '%s' matches mailbox number, playing recorded name\n", callerid);
9178 ast_verb(3,
"Playing envelope info: message from '%s'\n", callerid);
9181 res =
wait_file2(chan, vms,
"vm-from-extension");
9187 ast_debug(1,
"VM-CID: Numeric caller id: (%s)\n", callerid);
9193 ast_verb(3,
"Playing recorded name for CID number '%s' - '%s'\n", callerid,prefile);
9196 ast_verb(3,
"Played recorded name result '%d'\n", res);
9199 wait_file2(chan, vms,
"vm-from-phonenumber");
9208 ast_debug(1,
"VM-CID: From an unknown number\n");
9210 res =
wait_file2(chan, vms,
"vm-unknown-caller");
9221 if (duration ==
NULL)
9225 durations = atoi(duration);
9226 durationm = (durations / 60);
9228 ast_debug(1,
"VM-Duration: duration is: %d seconds converted to: %d minutes\n", durations, durationm);
9230 if ((!res) && (durationm >= minduration)) {
9235 div_t num = div(durationm, 10);
9237 if (durationm == 1) {
9240 }
else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
9269 const char *origtime, *
context, *category, *duration, *
flag;
9284 snprintf(filename,
sizeof(filename),
"%s.txt", vms->
fn);
9305 ten = (vms->
curmsg + 1) / 10;
9306 one = (vms->
curmsg + 1) % 10;
9309 snprintf(nextmsg,
sizeof(nextmsg),
"digits/n-%d", vms->
curmsg + 1);
9312 snprintf(nextmsg,
sizeof(nextmsg),
"digits/n-%d", ten * 10);
9316 snprintf(nextmsg,
sizeof(nextmsg),
"digits/n-%d", one);
9358 res =
wait_file2(chan, vms,
"vm-meddelandet");
9425 isprint(res) ? res :
'?', isprint(res) ? res :
'?');
9432static int imap_remove_file(
char *dir,
int msgnum)
9440 snprintf(
intro,
sizeof(
intro),
"%sintro", fn);
9444 if ((msgnum < 0 && imapgreetings) || msgnum > -1) {
9449 snprintf(full_fn,
sizeof(full_fn),
"%s.txt", fn);
9457static int imap_delete_old_greeting (
char *dir,
struct vm_state *vms)
9459 char *
file, *filename;
9469 ast_log(
AST_LOG_ERROR,
"Failed to procure file name from directory passed. You should never see this.\n");
9484 for (i = 0; i < vms->mailstream->nmsgs; i++) {
9485 mail_fetchstructure(vms->mailstream, i + 1, &body);
9487 if (body->nested.part->next && body->nested.part->next->body.parameter->value) {
9488 char *attachment = body->nested.part->next->body.parameter->value;
9489 char copy[strlen(attachment) + 1];
9491 strcpy(
copy, attachment);
9494 filename =
strsep(&attachment,
".");
9495 if (!strcmp(filename,
file)) {
9496 snprintf(arg,
sizeof(arg),
"%d", i + 1);
9497 mail_setflag(vms->mailstream, arg,
"\\DELETED");
9505 mail_expunge(vms->mailstream);
9507 if (curr_mbox != -1) {
9509 if (init_mailstream(vms, curr_mbox) || !vms->mailstream) {
9518#elif !defined(IMAP_STORAGE)
9521 int count_msg, last_msg;
9522 SCOPE_ENTER(3,
"user: %s dir: %s msg: %d box %d\n",
9537 if (count_msg < 0) {
9562 if (last_msg < -1) {
9564 }
else if (vms->
lastmsg != last_msg) {
9565 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);
9576 int last_msg_idx = 0;
9579 int res = 0, nummsg;
9586 ast_trace(-1,
"No messages in mailbox\n");
9599 if (last_msg_idx != vms->
lastmsg) {
9604 for (x = 0; x < last_msg_idx + 1; x++) {
9613 if (strcmp(vms->
fn, fn2)) {
9630 ast_trace(-1,
"Unable to lock path. Not moving message to deleted folder.\n");
9649 for (x = vms->
curmsg + 1; x <= nummsg; x++) {
9663 for (x = last_msg_idx - 1; x >= 0; x--) {
9704 if (!strcasecmp(box,
"vm-INBOX") || !strcasecmp(box,
"vm-Old")){
9717 if (!strcasecmp(box,
"vm-INBOX") || !strcasecmp(box,
"vm-Old")) {
9730 if (!strcasecmp(box,
"vm-INBOX") || !strcasecmp(box,
"vm-Old")) {
9731 if (!strcasecmp(box,
"vm-INBOX"))
9746 if (!strcasecmp(box,
"vm-Family") || !strcasecmp(box,
"vm-Friends") || !strcasecmp(box,
"vm-Work")){
10105 snprintf(recname,
sizeof(recname),
"digits/1kvk");
10107 snprintf(recname,
sizeof(recname),
"digits/%dhk", vms->
urgentmessages);
10120 snprintf(recname,
sizeof(recname),
"digits/1kvk");
10122 snprintf(recname,
sizeof(recname),
"digits/%dhk", vms->
newmessages);
10137 snprintf(recname,
sizeof(recname),
"digits/1kvk");
10139 snprintf(recname,
sizeof(recname),
"digits/%dhk", vms->
oldmessages);
10215 }
else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
10216 if (num.rem == 2) {
10242 }
else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
10243 if (num.rem == 2) {
10853 static int deprecation_warning = 0;
10854 if (deprecation_warning++ % 10 == 0) {
10855 ast_log(
LOG_WARNING,
"cz is not a standard language code. Please switch to using cs instead.\n");
10923 if (skipadvanced) {
10938 if (!res && !skipadvanced)
10953 int curmsg_deleted;
10962 if (!curmsg_deleted) {
11012 if (skipadvanced) {
11033 if (!res && !skipadvanced)
11048 int curmsg_deleted;
11056 if (!curmsg_deleted) {
11127 char newpassword[80] =
"";
11128 char newpassword2[80] =
"";
11130 unsigned char buf[256];
11147 cmd =
play_record_review(chan,
"vm-rec-name", prefile,
maxgreet, fmtc, 0, vmu, &duration,
NULL,
NULL, record_gain, vms,
NULL,
NULL, 0);
11148 if (cmd < 0 || cmd ==
't' || cmd ==
'#')
11157 cmd =
play_record_review(chan,
"vm-rec-unv", prefile,
maxgreet, fmtc, 0, vmu, &duration,
NULL,
NULL, record_gain, vms,
NULL,
NULL, 0);
11158 if (cmd < 0 || cmd ==
't' || cmd ==
'#')
11164 cmd =
play_record_review(chan,
"vm-rec-busy", prefile,
maxgreet, fmtc, 0, vmu, &duration,
NULL,
NULL, record_gain, vms,
NULL,
NULL, 0);
11165 if (cmd < 0 || cmd ==
't' || cmd ==
'#')
11175 newpassword[1] =
'\0';
11178 newpassword[0] =
'\0';
11179 if (cmd < 0 || cmd ==
't' || cmd ==
'#')
11181 cmd =
ast_readstring(chan, newpassword + strlen(newpassword),
sizeof(newpassword) - 1, 2000, 10000,
"#");
11182 if (cmd < 0 || cmd ==
't' || cmd ==
'#')
11189 newpassword2[1] =
'\0';
11192 newpassword2[0] =
'\0';
11193 if (cmd < 0 || cmd ==
't' || cmd ==
'#')
11195 cmd =
ast_readstring(chan, newpassword2 + strlen(newpassword2),
sizeof(newpassword2) - 1, 2000, 10000,
"#");
11196 if (cmd < 0 || cmd ==
't' || cmd ==
'#')
11198 if (!strcmp(newpassword, newpassword2))
11214 ast_debug(1,
"User %s set password to %s of length %d\n", vms->
username, newpassword, (
int) strlen(newpassword));
11225 char newpassword[80] =
"";
11226 char newpassword2[80] =
"";
11228 unsigned char buf[256];
11241 while ((cmd >= 0) && (cmd !=
't')) {
11247 cmd =
SCOPE_CALL_WITH_INT_RESULT(-1,
play_record_review, chan,
"vm-rec-unv", prefile,
maxgreet, fmtc, 0, vmu, &duration,
NULL,
NULL, record_gain, vms,
NULL,
NULL, 0);
11251 cmd =
SCOPE_CALL_WITH_INT_RESULT(-1,
play_record_review, chan,
"vm-rec-busy", prefile,
maxgreet, fmtc, 0, vmu, &duration,
NULL,
NULL, record_gain, vms,
NULL,
NULL, 0);
11255 cmd =
SCOPE_CALL_WITH_INT_RESULT(-1,
play_record_review, chan,
"vm-rec-name", prefile,
maxgreet, fmtc, 0, vmu, &duration,
NULL,
NULL, record_gain, vms,
NULL,
NULL, 0);
11265 newpassword[1] =
'\0';
11268 newpassword[0] =
'\0';
11272 if ((cmd =
ast_readstring(chan, newpassword + strlen(newpassword),
sizeof(newpassword) - 1, 2000, 10000,
"#")) < 0) {
11285 newpassword2[1] =
'\0';
11288 newpassword2[0] =
'\0';
11293 if ((cmd =
ast_readstring(chan, newpassword2 + strlen(newpassword2),
sizeof(newpassword2) - 1, 2000, 10000,
"#")) < 0) {
11297 if (strcmp(newpassword, newpassword2)) {
11313 ast_debug(1,
"User %s set password to %s of length %d\n",
11314 vms->
username, newpassword, (
int) strlen(newpassword));
11341 isprint(cmd) ? cmd :
'?', isprint(cmd) ? cmd :
'?');
11371 unsigned char buf[256];
11385 while ((cmd >= 0) && (cmd !=
't')) {
11390 cmd =
play_record_review(chan,
"vm-rec-temp", prefile,
maxgreet, fmtc, 0, vmu, &duration,
NULL,
NULL, record_gain, vms,
NULL,
NULL, 0);
11398 cmd =
play_record_review(chan,
"vm-rec-temp", prefile,
maxgreet, fmtc, 0, vmu, &duration,
NULL,
NULL, record_gain, vms,
NULL,
NULL, 0);
11401 DELETE(prefile, -1, prefile, vmu);
11411 "vm-tempgreeting2" :
"vm-tempgreeting");
11422 isprint(cmd) ? cmd :
'?', isprint(cmd) ? cmd :
'?');
11448 if (!strcasecmp(vms->
vmbox,
"vm-INBOX") ||!strcasecmp(vms->
vmbox,
"vm-Old")){
11450 snprintf(vms->
fn,
sizeof(vms->
fn),
"vm-%ss", vms->
curbox);
11459 snprintf(vms->
fn,
sizeof(vms->
fn),
"vm-%s", vms->
curbox);
11475 if (!strcasecmp(vms->
fn,
"INBOX")) {
11503 snprintf(vms->
fn,
sizeof(vms->
fn),
"vm-%s", vms->
curbox);
11531 snprintf(vms->
fn,
sizeof(vms->
fn),
"vm-%s", vms->
curbox);
11553 snprintf(vms->
fn,
sizeof(vms->
fn),
"vm-%s", vms->
curbox);
11584 snprintf(vms->
fn,
sizeof(vms->
fn),
"vm-%s", vms->
curbox);
11608 snprintf(vms->
fn,
sizeof(vms->
fn),
"vm-%s", vms->
curbox);
11638 snprintf(vms->
fn,
sizeof(vms->
fn),
"vm-%s", vms->
curbox);
11662 snprintf(vms->
fn,
sizeof(vms->
fn),
"vm-%s", vms->
curbox);
11705 int skipuser,
int max_logins,
int silent)
11707 int useadsi = 0, valid = 0, logretries = 0;
11713 if (!skipuser && useadsi)
11722 while (!valid && (logretries < max_logins)) {
11732 ast_verb(3,
"Username not entered\n");
11735 }
else if (
mailbox[0] ==
'*') {
11737 ast_verb(4,
"Mailbox begins with '*', attempting jump to extension 'a'\n");
11742 ast_verb(4,
"Jump to extension 'a' failed; setting mailbox to NULL\n");
11750 char fullusername[80];
11753 strncat(fullusername,
mailbox,
sizeof(fullusername) - 1 - strlen(fullusername));
11758 memset(&vmus, 0,
sizeof(vmus));
11777 ast_verb(4,
"Password begins with '*', attempting jump to extension 'a'\n");
11784 ast_verb(4,
"Jump to extension 'a' failed; setting mailbox and user to NULL\n");
11794 if (passptr[0] ==
'-') passptr++;
11796 if (vmu && !strcmp(passptr,
password))
11805 if (skipuser || logretries >= max_logins) {
11826 if (!valid && (logretries >= max_logins)) {
11832 if (vmu && !skipuser) {
11841 const char *msg_id)
11890 memset(&vmus, 0,
sizeof(vmus));
11891 memset(&vms, 0,
sizeof(vms));
11894 goto play_msg_cleanup;
11906 goto play_msg_cleanup;
11918 goto play_msg_cleanup;
11934 vmstate_delete(&vms);
11984#define VMBOX_STRING_HEADER_FORMAT "%-32.32s %-32.32s %-16.16s %-16.16s %-16.16s %-16.16s\n"
11985#define VMBOX_STRING_DATA_FORMAT "%-32.32s %-32.32s %-16.16s %-16.16s %-16.16s %-16.16s\n"
11991 memset(&vmus, 0,
sizeof(vmus));
11992 memset(&vms, 0,
sizeof(vms));
12007#define VM_STRING_HEADER_FORMAT "%-8.8s %-32.32s %-32.32s %-9.9s %-6.6s %-30.30s\n"
12016 if (!mailbox_snapshot) {
12023 for (i = 0; i < mailbox_snapshot->
folders; i++) {
12026 msg->flag,
msg->msg_id);
12049 const char *from_context =
a->argv[3];
12050 const char *from_folder =
a->argv[4];
12051 const char *
id[] = {
a->argv[5] };
12052 const char *to_mailbox =
a->argv[6];
12053 const char *to_context =
a->argv[7];
12054 const char *to_folder =
a->argv[8];
12057 ast_cli(
a->fd,
"Error forwarding message %s from mailbox %s@%s %s to mailbox %s@%s %s\n",
12058 id[0],
from_mailbox, from_context, from_folder, to_mailbox, to_context, to_folder);
12060 ast_cli(
a->fd,
"Forwarded message %s from mailbox %s@%s %s to mailbox %s@%s %s\n",
12061 id[0],
from_mailbox, from_context, from_folder, to_mailbox, to_context, to_folder);
12070 const char *from_folder =
a->argv[4];
12071 const char *
id[] = {
a->argv[5] };
12072 const char *to_folder =
a->argv[6];
12075 ast_cli(
a->fd,
"Error moving message %s from mailbox %s@%s %s to %s\n",
12078 ast_cli(
a->fd,
"Moved message %s from mailbox %s@%s %s to %s\n",
12088 const char *folder =
a->argv[4];
12089 const char *
id[] = {
a->argv[5] };
12092 ast_cli(
a->fd,
"Error removing message %s from mailbox %s@%s %s\n",
12095 ast_cli(
a->fd,
"Removed message %s from mailbox %s@%s %s\n",
12103 const char *
word =
a->word;
12114 wordlen = strlen(
word);
12117 if (!strncasecmp(
word, vmu->
mailbox , wordlen)) {
12127 }
else if (pos == 4) {
12129 const char *box =
a->argv[3];
12130 wordlen = strlen(
word);
12152 e->
command =
"voicemail show mailbox";
12154 "Usage: voicemail show mailbox <mailbox> <context>\n"
12155 " Show contents of mailbox <mailbox>@<context>\n";
12163 if (
a->argc != 5) {
12193 const char *
word =
a->word;
12199 const char *
context =
"", *
mailbox =
"", *folder =
"", *
id =
"";
12202 if (pos > maxpos) {
12208 if (pos == 2 || (pos == 6 && maxpos == 8)) {
12210 wordlen = strlen(
word);
12213 if (!strncasecmp(
word, vmu->
mailbox , wordlen)) {
12223 }
else if (pos == 3 || pos == 7) {
12225 mailbox = (pos == 3) ?
a->argv[2] :
a->argv[6];
12226 wordlen = strlen(
word);
12239 }
else if (pos == 4 || pos == 8 || (pos == 6 && maxpos == 6) ) {
12242 wordlen = strlen(
word);
12249 }
else if (pos == 5) {
12255 folder =
a->argv[4];
12256 wordlen = strlen(
word);
12268 if (
id && !strncasecmp(
word,
msg->msg_id, wordlen) && ++which >
state) {
12286 e->
command =
"voicemail forward";
12288 "Usage: voicemail forward <from_mailbox> <from_context> <from_folder> <messageid> <to_mailbox> <to_context> <to_folder>\n"
12289 " Forward message <messageid> in mailbox <mailbox>@<context> <from_folder>\n"
12290 " to mailbox <mailbox>@<context> <to_folder>\n";
12298 if (
a->argc != 9) {
12313 e->
command =
"voicemail move";
12315 "Usage: voicemail move <mailbox> <context> <from_folder> <messageid> <to_folder>\n"
12316 " Move message <messageid> in mailbox <mailbox>&<context> from <from_folder> to <to_folder>\n";
12324 if (
a->argc != 7) {
12339 e->
command =
"voicemail remove";
12341 "Usage: voicemail remove <mailbox> <context> <from_folder> <messageid>\n"
12342 " Remove message <messageid> from <from_folder> in mailbox <mailbox>@<context>\n";
12350 if (
a->argc != 6) {
12369 char prefixstr[80] =
"";
12370 char ext_context[256]=
"";
12377 int silentexit = 0;
12379 signed char record_gain = 0;
12381 int play_folder = 0;
12410 if (
args.argc == 2) {
12420 record_gain = (
signed char) gain;
12440 if (play_folder > 9 || play_folder < 0) {
12442 "Invalid value '%s' provided for folder autoplay option. Defaulting to 'INBOX'\n",
12452 while (*(
args.argv0)) {
12453 if (*(
args.argv0) ==
's')
12455 else if (*(
args.argv0) ==
'p')
12520 pthread_once(&ts_vmstate.once, ts_vmstate.key_init);
12521 pthread_setspecific(ts_vmstate.key, &vms);
12523 vms.interactive = 1;
12527 vmstate_insert(&vms);
12528 init_vm_state(&vms);
12534 ast_channel_language_set(chan, vmu->
language);
12539 ast_trace(-1,
"Before open_mailbox\n");
12542 ast_trace(-1,
"open mailbox: %d\n", res);
12550 ast_trace(-1,
"open mailbox: %d\n", res);
12559 ast_trace(-1,
"open mailbox: %d\n", res);
12576 ast_trace(-1,
"open mailbox: %d\n", res);
12614 if ((cmd ==
't') || (cmd ==
'#')) {
12620 }
else if (cmd < 0) {
12629 ast_debug(3,
"Checking quotas: comparing %u to %u\n", vms.quota_usage, vms.quota_limit);
12630 if (vms.quota_limit && vms.quota_usage >= vms.quota_limit) {
12631 ast_debug(1,
"*** QUOTA EXCEEDED!!\n");
12648 isprint(cmd) ? cmd :
'?', isprint(cmd) ? cmd :
'?');
12652 while ((cmd > -1) && (cmd !=
't') && (cmd !=
'#')) {
12654 ast_trace(-1,
"Main menu: %d %c\n", cmd, (cmd >= 32 && cmd <= 126 ? cmd :
' '));
12670 isprint(cmd) ? cmd :
'?', isprint(cmd) ? cmd :
'?');
12673 }
else if (cmd > 0) {
12677 ast_trace(-1,
"close mailbox: %d\n", res);
12681 if (cmd != 11) in_urgent = 0;
12684 ast_trace(-1,
"open mailbox: %d\n", res);
12704 while ((cmd > -1) && (cmd !=
't') && (cmd !=
'#')) {
12711 ast_trace(-1,
"advanced options: %d\n", cmd);
12721 ast_verb(3,
"Callback Requested\n");
12724 ast_trace(-1,
"advanced options: %d\n", cmd);
12742 ast_trace(-1,
"advanced options: %d\n", cmd);
12769 ast_trace(-1,
"forward message: %d\n", cmd);
12812 isprint(cmd) ? cmd :
'?', isprint(cmd) ? cmd :
'?');
12835 ast_trace(-1,
"close mailbox: %d\n", res);
12840 ast_trace(-1,
"open mailbox: %d\n", res);
12843 ast_debug(1,
"No more new messages, opened INBOX and got %d Urgent messages\n", vms.
lastmsg + 1);
12870 ast_trace(-1,
"close mailbox: %d\n", res);
12875 ast_trace(-1,
"open mailbox: %d\n", res);
12878 ast_debug(1,
"No more urgent messages, opened INBOX and got %d new messages\n", vms.
lastmsg + 1);
12897 if (play_folder == 0) {
12904 else if (play_folder == 1)
12908 if (play_folder == 0) {
12915 else if (play_folder == 1)
12931 if (in_urgent == 1) {
12936 ast_trace(-1,
"close mailbox: %d\n", res);
12941 ast_trace(-1,
"open mailbox: %d\n", res);
12944 ast_debug(1,
"No more urgent messages, opened INBOX and got %d new messages\n", vms.
lastmsg + 1);
12966 ast_trace(-1,
"forward message: %d\n", res);
12979 ast_trace(-1,
"close mailbox: %d\n", res);
12984 ast_trace(-1,
"open mailbox: %d\n", res);
12987 ast_debug(1,
"No more urgent messages, opened INBOX and got %d new messages\n", vms.
lastmsg + 1);
13008 isprint(cmd) ? cmd :
'?', isprint(cmd) ? cmd :
'?');
13013 }
else if (cmd > 0) {
13014 box = cmd = cmd -
'0';
13018 ast_trace(-1,
"save to folder: %d\n", res);
13020#ifndef IMAP_STORAGE
13032 snprintf(vms.
fn,
sizeof(vms.
fn),
"vm-%s",
mbox(vmu, box));
13061 ast_trace(-1,
"close mailbox: %d\n", res);
13066 ast_trace(-1,
"open mailbox: %d\n", res);
13069 ast_debug(1,
"No more urgent messages, opened INBOX and got %d new messages\n", vms.
lastmsg + 1);
13118 ast_trace(-1,
"open mailbox: %d\n", res);
13129 if ((cmd ==
't') || (cmd ==
'#')) {
13157 int new = 0, old = 0, urgent = 0;
13158 snprintf(ext_context,
sizeof(ext_context),
"%s@%s", vms.
username, vmu->
context);
13166 ast_debug(3,
"*** Checking if we can expunge, deleted set to %d, expungeonhangup set to %d\n", deleted, expungeonhangup);
13167 if (vmu && deleted == 1 && expungeonhangup == 1 && vms.mailstream !=
NULL) {
13169#ifdef HAVE_IMAP_TK2006
13170 if (LEVELUIDPLUS (vms.mailstream)) {
13171 mail_expunge_full(vms.mailstream, NIL, EX_UID);
13174 mail_expunge(vms.mailstream);
13180 vmstate_delete(&vms);
13187 pthread_setspecific(ts_vmstate.key,
NULL);
13205 memset(&leave_options, 0,
sizeof(leave_options));
13210 if (
args.argc == 2) {
13236 res =
ast_app_getdata(chan,
"vm-whichbox", temp,
sizeof(temp) - 1, 0);
13286 ast_log(
LOG_ERROR,
"Voicemail data file %s/%d.txt has no [message] category?\n", dir, msg);
13307 ast_log(
LOG_WARNING,
"Mailbox %s in context %s begins with '*' character. The '*' character,"
13308 "\n\twhen it is the first character in a mailbox or password, is used to jump to a"
13309 "\n\tpredefined extension 'a'. A mailbox or password beginning with '*' is not valid"
13310 "\n\tand will be ignored.\n", box,
context);
13317 ast_log(
LOG_WARNING,
"\nIt has been detected that you have defined mailbox '%s' in separate\
13318 \n\tcontexts and that you have the 'searchcontexts' option on. This type of\
13319 \n\tconfiguration creates an ambiguity that you likely do not want. Please\
13320 \n\tamend your voicemail.conf file to avoid this situation.\n", box);
13350 int new = 0, old = 0, urgent = 0;
13361 if ((s =
strsep(&stringp,
","))) {
13364 "\n\tmust be reset in voicemail.conf.\n", box);
13369 if (stringp && (s =
strsep(&stringp,
","))) {
13372 if (stringp && (s =
strsep(&stringp,
","))) {
13375 if (stringp && (s =
strsep(&stringp,
","))) {
13395 imap_logout(mailbox_full);
13402#ifdef TEST_FRAMEWORK
13408 static const char options_string[] =
"attach=yes|attachfmt=wav49|"
13409 "serveremail=someguy@digium.com|fromstring=Voicemail System|tz=central|delete=yes|saycid=yes|"
13410 "sendvoicemail=yes|review=yes|tempgreetwarn=yes|messagewrap=yes|operator=yes|leaveurgent=yes|"
13411 "envelope=yes|moveheard=yes|sayduration=yes|saydurationm=5|forcename=yes|"
13412 "forcegreetings=yes|callback=somecontext|dialout=somecontext2|"
13413 "exitcontext=somecontext3|minsecs=10|maxsecs=100|nextaftercmd=yes|"
13414 "backupdeleted=50|volgain=1.3|passwordlocation=spooldir|emailbody="
13415 "Dear ${VM_NAME}:\n\n\tYou were just left a ${VM_DUR} long message|emailsubject="
13416 "[PBX]: New message \\\\${VM_MSGNUM}\\\\ in mailbox ${VM_MAILBOX}";
13418 static const char option_string2[] =
"imapuser=imapuser|imappassword=imappasswd|"
13419 "imapfolder=INBOX|imapvmshareid=6000|imapserver=imapserver|imapport=1234|imapflags=flagged";
13424 info->name =
"vmuser";
13425 info->category =
"/apps/app_voicemail/";
13426 info->summary =
"Vmuser unit test";
13427 info->description =
13428 "This tests passing all supported parameters to apply_options, the voicemail user config parser";
13446 if (strcasecmp(vmu->
attachfmt,
"wav49")) {
13450 if (strcasecmp(vmu->
fromstring,
"Voicemail System")) {
13454 if (strcasecmp(vmu->
serveremail,
"someguy@digium.com")) {
13458 if (!vmu->
emailsubject || strcasecmp(vmu->
emailsubject,
"[PBX]: New message \\${VM_MSGNUM}\\ in mailbox ${VM_MAILBOX}")) {
13462 if (!vmu->
emailbody || strcasecmp(vmu->
emailbody,
"Dear ${VM_NAME}:\n\n\tYou were just left a ${VM_DUR} long message")) {
13466 if (strcasecmp(vmu->
zonetag,
"central")) {
13526 if (strcasecmp(vmu->
callback,
"somecontext")) {
13530 if (strcasecmp(vmu->
dialout,
"somecontext2")) {
13534 if (strcasecmp(vmu->
exit,
"somecontext3")) {
13565 if (strcasecmp(vmu->imapuser,
"imapuser")) {
13569 if (strcasecmp(vmu->imappassword,
"imappasswd")) {
13573 if (strcasecmp(vmu->imapfolder,
"INBOX")) {
13577 if (strcasecmp(vmu->imapvmshareid,
"6000")) {
13581 if (strcasecmp(vmu->imapserver,
"imapserver")) {
13585 if (strcasecmp(vmu->imapport,
"1234")) {
13589 if (strcasecmp(vmu->imapflags,
"flagged")) {
13619 ast_log(
LOG_ERROR,
"VM_INFO requires an argument (<mailbox>[@<context>],attribute[,folder])\n");
13629 ast_log(
LOG_ERROR,
"VM_INFO requires an argument (<mailbox>[@<context>],attribute[,folder])\n");
13633 memset(&svm, 0,
sizeof(svm));
13636 if (!strncasecmp(arg.attribute,
"exists", 5)) {
13643 if (!strncasecmp(arg.attribute,
"password", 8)) {
13645 }
else if (!strncasecmp(arg.attribute,
"fullname", 8)) {
13647 }
else if (!strncasecmp(arg.attribute,
"email", 5)) {
13649 }
else if (!strncasecmp(arg.attribute,
"pager", 5)) {
13651 }
else if (!strncasecmp(arg.attribute,
"language", 8)) {
13653 }
else if (!strncasecmp(arg.attribute,
"locale", 6)) {
13655 }
else if (!strncasecmp(arg.attribute,
"tz", 2)) {
13657 }
else if (!strncasecmp(arg.attribute,
"count", 5)) {
13666 ast_log(
LOG_ERROR,
"Unable to retrieve message count for mailbox %s\n", arg.mailbox_context);
13670 snprintf(
buf,
len,
"%d", res);
13672 ast_log(
LOG_ERROR,
"Unknown attribute '%s' for VM_INFO\n", arg.attribute);
13692 int silent = 0, skipuser = 0;
13718 }
else if (
mailbox[0] ==
'*') {
13731 const char *cat =
NULL;
13740 "=============================================================\n"
13741 "=== Configured Voicemail Users ==============================\n"
13742 "=============================================================\n"
13748 "=== Mailbox ...\n"
13754 "=== ---------------------------------------------------------\n"
13759 "=============================================================\n"
13778 wordlen = strlen(
word);
13799#define HVSU_OUTPUT_FORMAT "%-10s %-5s %-25s %-10s %6s\n"
13801 int users_counter = 0;
13805 e->
command =
"voicemail show users [for]";
13807 "Usage: voicemail show users [for <context>]\n"
13808 " Lists all mailboxes currently set up\n";
13814 if ((
a->argc < 3) || (
a->argc > 5) || (
a->argc == 4))
13816 if (
a->argc == 5) {
13817 if (strcmp(
a->argv[3],
"for"))
13824 ast_cli(
a->fd,
"You must specify a specific context to show users from realtime!\n");
13832 ast_cli(
a->fd,
"There are no voicemail users currently defined\n");
13855 int newmsgs = 0, oldmsgs = 0;
13856 char count[12],
tmp[256] =
"";
13861 snprintf(count,
sizeof(count),
"%d", newmsgs);
13867 ast_cli(
a->fd,
"%d voicemail users configured.\n", users_counter);
13875#define HVSZ_OUTPUT_FORMAT "%-15s %-20s %-45s\n"
13880 e->
command =
"voicemail show zones";
13882 "Usage: voicemail show zones\n"
13883 " Lists zone message formats\n";
13899 ast_cli(
a->fd,
"There are no voicemail zones currently defined\n");
13912#define ALIASES_OUTPUT_FORMAT "%-32s %-32s\n"
13917 e->
command =
"voicemail show aliases";
13919 "Usage: voicemail show aliases\n"
13920 " Lists mailbox aliases\n";
13930 ast_cli(
a->fd,
"Aliases are not enabled\n");
13952 e->
command =
"voicemail reload";
13954 "Usage: voicemail reload\n"
13955 " Reload voicemail configuration\n";
13964 ast_cli(
a->fd,
"Reloading voicemail configuration...\n");
13983 int new = 0, old = 0, urgent = 0;
13993 if (imap_poll_logout) {
14009 struct timespec ts = { 0, };
14010 struct timeval wait;
14019 ts.tv_sec = wait.tv_sec;
14020 ts.tv_nsec = wait.tv_usec * 1000;
14031static void imap_logout(
const char *mailbox_id)
14044 memset(&vmus, 0,
sizeof(vmus));
14050 vms = get_vm_state_by_imapuser(vmu->imapuser, 0);
14059 vms->mailstream = mail_close(vms->mailstream);
14062 vmstate_delete(vms);
14065static int imap_close_subscribed_mailbox(
struct ast_mwi_state *mwi_state,
void *data)
14088 imap_close_subscribed_mailbox(mwi_state,
NULL);
14162 const char* event_name,
14163 const char* actionid
14171 if((s ==
NULL) || (vmu ==
NULL) || (event_name ==
NULL) || (actionid ==
NULL)) {
14191 ast_log(
LOG_ERROR,
"Could not get mailbox count. user[%s], context[%s]\n",
14199 "VMContext: %s\r\n"
14200 "VoiceMailbox: %s\r\n"
14204 "ServerEmail: %s\r\n"
14205 "FromString: %s\r\n"
14206 "MailCommand: %s\r\n"
14212 "ExitContext: %s\r\n"
14213 "SayDurationMinimum: %d\r\n"
14214 "SayEnvelope: %s\r\n"
14216 "AttachMessage: %s\r\n"
14217 "AttachmentFormat: %s\r\n"
14218 "DeleteMessage: %s\r\n"
14219 "VolumeGain: %.2f\r\n"
14220 "CanReview: %s\r\n"
14221 "CanMarkUrgent: %s\r\n"
14222 "CallOperator: %s\r\n"
14223 "MaxMessageCount: %d\r\n"
14224 "MaxMessageLength: %d\r\n"
14225 "NewMessageCount: %d\r\n"
14226 "OldMessageCount: %d\r\n"
14229 "IMAPServer: %s\r\n"
14231 "IMAPFlags: %s\r\n"
14287 const char* event_name,
14288 const char* actionid)
14292 int nummessages = 0;
14297 if (!mailbox_snapshot) {
14305 for (i = 0; i < mailbox_snapshot->
folders; i++) {
14350 (at = strchr(mwi_state->
uniqueid,
'@')) &&
14354 (at = strchr(mwi_state->
uniqueid,
'@')) &&
14355 strcmp(
context, at + 1) == 0) ||
14358 (at = strchr(mwi_state->
uniqueid,
'@')) &&
14360 strcmp(
context, at + 1) == 0)
14380 char actionid[128];
14392 actionid[0] =
'\0';
14394 snprintf(actionid,
sizeof(actionid),
"ActionID: %s\r\n",
id);
14398 memset(&svm, 0,
sizeof(svm));
14402 astman_send_ack(s, m,
"There is no voicemail user of the given info.");
14426 char actionid[128];
14430 actionid[0] =
'\0';
14432 snprintf(actionid,
sizeof(actionid),
"ActionID: %s\r\n",
id);
14438 astman_send_ack(s, m,
"There are no voicemail users currently defined.");
14467 char actionid[128];
14478 actionid[0] =
'\0';
14480 snprintf(actionid,
sizeof(actionid),
"ActionID: %s\r\n",
id);
14484 memset(&svm, 0,
sizeof(svm));
14488 astman_send_ack(s, m,
"There is no voicemail user matching the given user.");
14668 if (!
str->used ||
str->str[
str->used - 1] !=
'\r') {
14702 ast_log(
LOG_ERROR,
"Config file users.conf is in an invalid format. Avoiding.\n");
14717 ast_log(
LOG_ERROR,
"Config file users.conf is in an invalid format. Avoiding.\n");
14735#ifdef TEST_FRAMEWORK
14747 size_t from_len = strlen(
alias) + 1;
14748 size_t to_len = strlen(
mailbox) + 1;
14750 mapping =
ao2_alloc(
sizeof(*mapping) + from_len + to_len,
NULL);
14790 char storage[strlen(
var->value) + 1];
14797 strcpy(storage,
var->value);
14822 if (strcasecmp(cat,
"general") == 0
14824 || strcasecmp(cat,
"zonemessages") == 0) {
14841 char *q, *stringp, *
tmp;
14843 unsigned int tmpadsi[4];
14845 long tps_queue_low;
14846 long tps_queue_high;
14902 strcpy(odbc_database,
"asterisk");
14907 strcpy(odbc_table,
"voicemessages");
14911 odbc_table_len = strlen(odbc_table);
14947 if (sscanf(
val,
"%30d", &x) == 1)
15016 expungeonhangup = 0;
15018 expungeonhangup = 1;
15020 expungeonhangup = 1;
15047 imap_poll_logout = 0;
15055 mail_parameters(NIL, SET_READTIMEOUT, (
void *) (atol(
val)));
15057 mail_parameters(NIL, SET_READTIMEOUT, (
void *) 60L);
15061 mail_parameters(NIL, SET_WRITETIMEOUT, (
void *) (atol(
val)));
15063 mail_parameters(NIL, SET_WRITETIMEOUT, (
void *) 60L);
15067 mail_parameters(NIL, SET_OPENTIMEOUT, (
void *) (atol(
val)));
15069 mail_parameters(NIL, SET_OPENTIMEOUT, (
void *) 60L);
15073 mail_parameters(NIL, SET_CLOSETIMEOUT, (
void *) (atol(
val)));
15075 mail_parameters(NIL, SET_CLOSETIMEOUT, (
void *) 60L);
15091 ast_debug(1,
"Enabled SMDI voicemail notification\n");
15095 ast_debug(1,
"No SMDI interface set, trying default (/dev/ttyS0)\n");
15099 ast_log(
AST_LOG_ERROR,
"No valid SMDI interface specfied, disabling SMDI voicemail notification\n");
15114 if (sscanf(
val,
"%30d", &x) == 1) {
15120 static int maxmessage_deprecate = 0;
15121 if (maxmessage_deprecate == 0) {
15122 maxmessage_deprecate = 1;
15125 if (sscanf(
val,
"%30d", &x) == 1) {
15134 if (sscanf(
val,
"%30d", &x) == 1) {
15143 static int maxmessage_deprecate = 0;
15144 if (maxmessage_deprecate == 0) {
15145 maxmessage_deprecate = 1;
15148 if (sscanf(
val,
"%30d", &x) == 1) {
15165 ast_log(
LOG_ERROR,
"Error processing format string, defaulting to format 'wav'\n");
15173 if (sscanf(
val,
"%30d", &x) == 1) {
15181 if (sscanf(
val,
"%30d", &x) == 1) {
15190 if (sscanf(
val,
"%30d", &x) == 1) {
15199 if (sscanf(
val,
"%30d", &x) == 1) {
15217 ast_debug(1,
"VM_CID Internal context string: %s\n",
val);
15221 q =
strsep(&stringp,
",");
15222 while ((*q ==
' ')||(*q ==
'\t'))
15232 ast_debug(1,
"VM Review Option disabled globally\n");
15240 ast_debug(1,
"VM leave urgent messages disabled globally\n");
15247 ast_debug(1,
"VM Temporary Greeting Reminder Option disabled globally\n");
15250 ast_debug(1,
"VM Temporary Greeting Reminder Option enabled globally\n");
15254 ast_debug(1,
"VM next message wrap disabled globally\n");
15260 ast_debug(1,
"VM Operator break disabled globally\n");
15266 ast_debug(1,
"VM CID Info before msg disabled globally\n");
15272 ast_debug(1,
"Send Voicemail msg disabled globally\n");
15278 ast_debug(1,
"ENVELOPE before msg enabled globally\n");
15284 ast_debug(1,
"Move Heard enabled globally\n");
15290 ast_debug(1,
"Autoset of Urgent flag on forwarded Urgent messages disabled globally\n");
15296 ast_debug(1,
"Duration info before msg enabled globally\n");
15303 if (sscanf(
val,
"%30d", &x) == 1) {
15311 ast_debug(1,
"We are not going to skip to the next msg after save/delete\n");
15377 val =
"voicemail.conf";
15379 if (!(strcmp(
val,
"spooldir"))) {
15399 strcpy(
charset,
"ISO-8859-1");
15425 sscanf(
val,
"%2x%2x%2x%2x", &tmpadsi[0], &tmpadsi[1], &tmpadsi[2], &tmpadsi[3]);
15426 for (x = 0; x < 4; x++) {
15427 memcpy(&
adsifdn[x], &tmpadsi[x], 1);
15431 sscanf(
val,
"%2x%2x%2x%2x", &tmpadsi[0], &tmpadsi[1], &tmpadsi[2], &tmpadsi[3]);
15432 for (x = 0; x < 4; x++) {
15433 memcpy(&
adsisec[x], &tmpadsi[x], 1);
15462 if (sscanf(
val,
"%30ld", &tps_queue_high) != 1 || tps_queue_high <= 0) {
15467 tps_queue_low = -1;
15469 if (sscanf(
val,
"%30ld", &tps_queue_low) != 1 ||
15470 tps_queue_low < -1 || tps_queue_high < tps_queue_low) {
15472 tps_queue_low = -1;
15482 if (!strcasecmp(cat,
"general")) {
15495 switch (
current->passwordlocation) {
15536 ast_debug(2,
"About to try retrieving name file %s\n", dir);
15582 ast_log(
LOG_NOTICE,
"Failed reading voicemail password from %s, using secret from config file\n", secretfn);
15641#ifdef TEST_FRAMEWORK
15656 static const char TEST_CONTEXT[] =
"very_long_unique_context_so_that_nobody_will_ever_have_the_same_one_configured_3141592653";
15664 .
write = fake_write,
15670 info->name =
"vmsayname_exec";
15671 info->category =
"/apps/app_voicemail/";
15672 info->summary =
"Vmsayname unit test";
15673 info->description =
15674 "This tests passing various parameters to vmsayname";
15681 NULL,
NULL, 0, 0,
"TestChannel1"))) {
15682 goto exit_vmsayname_test;
15688 goto exit_vmsayname_test;
15708 goto exit_vmsayname_test;
15713 goto exit_vmsayname_test;
15718 if ((res = symlink(dir, dir2))) {
15720 goto exit_vmsayname_test;
15735exit_vmsayname_test:
15758 struct test_files *
tmp =
ast_alloca(
sizeof(
struct test_files) * 3);
15760 const char origweasels[] =
"tt-weasels";
15761 const char testcontext[] =
"test";
15762 const char testmailbox[] =
"00000000";
15763 const char testspec[] =
"00000000@test";
15765 int new, old, urgent;
15766 const char *folders[3] = {
"Old",
"Urgent",
"INBOX" };
15767 const int folder2mbox[3] = { 1, 11, 0 };
15768 const int expected_results[3][12] = {
15770 { 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0 },
15771 { 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1 },
15772 { 1, 1, 1, 1, 0, 2, 1, 1, 1, 1, 1, 2 },
15777 info->name =
"test_voicemail_msgcount";
15778 info->category =
"/apps/app_voicemail/";
15779 info->summary =
"Test Voicemail status checks";
15780 info->description =
15781 "Verify that message counts are correct when retrieved through the public API";
15788 snprintf(syscmd,
sizeof(syscmd),
"rm -rf \"%s%s/%s\"",
VM_SPOOL_DIR, testcontext, testmailbox);
15791 syserr > 0 ? strerror(syserr) :
"unable to fork()");
15802 memset(&svm, 0,
sizeof(svm));
15803 if (!(vmu =
find_user(&svm, testcontext, testmailbox)) &&
15813 memset(&vms, 0,
sizeof(vms));
15816 for (i = 0; i < 3; i++) {
15819 snprintf(
tmp[i].txtfile,
sizeof(
tmp[i].txtfile),
"%s.txt",
tmp[i].
file);
15822 snprintf(syscmd,
sizeof(syscmd),
"cp \"%s/sounds/en/%s.gsm\" \"%s/%s/%s/%s/msg0000.gsm\"",
ast_config_AST_DATA_DIR, origweasels,
15826 syserr > 0 ? strerror(syserr) :
"unable to fork()");
15835 if ((txt = fopen(
tmp[i].txtfile,
"w+"))) {
15836 fprintf(txt,
"; just a stub\n[message]\nflag=%s\n", strcmp(folders[i],
"Urgent") ?
"" :
"Urgent");
15844 STORE(
tmp[i].dir, testmailbox, testcontext, 0, chan, vmu,
"gsm", 600, &vms, strcmp(folders[i],
"Urgent") ?
"" :
"Urgent",
NULL);
15847 for (j = 0; j < 3; j++) {
15856 new = old = urgent = 0;
15860 }
else if (old != expected_results[i][3 + 0] ||
new != expected_results[i][3 + 2]) {
15862 testspec, old, expected_results[i][3 + 0],
new, expected_results[i][3 + 2]);
15866 new = old = urgent = 0;
15870 }
else if (old != expected_results[i][6 + 0] ||
15871 urgent != expected_results[i][6 + 1] ||
15872 new != expected_results[i][6 + 2] ) {
15873 ast_test_status_update(
test,
"inboxcount2(%s) returned old=%d (expected %d), urgent=%d (expected %d), and new=%d (expected %d)\n",
15874 testspec, old, expected_results[i][6 + 0], urgent, expected_results[i][6 + 1],
new, expected_results[i][6 + 2]);
15878 new = old = urgent = 0;
15879 for (j = 0; j < 3; j++) {
15882 testspec, folders[j],
ast_app_messagecount(testspec, folders[j]), expected_results[i][9 + j]);
15888 for (i = 0; i < 3; i++) {
15908 snprintf(syscmd,
sizeof(syscmd),
"rm -rf \"%s%s/%s\"",
VM_SPOOL_DIR, testcontext, testmailbox);
15911 syserr > 0 ? strerror(syserr) :
"unable to fork()");
15922 char testcontext[] =
"test";
15923 char testmailbox[] =
"00000000";
15924 char from[] =
"test@example.net", cidnum[] =
"1234", cidname[] =
"Mark Spencer", format[] =
"gsm";
15925 char attach[256], attach2[256];
15926 char buf[256] =
"";
15934 enum { INT, FLAGVAL, STATIC, STRPTR }
type;
15941 {
"plain jane config", STATIC, vmus.
password, .u.strval =
"1234" },
15942 {
"emailsubject", STRPTR, vmus.
emailsubject, .u.strval =
"Oogly boogly\xf8koogly with what appears to be UTF-8" },
15943 {
"emailbody", STRPTR, vmus.
emailbody, .u.strval =
"This is a test\n\twith multiple\nlines\nwithin\n" },
15944 {
"serveremail", STATIC, vmus.
serveremail, .u.strval =
"\"\xf8Something\xe8that\xd8seems to have UTF-8 chars\" <test@example.net>" },
15945 {
"attachment flag", FLAGVAL, &vmus.
flags, .u.intval =
VM_ATTACH },
15946 {
"attach2", STRPTR, attach2, .u.strval =
"" },
15947 {
"attach", STRPTR, attach, .u.strval =
"" },
15953 info->name =
"test_voicemail_notify_endl";
15954 info->category =
"/apps/app_voicemail/";
15955 info->summary =
"Test Voicemail notification end-of-line";
15956 info->description =
15957 "Verify that notification emails use a consistent end-of-line character";
15966 if (!(vmu =
find_user(&vmus, testcontext, testmailbox)) &&
15972 if (vmu != &vmus && !(vmu =
find_user(&vmus, testcontext, testmailbox))) {
15984 for (which = 0; which <
ARRAY_LEN(test_items); which++) {
15987 if (ftruncate(fileno(
file), 0)) {
15994 if (test_items[which].
type == INT) {
15995 *((
int *) test_items[which].location) = test_items[which].u.intval;
15996 }
else if (test_items[which].
type == FLAGVAL) {
16002 }
else if (test_items[which].
type == STATIC) {
16003 strcpy(test_items[which].location, test_items[which].u.strval);
16004 }
else if (test_items[which].
type == STRPTR) {
16005 test_items[which].location = test_items[which].u.strval;
16008 make_email_file(
file, from, vmu, 0, testcontext, testmailbox,
"INBOX", cidnum, cidname, attach, attach2, format, 999, 1, chan,
NULL, 0,
NULL,
NULL);
16012 (strlen(
buf) > 1 &&
16014 buf[strlen(
buf) - 2] !=
'\r'
16016 buf[strlen(
buf) - 2] ==
'\r'
16019 ||
buf[strlen(
buf) - 1] !=
'\n') {
16042 info->name =
"test_voicemail_load_config";
16043 info->category =
"/apps/app_voicemail/";
16044 info->summary =
"Test loading Voicemail config";
16045 info->description =
16046 "Verify that configuration is loaded consistently. "
16047 "This is to test regressions of ASTERISK-18838 where it was noticed that "
16048 "some options were loaded after the mailboxes were instantiated, causing "
16049 "those options not to be set correctly.";
16059 if (!(
file = fdopen(fd,
"w"))) {
16064 fputs(
"[general]\ncallback=somecontext\nlocale=de_DE.UTF-8\ntz=european\n[test]",
file);
16065 fputs(
"00000001 => 9999,Mr. Test,,,callback=othercontext|locale=nl_NL.UTF-8|tz=central\n",
file);
16066 fputs(
"00000002 => 9999,Mrs. Test\n",
file);
16074 load_config_from_memory(1, cfg,
NULL);
16077#define CHECK(u, attr, value) else if (strcmp(u->attr, value)) { \
16078 ast_test_status_update(test, "mailbox %s should have %s '%s', but has '%s'\n", \
16079 u->mailbox, #attr, value, u->attr); res = AST_TEST_FAIL; break; }
16083 if (!strcmp(vmu->
mailbox,
"00000001")) {
16085 CHECK(vmu, callback,
"othercontext")
16086 CHECK(vmu,
locale, "nl_NL.UTF-8")
16087 CHECK(vmu,
zonetag, "central")
16088 } else
if (!strcmp(vmu->
mailbox, "00000002")) {
16090 CHECK(vmu, callback,
"somecontext")
16091 CHECK(vmu,
locale, "de_DE.UTF-8")
16092 CHECK(vmu,
zonetag, "european")
16111 const char testcontext[] =
"test";
16112 const char testmailbox[] =
"00000000";
16113 const char vminfo_cmd[] =
"VM_INFO";
16114 char vminfo_buf[256], vminfo_args[256];
16117 int test_counter = 0;
16120 char *vminfo_test_args;
16121 char *vminfo_expected;
16125 {
"00000000@test,badparam",
"", -1 },
16126 {
"00000000@test",
"", -1 },
16127 {
"00000000@test,exists",
"1", 0 },
16128 {
"11111111@test,exists",
"0", 0 },
16129 {
"00000000@test,email",
"vm-info-test@example.net", 0 },
16130 {
"11111111@test,email",
"", 0 },
16131 {
"00000000@test,fullname",
"Test Framework Mailbox", 0 },
16132 {
"00000000@test,pager",
"vm-info-pager-test@example.net", 0 },
16133 {
"00000000@test,locale",
"en_US", 0 },
16134 {
"00000000@test,tz",
"central", 0 },
16135 {
"00000000@test,language",
"en", 0 },
16136 {
"00000000@test,password",
"9876", 0 },
16141 info->name =
"test_voicemail_vm_info";
16142 info->category =
"/apps/app_voicemail/";
16143 info->summary =
"VM_INFO unit test";
16144 info->description =
16145 "This tests passing various parameters to VM_INFO";
16178 for (test_counter = 0; test_counter <
ARRAY_LEN(test_items); test_counter++) {
16179 ast_copy_string(vminfo_args, test_items[test_counter].vminfo_test_args,
sizeof(vminfo_args));
16180 test_ret =
acf_vm_info(chan, vminfo_cmd, vminfo_args, vminfo_buf,
sizeof(vminfo_buf));
16181 if (strcmp(vminfo_buf, test_items[test_counter].vminfo_expected)) {
16182 ast_test_status_update(
test,
"VM_INFO respose was: '%s', but expected: '%s'\n", vminfo_buf, test_items[test_counter].vminfo_expected);
16185 if (!(test_ret == test_items[test_counter].vminfo_ret)) {
16186 ast_test_status_update(
test,
"VM_INFO return code was: '%i', but expected '%i'\n", test_ret, test_items[test_counter].vminfo_ret);
16244#ifdef TEST_FRAMEWORK
16255#ifdef TEST_FRAMEWORK
16256 ast_uninstall_vm_test_functions();
16287 prnt(where,
"Alias: %s Mailbox: %s", mapping->
alias, mapping->
mailbox);
16317 alias_mailbox_mapping_hash_fn,
NULL, alias_mailbox_mapping_cmp_fn);
16319 ast_log(
LOG_ERROR,
"Unable to create alias_mailbox_mappings container\n");
16325 ast_log(
LOG_ERROR,
"Unable to register alias_mailbox_mappings container\n");
16332 mailbox_alias_mapping_hash_fn,
NULL, mailbox_alias_mapping_cmp_fn);
16334 ast_log(
LOG_ERROR,
"Unable to create mailbox_alias_mappings container\n");
16342 ast_log(
LOG_ERROR,
"Unable to register mailbox_alias_mappings container\n");
16375#ifdef TEST_FRAMEWORK
16385 ast_log(
LOG_ERROR,
"Failure registering applications, functions or tests\n");
16408#ifdef TEST_FRAMEWORK
16409 ast_install_vm_test_functions(vm_test_create_user, vm_test_destroy_user);
16421 char destination[80] =
"";
16425 ast_verb(3,
"Destination number will be entered manually\n");
16426 while (retries < 3 && cmd !=
't') {
16427 destination[1] =
'\0';
16436 destination[0] = cmd;
16445 ast_verb(3,
"User hit '*' to cancel outgoing call\n");
16448 if ((cmd =
ast_readstring(chan, destination + strlen(destination),
sizeof(destination) - 1, 6000, 10000,
"#")) < 0)
16454 isprint(cmd) ? cmd :
'?', isprint(cmd) ? cmd :
'?');
16456 if (retries >= 3) {
16461 ast_verb(3,
"Destination number is CID number '%s'\n", num);
16466 if (destination[strlen(destination) -1 ] ==
'*')
16468 ast_verb(3,
"Placing outgoing call to extension '%s' in context '%s' from context '%s'\n", destination, outgoing_context,
ast_channel_context(chan));
16495 const char *origtime, *
context;
16506 snprintf(filename,
sizeof(filename),
"%s.txt", vms->
fn);
16541 while ((res > -1) && (res !=
't')) {
16565 ast_verb(3,
"Caller can not specify callback number - no dialout context available\n");
16587 ast_verb(3,
"Confirm CID number '%s' is number to use for callback\n", num);
16618 isprint(res) ? res :
'?', isprint(res) ? res :
'?');
16624 else if (res ==
'*')
16636 ast_verb(3,
"No CID number available, no reply sent\n");
16643 memset(&vmu2, 0,
sizeof(vmu2));
16650 ast_verb(3,
"Leaving voicemail for '%s' in context '%s'\n", num, vmu->
context);
16652 memset(&leave_options, 0,
sizeof(leave_options));
16663 ast_verb(3,
"No mailbox number '%s' in context '%s', no reply sent\n", num, vmu->
context);
16677#ifndef IMAP_STORAGE
16680 vms->
heard[msg] = 1;
16688 int outsidecaller,
struct ast_vm_user *vmu,
int *duration,
int *sound_duration,
const char *unlockdir,
16694 int max_attempts = 3;
16697 int msg_exists = 0;
16698 signed char zero_gain = 0;
16700 char *acceptdtmf =
"#";
16701 char *canceldtmf =
"";
16702 int canceleddtmf = 0;
16703 SCOPE_ENTER(3,
"%s: rf: %s fmt: %s type: %s vmu: %s\n",
16704 ast_channel_name(chan), recordfile, fmt, outsidecaller ?
"msg" :
"greeting",
16709 if (duration ==
NULL) {
16713 if (!outsidecaller)
16714 snprintf(tempfile,
sizeof(tempfile),
"%s.tmp", recordfile);
16720 while ((cmd >= 0) && (cmd !=
't')) {
16729 ast_verb(3,
"Saving message as is\n");
16730 if (!outsidecaller) {
16731 ast_trace(-1,
"Renaming greeting '%s' to '%s'\n", tempfile, recordfile);
16734 if (!forwardintro) {
16737 if (!outsidecaller) {
16739 ast_trace(-1,
"Saving greeting '%s'\n", recordfile);
16740 SCOPE_CALL(-1,
STORE, recordfile, vmu->
mailbox, vmu->
context, -1, chan, vmu, fmt, *duration, vms,
flag, msg_id);
16748 ast_verb(3,
"Reviewing the message\n");
16749 ast_trace(-1,
"Reviewing '%s'\n", tempfile);
16756 ast_verb(3,
"Re-recording the message\n");
16758 ast_verb(3,
"Recording the message\n");
16760 if (recorded && outsidecaller) {
16761 if (forwardintro) {
16771 SCOPE_EXIT_RTN_VALUE(cmd,
"User hung up before message could be rerecorded. Deleted '%s'\n", tempfile);
16779 ast_trace(-1,
"Recording '%s'\n", tempfile);
16780 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);
16781 if (strchr(canceldtmf, cmd)) {
16789 if (!outsidecaller) {
16794 outsidecaller ?
"Saved message " :
"Deleted greeting \n", tempfile);
16798 }
else if (cmd ==
'*') {
16801 }
else if (vmu->review && sound_duration && (*sound_duration < 5)) {
16803 ast_verb(3,
"Message too short\n");
16807 }
else if (vmu->review && (cmd == 2 && sound_duration && *sound_duration < (
maxsilence + 3))) {
16809 ast_verb(3,
"Nothing recorded\n");
16826 ast_verb(3,
"marking message as Urgent\n");
16828 strcpy(
flag,
"Urgent");
16830 ast_verb(3,
"UNmarking message as Urgent\n");
16857 if (outsidecaller) {
16869 if (msg_exists || recorded) {
16870 ast_trace(-1,
"Reviewing '%s'\n", tempfile);
16875 ast_trace(-1,
"Saving '%s' to '%s'\n", tempfile, recordfile);
16879 }
else if (cmd ==
'4') {
16882 strcpy(
flag,
"Urgent");
16887 ast_trace(-1,
"Deleting '%s'\n", tempfile);
16931 if (attempts > max_attempts) {
16936 if (!outsidecaller && (cmd == -1 || cmd ==
't')) {
16938 ast_trace(-1,
"Deleting '%s' on hangup or timeout\n", tempfile);
16942 if (cmd !=
't' && outsidecaller)
16952 if (!(msg_snapshot =
ast_calloc(1,
sizeof(*msg_snapshot)))) {
16961 return msg_snapshot;
16972#ifdef TEST_FRAMEWORK
16974static int vm_test_destroy_user(
const char *
context,
const char *
mailbox)
16992static int vm_test_create_user(
const char *
context,
const char *
mailbox)
17019 int snapshot_index,
17035 snprintf(filename,
sizeof(filename),
"%s.txt", vms->
fn);
17059 filename,
id,
sizeof(
id), vmu, mailbox_index))) {
17090 switch (sort_val) {
17103 if (descending &&
val >= 0) {
17107 }
else if (!descending &&
val <= 0) {
17133 const char *folder,
17136 int combine_INBOX_and_OLD)
17143 int this_index_only = -1;
17150 ast_log(
LOG_WARNING,
"Cannot create a mailbox snapshot since no mailbox was specified\n");
17154 memset(&vmus, 0,
sizeof(vmus));
17160 this_index_only = i;
17164 if (this_index_only == -1) {
17175 if (!(mailbox_snapshot =
ast_calloc(1,
sizeof(*mailbox_snapshot)))) {
17189 for (i = 0; i < mailbox_snapshot->
folders; i++) {
17190 int msg_folder_index = i;
17197 if (!(this_index_only == -1 || this_index_only == i || (this_index_only == inbox_index && combine_INBOX_and_OLD && (i == old_index || i == urgent_index)))) {
17202 if (combine_INBOX_and_OLD && (i == old_index || i == urgent_index)) {
17203 msg_folder_index = inbox_index;
17206 memset(&vms, 0,
sizeof(vms));
17214 goto snapshot_cleanup;
17222 goto snapshot_cleanup;
17228 goto snapshot_cleanup;
17240 vmstate_delete(&vms);
17245 return mailbox_snapshot;
17253 for (i = 0; i < mailbox_snapshot->
folders; i++) {
17286 for (i = 0; i < num_msgs; ++i) {
17287 const char *
msg_id = msg_ids[i];
17290 const char *other_msg_id;
17296 snprintf(filename,
sizeof(filename),
"%s.txt", vms->
fn);
17307 if (!
ast_strlen_zero(other_msg_id) && !strcmp(other_msg_id, msg_id)) {
17312 msg_nums[i] = vms->
curmsg;
17333 int new = 0, old = 0, urgent = 0;
17334 char ext_context[1024];
17336 snprintf(ext_context,
sizeof(ext_context),
"%s@%s", vmu->
mailbox, vmu->
context);
17343 const char *from_context,
17344 const char *from_folder,
17345 const char *to_mailbox,
17346 const char *to_context,
17347 const char *to_folder,
17349 const char *msg_ids [],
17358 int from_folder_index;
17365 ast_log(
LOG_WARNING,
"Cannot forward message because either the from or to mailbox was not specified\n");
17370 ast_log(
LOG_WARNING,
"Invalid number of messages specified to forward: %zu\n", num_msgs);
17375 ast_log(
LOG_WARNING,
"Cannot forward message because the from_folder or to_folder was not specified\n");
17379 memset(&vmus, 0,
sizeof(vmus));
17380 memset(&to_vmus, 0,
sizeof(to_vmus));
17381 memset(&from_vms, 0,
sizeof(from_vms));
17384 if (from_folder_index == -1) {
17397 if (!(to_vmu =
find_user(&to_vmus, to_context, to_mailbox))) {
17398 ast_log(
LOG_WARNING,
"Can't find voicemail user to forward to (%s@%s)\n", to_mailbox, to_context);
17408 if ((res =
open_mailbox(&from_vms, vmu, from_folder_index)) < 0) {
17411 goto vm_forward_cleanup;
17416 if ((from_vms.
lastmsg + 1) < num_msgs) {
17417 ast_log(
LOG_WARNING,
"Folder %s has less than %zu messages\n", from_folder, num_msgs);
17419 goto vm_forward_cleanup;
17422 msg_nums =
ast_alloca(
sizeof(
int) * num_msgs);
17425 goto vm_forward_cleanup;
17429 for (i = 0; i < num_msgs; i++) {
17430 int cur_msg = msg_nums[i];
17435 snprintf(filename,
sizeof(filename),
"%s.txt", from_vms.
fn);
17447 duration = atoi(
value);
17453 from_vms.
deleted[cur_msg] = 1;
17462 goto vm_forward_cleanup;
17472 vmstate_delete(&from_vms);
17488 const char *oldfolder,
17489 const char *old_msg_ids [],
17490 const char *newfolder)
17494 int old_folder_index;
17495 int new_folder_index;
17507 ast_log(
LOG_WARNING,
"Invalid number of messages specified to move: %zu\n", num_msgs);
17512 ast_log(
LOG_WARNING,
"Cannot move message because either oldfolder or newfolder was not specified\n");
17519 memset(&vmus, 0,
sizeof(vmus));
17520 memset(&vms, 0,
sizeof(vms));
17522 if (old_folder_index == -1 || new_folder_index == -1) {
17535 if ((res =
open_mailbox(&vms, vmu, old_folder_index)) < 0) {
17538 goto vm_move_cleanup;
17543 if ((vms.
lastmsg + 1) < num_msgs) {
17544 ast_log(
LOG_WARNING,
"Folder %s has less than %zu messages\n", oldfolder, num_msgs);
17546 goto vm_move_cleanup;
17549 old_msg_nums =
ast_alloca(
sizeof(
int) * num_msgs);
17552 goto vm_move_cleanup;
17556 for (i = 0; i < num_msgs; ++i) {
17559 goto vm_move_cleanup;
17561 vms.
deleted[old_msg_nums[i]] = 1;
17567 goto vm_move_cleanup;
17577 vmstate_delete(&vms);
17592 const char *folder,
17593 const char *msgs[])
17609 ast_log(
LOG_WARNING,
"Invalid number of messages specified to remove: %zu\n", num_msgs);
17618 memset(&vmus, 0,
sizeof(vmus));
17619 memset(&vms, 0,
sizeof(vms));
17622 if (folder_index == -1) {
17637 if ((res =
open_mailbox(&vms, vmu, folder_index)) < 0) {
17640 goto vm_remove_cleanup;
17645 if ((vms.
lastmsg + 1) < num_msgs) {
17648 goto vm_remove_cleanup;
17651 msg_nums =
ast_alloca(
sizeof(
int) * num_msgs);
17654 goto vm_remove_cleanup;
17657 for (i = 0; i < num_msgs; i++) {
17658 vms.
deleted[msg_nums[i]] = 1;
17665 goto vm_remove_cleanup;
17675 vmstate_delete(&vms);
17690 const char *folder,
17691 const char *msg_id,
17716 ast_log(
LOG_WARNING,
"Cannot play message because no message number was specified\n");
17720 memset(&vmus, 0,
sizeof(vmus));
17721 memset(&vms, 0,
sizeof(vms));
17736 goto play2_msg_cleanup;
17742 goto play2_msg_cleanup;
17747 snprintf(filename,
sizeof(filename),
"%s.txt", vms.
fn);
17754 goto play2_msg_cleanup;
17757 duration = atoi(
value);
17770 cb(chan, vms.
fn, duration);
17771 }
else if ((
wait_file(chan, &vms, vms.
fn)) < 0) {
17789 vmstate_delete(&vms);
17810 .optional_modules =
"res_adsi,res_smdi",
ADSI Support (built upon Caller*ID)
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_adsi_load_soft_key(unsigned char *buf, int key, const char *llabel, const char *slabel, char *ret, int data)
Creates "load soft key" parameters.
#define ADSI_MSG_DOWNLOAD
int ast_adsi_data_mode(unsigned char *buf)
Puts CPE in data mode.
int ast_adsi_unload_session(struct ast_channel *chan)
int ast_adsi_begin_download(struct ast_channel *chan, char *service, unsigned char *fdn, unsigned char *sec, int version)
int ast_adsi_set_line(unsigned char *buf, int page, int line)
Sets the current line and page.
int ast_adsi_input_control(unsigned char *buf, int page, int line, int display, int format, int just)
Set input information.
int ast_adsi_input_format(unsigned char *buf, int num, int dir, int wrap, char *format1, char *format2)
Set input format.
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,...
int ast_adsi_end_download(struct ast_channel *chan)
int ast_adsi_download_disconnect(unsigned char *buf)
Disconnects (and hopefully saves) a downloaded script.
int ast_adsi_available(struct ast_channel *chan)
Returns non-zero if Channel does or might support ADSI.
int ast_adsi_transmit_message(struct ast_channel *chan, unsigned char *msg, int msglen, int msgtype)
#define ADSI_DIR_FROM_LEFT
int ast_adsi_set_keys(unsigned char *buf, unsigned char *keys)
Set which soft keys should be displayed.
int ast_adsi_voice_mode(unsigned char *buf, int when)
Puts CPE in voice mode.
struct sla_ringing_trunk * last
#define VMBOX_STRING_DATA_FORMAT
static char * vm_check_password_shell(char *command, char *buf, size_t len)
static int vm_browse_messages_vi(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
Vietnamese syntax for 'You have N messages' greeting.
static int save_to_folder(struct ast_vm_user *vmu, struct vm_state *vms, int msg, int box, int *newmsg, int move)
static char pagerfromstring[100]
static char vm_password[80]
static char vm_invalid_password[80]
#define VM_ODBC_AUDIO_ON_DISK
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_en(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
Default English syntax for 'You have N messages' greeting.
static char listen_control_reverse_key[12]
#define MAX_VM_CONTEXT_LEN
#define EXISTS(a, b, c, d)
static int vm_intro_pl(struct ast_channel *chan, struct vm_state *vms)
static void adsi_password(struct ast_channel *chan)
static char serveremail[80]
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
#define VMSTATE_MAX_MSG_ARRAY
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.
static void adsi_folders(struct ast_channel *chan, int start, char *label)
static int close_mailbox(struct vm_state *vms, struct ast_vm_user *vmu)
static int mwi_handle_unsubscribe2(void *data)
#define VOICEMAIL_DIR_MODE
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...
static int manager_voicemail_refresh(struct mansession *s, const struct message *m)
static int inprocess_hash_fn(const void *obj, const int flags)
static struct ast_custom_function vm_info_acf
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 ...
static int show_messages_for_mailbox(struct ast_cli_args *a)
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)
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.
static int manager_list_voicemail_users(struct mansession *s, const struct message *m)
Manager list voicemail users command.
#define DEFAULT_LISTEN_CONTROL_FORWARD_KEY
static int vm_delete(char *file)
Removes the voicemail sound and information file.
static int wait_file2(struct ast_channel *chan, struct vm_state *vms, char *file)
static int msg_id_incrementor
static const struct ast_vm_functions vm_table
static void free_zone(struct vm_zone *z)
static void adsi_begin(struct ast_channel *chan, int *useadsi)
static char * handle_voicemail_show_mailbox(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static void read_password_from_file(const char *secretfn, char *password, int passwordlen)
static int say_and_wait(struct ast_channel *chan, int num, const char *language)
static void apply_options_full(struct ast_vm_user *retval, struct ast_variable *var)
Loads the options specific to a voicemail user.
static void populate_defaults(struct ast_vm_user *vmu)
Sets default voicemail system options to a voicemail user.
static struct ast_taskprocessor * mwi_subscription_tps
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 char vm_newpassword[80]
static int vm_intro_he(struct ast_channel *chan, struct vm_state *vms)
static int vm_execmain(struct ast_channel *chan, const char *data)
static void free_user(struct ast_vm_user *vmu)
AO2_STRING_FIELD_CMP_FN(alias_mailbox_mapping, alias)
static int vm_play_folder_name_gr(struct ast_channel *chan, char *box)
static int vm_instructions_zh(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int skipadvanced, int in_urgent, int nodelete)
static int invent_message(struct ast_channel *chan, char *context, char *ext, int busy, char *ecodes)
static int vm_instructions(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int skipadvanced, int in_urgent, int nodelete)
#define UPDATE_MSG_ID(a, b, c, d, e, f)
static int vm_instructions_en(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int skipadvanced, int in_urgent, int nodelete)
#define VM_STRING_HEADER_FORMAT
static void generate_msg_id(char *dst)
Sets the destination string to a uniquely identifying msg_id string.
static struct ast_flags globalflags
static char listen_control_forward_key[12]
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)
static int vmauthenticate(struct ast_channel *chan, const char *data)
static int play_message_duration(struct ast_channel *chan, struct vm_state *vms, const char *duration, int minduration)
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 char vm_newuser[80]
#define VMBOX_STRING_HEADER_FORMAT
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 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 ast_mutex_t poll_lock
static int check_mime(const char *str)
Check if the string would need encoding within the MIME standard, to avoid confusing certain mail sof...
static const char * vm_index_to_foldername(int id)
static unsigned char adsisec[4]
static int play_message_category(struct ast_channel *chan, const char *category)
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 const char * substitute_escapes(const char *value)
static int change_password_realtime(struct ast_vm_user *vmu, const char *password)
Performs a change of the voicemail passowrd in the realtime engine.
static int reset_user_pw(const char *context, const char *mailbox, const char *newpass)
Resets a user password to a specified password.
static int count_messages(struct ast_vm_user *vmu, char *dir)
Find all .txt files - even if they are not in sequence from 0000.
static pthread_t poll_thread
static int vm_intro_multilang(struct ast_channel *chan, struct vm_state *vms, const char message_gender[])
static int vm_exec(struct ast_channel *chan, const char *data)
static struct ast_vm_msg_snapshot * vm_msg_snapshot_alloc(void)
static char * pagersubject
static int manager_voicemail_forward(struct mansession *s, const struct message *m)
static int manager_voicemail_move(struct mansession *s, const struct message *m)
#define COPY(a, b, c, d, e, f, g, h)
static void load_zonemessages(struct ast_config *cfg)
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(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms)
static int vm_playmsgexec(struct ast_channel *chan, const char *data)
static int vm_intro_de(struct ast_channel *chan, struct vm_state *vms)
static int passwordlocation
static int get_folder_ja(struct ast_channel *chan, int start)
static char vm_mismatch[80]
static void adsi_delete(struct ast_channel *chan, struct vm_state *vms)
static const struct ast_app_option vm_app_options[128]
static char * voicemail_app
static char * playmsg_app
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.
static void notify_new_state(struct ast_vm_user *vmu)
static void adsi_message(struct ast_channel *chan, struct vm_state *vms)
#define ASTERISK_USERNAME
static int vm_newuser_setup(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain)
static int valid_config(const struct ast_config *cfg)
Check if configuration file is valid.
static char vm_pls_try_again[80]
static int play_message_callerid(struct ast_channel *chan, struct vm_state *vms, char *cid, const char *context, int callback, int saycidnumber)
static int write_password_to_file(const char *secretfn, const char *password)
static int wait_file(struct ast_channel *chan, struct vm_state *vms, char *file)
static int append_vmbox_info_astman(struct mansession *s, const struct message *m, struct ast_vm_user *vmu, const char *event_name, const char *actionid)
Append vmbox info string into given astman with event_name.
static int msg_create_from_file(struct ast_vm_recording_data *recdata)
static char * complete_voicemail_show_mailbox(struct ast_cli_args *a)
static const struct ast_vm_greeter_functions vm_greeter_table
static void rename_file(char *sfn, char *dfn)
Renames a message in a mailbox folder.
static int move_message_from_mailbox(struct ast_cli_args *a)
static struct alias_mailbox_mapping * alias_mailbox_mapping_create(const char *alias, const char *mailbox)
static struct ast_vm_mailbox_snapshot * vm_mailbox_snapshot_destroy(struct ast_vm_mailbox_snapshot *mailbox_snapshot)
struct ast_mwi_observer mwi_observer
static char ext_pass_check_cmd[128]
static int vm_intro_pt_BR(struct ast_channel *chan, struct vm_state *vms)
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 int separate_mailbox(char *mailbox_id, char **mailbox, char **context)
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.
static char dialcontext[AST_MAX_CONTEXT]
static int vmsayname_exec(struct ast_channel *chan, const char *data)
#define DEFAULT_POLL_FREQ
static int vm_intro_vi(struct ast_channel *chan, struct vm_state *vms)
static int messagecount(const char *mailbox_id, const char *folder)
static int manager_voicemail_remove(struct mansession *s, const struct message *m)
static void stop_poll_thread(void)
AO2_STRING_FIELD_HASH_FN(alias_mailbox_mapping, alias)
static char aliasescontext[MAX_VM_CONTEXT_LEN]
static int vm_sayname(struct ast_channel *chan, const char *mailbox_id)
#define DELETE(a, b, c, d)
static void print_mappings(void *v_obj, void *where, ao2_prnt_fn *prnt)
static struct ast_cli_entry cli_voicemail[]
#define DEFAULT_LISTEN_CONTROL_RESTART_KEY
static char listen_control_stop_key[12]
static char fromstring[100]
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.
#define PWDCHANGE_INTERNAL
static char * handle_voicemail_forward_message(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int vm_intro_cs(struct ast_channel *chan, struct vm_state *vms)
static void mwi_handle_unsubscribe(const char *id, struct ast_mwi_subscriber *sub)
static int adsi_load_vmail(struct ast_channel *chan, int *useadsi)
static void vm_change_password(struct ast_vm_user *vmu, const char *newpassword)
The handler for the change password option.
static void * mb_poll_thread(void *data)
static char cidinternalcontexts[MAX_NUM_CID_CONTEXTS][64]
static void run_externnotify(const char *context, const char *extension, const char *flag)
static int append_mailbox(const char *context, const char *box, const char *data)
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...
static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms)
static int vm_intro_nl(struct ast_channel *chan, struct vm_state *vms)
static void adsi_status(struct ast_channel *chan, struct vm_state *vms)
#define DEFAULT_LISTEN_CONTROL_STOP_KEY
static int acf_vm_info(struct ast_channel *chan, const char *cmd, char *args, char *buf, size_t len)
static int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu, int box)
static int vm_intro_zh(struct ast_channel *chan, struct vm_state *vms)
static char emaildateformat[32]
static char vm_reenterpassword[80]
static void adsi_login(struct ast_channel *chan)
static int manager_get_mailbox_summary(struct mansession *s, const struct message *m)
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 MAX_VM_MAILBOX_LEN
static int __has_voicemail(const char *context, const char *mailbox, const char *folder, int shortcircuit)
static int vm_intro_pt(struct ast_channel *chan, struct vm_state *vms)
static int check_password(struct ast_vm_user *vmu, char *password)
Check that password meets minimum required length.
static int play_message_by_id_helper(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, const char *msg_id)
static int load_config_force(int reload, int force)
Reload voicemail.conf.
static int saydurationminfo
struct ao2_container * inprocess_container
static int vm_allocate_dh(struct vm_state *vms, struct ast_vm_user *vmu, int count_msg)
static void prep_email_sub_vars(struct ast_channel *ast, struct ast_vm_user *vmu, int msgnum, char *context, char *mailbox, const char *fromfolder, char *cidnum, char *cidname, char *dur, char *date, const char *category, const char *flag)
static char * sayname_app
static void free_user_final(struct ast_vm_user *vmu)
static int vm_instructions_ja(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int skipadvanced, int in_urgent, int nodelete)
static void load_users(struct ast_config *cfg)
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.
static int get_folder2(struct ast_channel *chan, char *fn, int start)
plays a prompt and waits for a keypress.
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 adsi_goodbye(struct ast_channel *chan)
#define HVSU_OUTPUT_FORMAT
static char ext_pass_cmd[128]
static int is_valid_dtmf(const char *key)
Determines if a DTMF key entered is valid.
static char pagerdateformat[32]
static int vm_tempgreeting(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain)
The handler for 'record a temporary greeting'.
static int actual_load_config(int reload, struct ast_config *cfg, struct ast_config *ucfg)
static int get_folder_by_name(const char *name)
#define HVSZ_OUTPUT_FORMAT
static char * emailsubject
static int inprocess_count(const char *context, const char *mailbox, int delta)
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 struct ao2_container * mailbox_alias_mappings
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...
static void apply_options(struct ast_vm_user *vmu, const char *options)
Destructively Parse options and apply.
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)
static char externnotify[160]
static int adsi_logo(unsigned char *buf)
static int play_message_datetime(struct ast_channel *chan, struct ast_vm_user *vmu, const char *origtime, const char *filename)
static unsigned char poll_thread_run
static char listen_control_restart_key[12]
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)
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.
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 MAX_VM_MBOX_ID_LEN
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.
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.
static void copy_plain_file(char *frompath, char *topath)
Copies a voicemail information (envelope) file.
static int vm_forwardoptions(struct ast_channel *chan, struct ast_vm_user *vmu, char *curdir, int curmsg, char *vm_fmts, char *context, signed char record_gain, long *duration, struct vm_state *vms, char *flag)
presents the option to prepend to an existing message when forwarding it.
#define DEFAULT_LISTEN_CONTROL_PAUSE_KEY
#define MAX_NUM_CID_CONTEXTS
static int vm_play_folder_name_pl(struct ast_channel *chan, char *box)
static char * complete_voicemail_show_users(const char *line, const char *word, int pos, int state)
static int inboxcount(const char *mailbox, int *newmsgs, int *oldmsgs)
@ OPT_PWLOC_VOICEMAILCONF
static char vm_prepend_timeout[80]
static char userscontext[AST_MAX_EXTENSION]
static int vm_authenticate(struct ast_channel *chan, char *mailbox, int mailbox_size, struct ast_vm_user *res_vmu, const char *context, const char *prefix, int skipuser, int max_logins, int silent)
#define RETRIEVE(a, b, c, d)
static int inprocess_cmp_fn(void *obj, void *arg, int flags)
static int vm_intro_en(struct ast_channel *chan, struct vm_state *vms)
static char VM_SPOOL_DIR[PATH_MAX]
static int vm_options(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain)
#define SMDI_MWI_WAIT_TIMEOUT
static char callcontext[AST_MAX_CONTEXT]
static void mwi_handle_subscribe(const char *id, struct ast_mwi_subscriber *sub)
static int vm_intro_da(struct ast_channel *chan, struct vm_state *vms)
static void vm_change_password_shell(struct ast_vm_user *vmu, char *newpassword)
static int vm_intro_fr(struct ast_channel *chan, struct vm_state *vms)
static int show_mailbox_snapshot(struct ast_cli_args *a)
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.
static int vm_msg_remove(const char *mailbox, const char *context, size_t num_msgs, const char *folder, const char *msgs[])
static char listen_control_pause_key[12]
static int copy(char *infile, char *outfile)
Utility function to copy a file.
static int silencethreshold
static void start_poll_thread(void)
#define MAX_MAIL_BODY_CONTENT_SIZE
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.
#define RENAME(a, b, c, d, e, f, g, h)
static int load_module(void)
Load the module.
static char * handle_voicemail_move_message(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int vm_browse_messages_he(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
static unsigned int poll_mailboxes
static int poll_subscribed_mailbox(struct ast_mwi_state *mwi_state, void *data)
static int sendpage(char *srcemail, char *pager, int msgnum, char *context, char *mailbox, const char *fromfolder, char *cidnum, char *cidname, int duration, struct ast_vm_user *vmu, const char *category, const char *flag)
static int forward_message_from_mailbox(struct ast_cli_args *a)
#define STORE(a, b, c, d, e, f, g, h, i, j, k)
static int vm_intro_is(struct ast_channel *chan, struct vm_state *vms)
static char * complete_voicemail_move_message(struct ast_cli_args *a, int maxpos)
static char * handle_voicemail_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Reload voicemail configuration from the CLI.
static unsigned int poll_freq
static int resequence_mailbox(struct ast_vm_user *vmu, char *dir, int stopcount)
static int last_message_index(char *dir)
Determines the highest message number in use for a given user and mailbox folder.
static ast_cond_t poll_cond
static void adsi_status2(struct ast_channel *chan, struct vm_state *vms)
static int unload_module(void)
static int load_config(int reload)
static void free_vm_zones(void)
Free the zones structure.
static int mwi_handle_subscribe2(void *data)
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.
static int vm_intro_es(struct ast_channel *chan, struct vm_state *vms)
#define PWDCHANGE_EXTERNAL
static struct ast_vm_user * find_or_create(const char *context, const char *box)
static unsigned char adsifdn[4]
static void queue_mwi_event(const char *channel_id, const char *box, int urgent, int new, int old)
static int manager_status_voicemail_user(struct mansession *s, const struct message *m)
#define VOICEMAIL_FILE_MODE
static char * handle_voicemail_remove_message(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
#define LAST_MSG_INDEX(a)
static void load_aliases(struct ast_config *cfg)
static struct ao2_container * alias_mailbox_mappings
static int vm_play_folder_name(struct ast_channel *chan, char *mbox)
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.
static int vm_play_folder_name_ua(struct ast_channel *chan, char *box)
#define DEFAULT_LISTEN_CONTROL_REVERSE_KEY
static char * show_users_realtime(int fd, const char *context)
static int remove_message_from_mailbox(struct ast_cli_args *a)
static int has_voicemail(const char *mailbox, const char *folder)
Determines if the given folder has messages.
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 VM_EMAIL_EXT_RECS
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 manager_match_mailbox(struct ast_mwi_state *mwi_state, void *data)
static int vm_intro_ja(struct ast_channel *chan, struct vm_state *vms)
static int inboxcount2(const char *mailbox, int *urgentmsgs, int *newmsgs, int *oldmsgs)
Check the given mailbox's message count.
static char exitcontext[AST_MAX_CONTEXT]
static int dialout(struct ast_channel *chan, struct ast_vm_user *vmu, char *num, char *outgoing_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)
static int sayname(struct ast_channel *chan, const char *mailbox, const char *context)
static int get_date(char *s, int len)
Gets the current date and time, as formatted string.
static const char *const mailbox_folders[]
static int show_mailbox_details(struct ast_cli_args *a)
static const char * mbox(struct ast_vm_user *vmu, int id)
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 char * vmauthenticate_app
static int vm_play_folder_name_ja(struct ast_channel *chan, char *box)
#define force_reload_config()
Forcibly reload voicemail.conf, even if it has not changed. This is necessary after running unit test...
static int vm_intro_se(struct ast_channel *chan, struct vm_state *vms)
static void apply_option(struct ast_vm_user *vmu, const char *var, const char *value)
Sets a specific property value.
static char vm_passchanged[80]
static struct ast_vm_msg_snapshot * vm_msg_snapshot_destroy(struct ast_vm_msg_snapshot *msg_snapshot)
static char * voicemailmain_app
#define ALIASES_OUTPUT_FORMAT
static int vm_intro_it(struct ast_channel *chan, struct vm_state *vms)
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.
static struct ast_smdi_interface * smdi_iface
static int vm_intro_gr(struct ast_channel *chan, struct vm_state *vms)
static void free_vm_users(void)
Free the users structure.
static int vm_intro_no(struct ast_channel *chan, struct vm_state *vms)
static int input(yyscan_t yyscanner)
Asterisk main include file. File version handling, generic pbx functions.
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
#define ast_realloc(p, len)
A wrapper for realloc()
#define ast_strdup(str)
A wrapper for strdup()
#define ast_strdupa(s)
duplicate a string in memory from the stack
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
#define ast_calloc(num, len)
A wrapper for calloc()
#define ast_malloc(len)
A wrapper for malloc()
#define ao2_iterator_next(iter)
#define ao2_link(container, obj)
Add an object to a container.
@ AO2_ALLOC_OPT_LOCK_MUTEX
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container,...
void ao2_container_unregister(const char *name)
Unregister a container for CLI stats and integrity check.
#define ao2_find(container, arg, flags)
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
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.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
@ OBJ_SEARCH_KEY
The arg parameter is a search key, but is not an object.
#define ao2_alloc(data_size, destructor_fn)
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Allocate and initialize a hash container with the desired number of buckets.
void() ao2_prnt_fn(void *where, const char *fmt,...)
Print output.
char * ast_callerid_merge(char *buf, int bufsiz, const char *name, const char *num, const char *unknown)
int ast_callerid_parse(char *instr, char **name, char **location)
Destructively parse inbuf into name and location (or number)
int ast_callerid_split(const char *src, char *name, int namelen, char *num, int numlen)
static SQLHSTMT generic_prepare(struct odbc_obj *obj, void *data)
static char language[MAX_LANGUAGE]
static int transfer(void *data)
General Asterisk PBX channel definitions.
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
const char * ast_channel_name(const struct ast_channel *chan)
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
#define ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag,...)
Create a channel structure.
void ast_channel_nativeformats_set(struct ast_channel *chan, struct ast_format_cap *value)
#define ast_channel_lock(chan)
struct ast_party_redirecting * ast_channel_redirecting(struct ast_channel *chan)
int ast_channel_priority(const struct ast_channel *chan)
const char * ast_channel_uniqueid(const struct ast_channel *chan)
const char * ast_channel_context(const struct ast_channel *chan)
void ast_channel_set_rawreadformat(struct ast_channel *chan, struct ast_format *format)
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
void ast_channel_set_rawwriteformat(struct ast_channel *chan, struct ast_format *format)
void ast_channel_set_readformat(struct ast_channel *chan, struct ast_format *format)
#define ast_channel_unref(c)
Decrease channel reference count.
const char * ast_channel_language(const struct ast_channel *chan)
void ast_channel_context_set(struct ast_channel *chan, const char *value)
#define ast_dummy_channel_alloc()
Create a fake channel structure.
int ast_channel_setoption(struct ast_channel *channel, int option, void *data, int datalen, int block)
Sets an option on a channel.
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
void ast_channel_priority_set(struct ast_channel *chan, int value)
int ast_readstring(struct ast_channel *c, char *s, int len, int timeout, int rtimeout, char *enders)
Reads multiple digits.
int ast_answer(struct ast_channel *chan)
Answer a channel.
void ast_channel_adsicpe_set(struct ast_channel *chan, enum ast_channel_adsicpe value)
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
void ast_channel_tech_set(struct ast_channel *chan, const struct ast_channel_tech *value)
const char * ast_channel_exten(const struct ast_channel *chan)
#define ast_channel_unlock(chan)
#define AST_MAX_EXTENSION
void ast_channel_set_writeformat(struct ast_channel *chan, struct ast_format *format)
void ast_party_caller_init(struct ast_party_caller *init)
Initialize the given caller structure.
ast_channel_state
ast_channel states
Standard Command Line Interface.
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
#define AST_CLI_DEFINE(fn, txt,...)
void ast_cli(int fd, const char *fmt,...)
#define ast_cli_register_multiple(e, len)
Register multiple commands.
static struct progalias aliases[]
Convenient Signal Processing routines.
int ast_dsp_get_threshold_from_settings(enum threshold which)
Get silence threshold from dsp.conf.
static char * config_filename
Generic File Format Support. Should be included by clients of the file handling routines....
off_t ast_tellstream(struct ast_filestream *fs)
Tell where we are in a stream.
int ast_stopstream(struct ast_channel *c)
Stops a stream.
int ast_seekstream(struct ast_filestream *fs, off_t sample_offset, int whence)
Seeks into stream.
int ast_filerename(const char *oldname, const char *newname, const char *fmt)
Renames a file.
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.
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
FILE * ast_file_mkftemp(char *template_name, mode_t mode)
same as mkstemp, but return a FILE
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.
char * ast_format_str_reduce(char *fmts)
int ast_filecopy(const char *oldname, const char *newname, const char *fmt)
Copies a file.
int ast_ratestream(struct ast_filestream *fs)
Return the sample rate of the stream's format.
int ast_closestream(struct ast_filestream *f)
Closes a stream.
int ast_fileexists(const char *filename, const char *fmt, const char *preflang)
Checks for the existence of a given file.
int ast_filedelete(const char *filename, const char *fmt)
Deletes a file.
int ast_waitstream(struct ast_channel *c, const char *breakon)
Waits for a stream to stop or digit to be pressed.
static int exists(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
static struct ast_threadstorage buf2
static struct ast_threadstorage buf1
static int quote(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag)
Send ack in manager transaction to begin a list.
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
void ast_manager_publish_event(const char *type, int class_type, struct ast_json *obj)
Publish an event to AMI.
void astman_send_list_complete_start(struct mansession *s, const struct message *m, const char *event_name, int count)
Start the list complete event.
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
void astman_append(struct mansession *s, const char *fmt,...)
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
#define SCOPE_EXIT_RTN(...)
#define SCOPE_EXIT_RTN_VALUE(__return_value,...)
#define SCOPE_EXIT_LOG_RTN_VALUE(__value, __log_level,...)
#define SCOPE_ENTER(level,...)
#define SCOPE_CALL_WITH_INT_RESULT(level, __funcname,...)
#define SCOPE_CALL(level, __funcname,...)
#define SCOPE_EXIT_LOG_RTN(__log_level,...)
#define ast_trace(level,...)
static char prefix[MAX_PREFIX]
Application convenience functions, designed to give consistent look and feel to Asterisk apps.
#define AST_APP_ARG(name)
Define an application argument.
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...
int ast_app_messagecount(const char *mailbox_id, const char *folder)
Get the number of messages in a given mailbox folder.
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.
void ast_vm_greeter_unregister(const char *module_name)
Unregister the specified voicemail greeter provider.
#define AST_APP_OPTIONS(holder, options...)
Declares an array of options for an application.
enum ast_getdata_result 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.
@ AST_VM_SNAPSHOT_SORT_BY_ID
@ AST_VM_SNAPSHOT_SORT_BY_TIME
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...
enum AST_LOCK_RESULT ast_lock_path(const char *path)
Lock a filesystem path.
#define AST_APP_OPTION_ARG(option, flagno, argno)
Declares an application option that accepts an argument.
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"....
#define VM_GREETER_MODULE_VERSION
int ast_safe_fork(int stop_reaper)
Common routine to safely fork without a chance of a signal handler firing badly in the child.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define VM_MODULE_VERSION
struct ast_vm_mailbox_snapshot * ast_vm_mailbox_snapshot_destroy(struct ast_vm_mailbox_snapshot *mailbox_snapshot)
destroy a snapshot
int ast_safe_system(const char *s)
Safely spawn an OS shell command while closing file descriptors.
void ast_vm_unregister(const char *module_name)
Unregister the specified voicemail provider.
#define ast_vm_register(vm_table)
See __ast_vm_register()
int ast_app_inboxcount(const char *mailboxes, int *newmsgs, int *oldmsgs)
Determine number of new/old messages in a mailbox.
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 AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
void() ast_vm_msg_play_cb(struct ast_channel *chan, const char *playfile, int duration)
Voicemail playback callback function definition.
@ AST_RECORD_IF_EXISTS_OVERWRITE
#define AST_APP_OPTION(option, flagno)
Declares an application option that does not accept an argument.
#define AST_NONSTANDARD_APP_ARGS(args, parse, sep)
Performs the 'nonstandard' argument separation process for an application.
int ast_app_inboxcount2(const char *mailboxes, int *urgentmsgs, int *newmsgs, int *oldmsgs)
Determine number of urgent/new/old messages in a mailbox.
#define ast_vm_greeter_register(vm_table)
See __ast_vm_greeter_register()
struct ast_vm_mailbox_snapshot * ast_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)
Create a snapshot of a mailbox which contains information about every msg.
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.
int ast_unlock_path(const char *path)
Unlock a path.
void ast_close_fds_above_n(int n)
Common routine for child processes, to close all fds prior to exec(2)
char * strsep(char **str, const char *delims)
char * mkdtemp(char *template_s)
char * strcasestr(const char *, const char *)
Configuration File Parser.
#define ast_config_load(filename, flags)
Load a config file.
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
int ast_update2_realtime(const char *family,...) attribute_sentinel
Update realtime configuration.
struct ast_config * ast_config_new(void)
Create a new base configuration structure.
int ast_realtime_require_field(const char *family,...) attribute_sentinel
Inform realtime what fields that may be stored.
struct ast_config * ast_load_realtime_multientry(const char *family,...) attribute_sentinel
Retrieve realtime configuration.
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.
void ast_category_append(struct ast_config *config, struct ast_category *category)
Appends a category to a config.
void ast_variable_append(struct ast_category *category, struct ast_variable *variable)
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.
struct ast_category * ast_category_new(const char *name, const char *in_file, int lineno)
Create a category.
#define ast_variable_new(name, value, filename)
int ast_unload_realtime(const char *family)
Release any resources cached for a realtime family.
#define CONFIG_STATUS_FILEUNCHANGED
#define CONFIG_STATUS_FILEINVALID
int ast_check_realtime(const char *family)
Check if realtime engine is configured for family.
int ast_destroy_realtime(const char *family, const char *keyfield, const char *lookup,...) attribute_sentinel
Destroy realtime configuration.
void ast_category_destroy(struct ast_category *cat)
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
int ast_update_realtime(const char *family, const char *keyfield, const char *lookup,...) attribute_sentinel
Update realtime configuration.
int ast_store_realtime(const char *family,...) attribute_sentinel
Create realtime configuration.
const char * ast_config_option(struct ast_config *cfg, const char *cat, const char *var)
Retrieve a configuration variable within the configuration set.
struct ast_variable * ast_load_realtime(const char *family,...) attribute_sentinel
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
struct ast_category * ast_category_get(const struct ast_config *config, const char *category_name, const char *filter)
Retrieve a category if it exists.
@ CONFIG_FLAG_WITHCOMMENTS
@ CONFIG_FLAG_FILEUNCHANGED
#define AST_OPTION_RXGAIN
struct ast_frame ast_null_frame
Support for logging to various files, console and syslog Configuration in file logger....
#define DEBUG_ATLEAST(level)
#define ast_debug(level,...)
Log a DEBUG message.
#define ast_verb(level,...)
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
#define AST_LIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a list of specified type, statically initialized.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
#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_ENTRY(type)
Declare a forward link structure inside a list entry.
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
#define AST_LIST_INSERT_BEFORE_CURRENT(elm, field)
Inserts a list entry before the current entry during a traversal.
#define AST_LIST_LOCK(head)
Locks a list.
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Custom localtime functions for multiple timezones.
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
int ast_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...
int ast_strftime_locale(char *buf, size_t len, const char *format, const struct ast_tm *tm, const char *locale)
Asterisk locking-related definitions:
#define AST_PTHREADT_NULL
#define ast_cond_timedwait(cond, mutex, time)
#define ast_mutex_init(pmutex)
#define ast_mutex_unlock(a)
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
pthread_cond_t ast_cond_t
#define ast_mutex_destroy(a)
#define ast_mutex_lock(a)
#define AST_MUTEX_DEFINE_STATIC(mutex)
#define ast_cond_signal(cond)
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
#define EVENT_FLAG_REPORTING
#define EVENT_FLAG_SYSTEM
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Asterisk module definitions.
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
@ AST_MODULE_SUPPORT_CORE
#define ASTERISK_GPL_KEY
The text the key() function should return.
int ast_unregister_application(const char *app)
Unregister an application.
@ AST_MODULE_LOAD_SUCCESS
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
#define ast_publish_mwi_state_channel(mailbox, context, new_msgs, old_msgs, channel_id)
Publish a MWI state update associated with some channel.
void ast_mwi_state_callback_all(on_mwi_state handler, void *data)
For each managed mailbox call the given handler.
void ast_mwi_state_callback_subscribed(on_mwi_state handler, void *data)
For each managed mailbox that has a subscriber call the given handler.
int ast_mwi_add_observer(struct ast_mwi_observer *observer)
Add an observer to receive MWI state related events.
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.
void ast_mwi_remove_observer(struct ast_mwi_observer *observer)
Remove an MWI state observer.
struct ast_mwi_state * ast_mwi_subscriber_data(struct ast_mwi_subscriber *sub)
Retrieves the state data object associated with the MWI subscriber.
def from_mailbox(key, val, section, pjsip, nmapped)
Asterisk file paths, configured in asterisk.conf.
const char * ast_config_AST_DATA_DIR
const char * ast_config_AST_SPOOL_DIR
Core PBX routines and definitions.
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
void ast_str_substitute_variables(struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ)
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
int pbx_exec(struct ast_channel *c, struct ast_app *app, const char *data)
Execute an application.
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.
#define ast_custom_function_register(acf)
Register a custom function.
int ast_goto_if_exists(struct ast_channel *chan, const char *context, const char *exten, int priority)
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.
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
struct ast_app * pbx_findapp(const char *app)
Look up an application.
static void * cleanup(void *unused)
static char intro[ADSI_MAX_INTRO][20]
static struct stasis_rest_handlers mailboxes
REST handler for /api-docs/mailboxes.json.
struct stasis_forward * sub
int ast_odbc_prepare(struct odbc_obj *obj, SQLHSTMT *stmt, const char *sql)
Prepares a SQL query on a statement.
void ast_odbc_release_obj(struct odbc_obj *obj)
Releases an ODBC object previously allocated by ast_odbc_request_obj()
struct ast_str * ast_odbc_print_errors(SQLSMALLINT handle_type, SQLHANDLE handle, const char *operation)
Shortcut for printing errors to logs after a failed SQL operation.
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.
SQLRETURN ast_odbc_execute_sql(struct odbc_obj *obj, SQLHSTMT *stmt, const char *sql)
Execute a unprepared SQL query.
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.
#define ast_odbc_request_obj(name, check)
Get a ODBC connection object.
static int debug
Global debug status.
Say numbers and dates (maybe words one day too)
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_say_number(struct ast_channel *chan, int num, const char *ints, const char *lang, const char *options)
says a number
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)
int ast_say_counted_noun(struct ast_channel *chan, int num, const char *noun)
int ast_say_counted_adjective(struct ast_channel *chan, int num, const char *adjective, const char *gender)
int ast_say_digit_str(struct ast_channel *chan, const char *num, const char *ints, const char *lang)
says digits of a string
SMDI support for Asterisk.
struct ast_smdi_interface * ast_smdi_interface_find(const char *iface_name)
Find an SMDI interface with the specified name.
int ast_smdi_mwi_set(struct ast_smdi_interface *iface, const char *mailbox)
Set the MWI indicator for a mailbox.
struct ast_smdi_mwi_message * ast_smdi_mwi_message_wait_station(struct ast_smdi_interface *iface, int timeout, const char *station)
int ast_smdi_mwi_unset(struct ast_smdi_interface *iface, const char *mailbox)
Unset the MWI indicator for a mailbox.
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
String manipulation functions.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
#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_get_time_t(const char *src, time_t *dst, time_t _default, int *consumed)
Parse a time (integer) string.
static force_inline int attribute_pure ast_strlen_zero(const char *s)
int ast_build_string(char **buffer, size_t *space, const char *fmt,...)
Build a string in a buffer, designed to be called repeatedly.
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is "false"....
#define ast_str_alloca(init_len)
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
ast_app: A registered application
Structure to describe a channel "technology", ie a channel driver See for examples:
int(*const write)(struct ast_channel *chan, struct ast_frame *frame)
Write a frame, in standard format (see frame.h)
struct ast_format_cap * capabilities
Main Channel structure associated with a channel.
descriptor for a cli entry.
Data structure associated with a custom dialplan function.
This structure is allocated by file.c in one chunk, together with buf_size and desc_size bytes of mem...
Structure used to handle boolean flags.
Data structure associated with a single frame of data.
Abstract JSON element (object, array, string, int, ...).
Structure for mutex and tracking information.
MWI state event interface.
void(* on_subscribe)(const char *mailbox, struct ast_mwi_subscriber *sub)
Raised when MWI is being subscribed.
The structure that contains MWI state.
const ast_string_field uniqueid
Caller Party information.
struct ast_party_id id
Caller party ID.
struct ast_party_name name
Subscriber name.
struct ast_party_number number
Subscriber phone number.
unsigned char valid
TRUE if the name information is valid/present.
char * str
Subscriber name (Malloced)
unsigned char valid
TRUE if the number information is valid/present.
char * str
Subscriber phone number (Malloced)
An SMDI message waiting indicator message.
char cause[SMDI_MWI_FAIL_CAUSE_LEN+1]
char fwd_st[SMDI_MAX_STATION_NUM_LEN+1]
Support for dynamic strings.
A ast_taskprocessor structure is a singleton by name.
Structure for variables, used for configurations and for channel variables.
Voicemail function table definition.
unsigned int module_version
The version of this function table.
const char * module_name
The name of the module that provides the voicemail functionality.
Voicemail greeter function table definition.
unsigned int module_version
The version of this function table.
const char * module_name
The name of the module that provides the voicemail greeter functionality.
struct ast_vm_mailbox_snapshot::@185 * snapshots
const ast_string_field origtime
struct ast_vm_msg_snapshot::@184 msg
const ast_string_field msg_id
Structure used for ast_copy_recording_to_vm in order to cleanly supply data needed for making the rec...
const ast_string_field recording_file
const ast_string_field call_callerchan
const ast_string_field context
const ast_string_field folder
const ast_string_field call_callerid
const ast_string_field call_context
const ast_string_field recording_ext
const ast_string_field call_extension
const ast_string_field mailbox
char mailbox[MAX_VM_MBOX_ID_LEN]
struct ast_vm_user::@82 list
char context[MAX_VM_CONTEXT_LEN]
char language[MAX_LANGUAGE]
All configuration options for http media cache.
structure to hold extensions
Options for leaving voicemail with the voicemail() application.
In case you didn't read that giant block of text above the mansession_session struct,...
structure to hold users read from users.conf
list of users found in the config file
An API for managing task processing threads that can be shared across modules.
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.
void * ast_taskprocessor_unreference(struct ast_taskprocessor *tps)
Unreference the specified taskprocessor and its reference count will decrement.
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.
#define AST_TASKPROCESSOR_HIGH_WATER_LEVEL
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.
#define AST_TEST_REGISTER(cb)
#define ast_test_status_update(a, b, c...)
#define AST_TEST_UNREGISTER(cb)
#define ast_test_suite_event_notify(s, f,...)
#define AST_TEST_DEFINE(hdr)
Definitions to aid in the use of thread local storage.
#define AST_THREADSTORAGE(name)
Define a thread storage variable.
Time-related functions and macros.
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 ...
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
#define ast_test_flag(p, flag)
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
int ast_file_is_readable(const char *filename)
Test that a file exists and is readable by the effective user.
#define ast_pthread_create(a, b, c, d)
#define ast_set2_flag(p, value, flag)
#define ast_clear_flag(p, flag)
long int ast_random(void)
int ast_mkdir(const char *path, int mode)
Recursively create directory path.
#define ast_set_flag(p, flag)
#define ast_copy_flags(dest, src, flagz)
int ast_base64_encode_file_path(const char *filename, FILE *outputfile, const char *endl)
Performs a base 64 encode algorithm on the contents of a File.