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__)
616static char imapserver[48] =
"localhost";
617static char imapport[8] =
"143";
618static char imapflags[128];
619static char imapfolder[64] =
"INBOX";
620static char imapparentfolder[64];
621static char greetingfolder[64] =
"INBOX";
622static char authuser[32];
623static char authpassword[42];
624static int imapversion = 1;
626static int expungeonhangup = 1;
627static int imapgreetings;
628static int imap_poll_logout;
629static char delimiter;
640static int init_mailstream(
struct vm_state *vms,
int box);
641static void write_file(
char *filename,
char *buffer,
unsigned long len);
642static char *get_header_by_tag(
char *
header,
char *tag,
char *
buf,
size_t len);
643static void vm_imap_delete(
char *file,
int msgnum,
struct ast_vm_user *vmu);
644static char *get_user_by_mailbox(
char *
mailbox,
char *
buf,
size_t len);
645static struct vm_state *get_vm_state_by_imapuser(
const char *
user,
int interactive);
646static struct vm_state *get_vm_state_by_mailbox(
const char *mailbox,
const char *
context,
int interactive);
648static void vmstate_insert(
struct vm_state *vms);
649static void vmstate_delete(
struct vm_state *vms);
650static void set_update(MAILSTREAM * stream);
651static void init_vm_state(
struct vm_state *vms);
652static int save_body(BODY *body,
struct vm_state *vms,
char *section,
char *format,
int is_intro);
653static void get_mailbox_delimiter(
struct vm_state *vms, MAILSTREAM *stream);
654static void mm_parsequota (MAILSTREAM *stream,
unsigned char *msg, QUOTALIST *pquota);
655static void imap_mailbox_name(
char *spec,
size_t len,
struct vm_state *vms,
int box,
int target);
656static 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);
657static 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);
658static void update_messages_by_imapuser(
const char *
user,
unsigned long number);
661static int imap_remove_file (
char *dir,
int msgnum);
662static int imap_retrieve_file (
const char *dir,
const int msgnum,
const char *mailbox,
const char *
context);
663static int imap_delete_old_greeting (
char *dir,
struct vm_state *vms);
664static void check_quota(
struct vm_state *vms,
char *mailbox);
666static void imap_logout(
const char *mailbox_id);
677#define SMDI_MWI_WAIT_TIMEOUT 1000
679#define COMMAND_TIMEOUT 5000
681#define VOICEMAIL_DIR_MODE 0777
682#define VOICEMAIL_FILE_MODE 0666
683#define CHUNKSIZE 65536
685#define VOICEMAIL_CONFIG "voicemail.conf"
686#define ASTERISK_USERNAME "asterisk"
691#define DEFAULT_LISTEN_CONTROL_FORWARD_KEY "#"
692#define DEFAULT_LISTEN_CONTROL_REVERSE_KEY "*"
693#define DEFAULT_LISTEN_CONTROL_PAUSE_KEY "0"
694#define DEFAULT_LISTEN_CONTROL_RESTART_KEY "2"
695#define DEFAULT_LISTEN_CONTROL_STOP_KEY "13456789"
696#define VALID_DTMF "1234567890*#"
700#define SENDMAIL "/usr/sbin/sendmail -t"
701#define INTRO "vm-intro"
703#define MAX_MAIL_BODY_CONTENT_SIZE 134217728L
706#define MAXMSGLIMIT 9999
716#define MAX_DATETIME_FORMAT 512
717#define MAX_NUM_CID_CONTEXTS 10
719#define VM_REVIEW (1 << 0)
720#define VM_OPERATOR (1 << 1)
721#define VM_SAYCID (1 << 2)
722#define VM_SVMAIL (1 << 3)
723#define VM_ENVELOPE (1 << 4)
724#define VM_SAYDURATION (1 << 5)
725#define VM_SKIPAFTERCMD (1 << 6)
726#define VM_FORCENAME (1 << 7)
727#define VM_FORCEGREET (1 << 8)
728#define VM_PBXSKIP (1 << 9)
729#define VM_DIRECTFORWARD (1 << 10)
730#define VM_ATTACH (1 << 11)
731#define VM_DELETE (1 << 12)
732#define VM_ALLOCED (1 << 13)
733#define VM_SEARCH (1 << 14)
734#define VM_TEMPGREETWARN (1 << 15)
735#define VM_MOVEHEARD (1 << 16)
736#define VM_MESSAGEWRAP (1 << 17)
737#define VM_FWDURGAUTO (1 << 18)
738#define VM_EMAIL_EXT_RECS (1 << 19)
739#define VM_MARK_URGENT (1 << 20)
740#define VM_ODBC_AUDIO_ON_DISK (1 << 21)
742#define ERROR_LOCK_PATH -100
743#define ERROR_MAX_MSGS -101
744#define OPERATOR_EXIT 300
746#define MSGFILE_LEN (7)
832#define force_reload_config() load_config_force(1, 1)
932#define MAX_VM_MBOX_ID_LEN (AST_MAX_EXTENSION)
933#define MAX_VM_CONTEXT_LEN (AST_MAX_CONTEXT)
935#define MAX_VM_MAILBOX_LEN (MAX_VM_MBOX_ID_LEN + MAX_VM_CONTEXT_LEN)
970 char imappassword[80];
972 char imapvmshareid[80];
987#define VMSTATE_MAX_MSG_ARRAY 256
1012 unsigned msg_array_max;
1013 MAILSTREAM *mailstream;
1016 char imapfolder[64];
1017 char imapserver[48];
1019 char imapflags[128];
1023 unsigned int quota_limit;
1024 unsigned int quota_usage;
1030static char odbc_database[80] =
"asterisk";
1031static char odbc_table[80] =
"voicemessages";
1032size_t odbc_table_len =
sizeof(odbc_table);
1033#define COUNT(a, b) odbc_count_messages(a,b)
1034#define LAST_MSG_INDEX(a) odbc_last_message_index(a)
1035#define RETRIEVE(a,b,c,d) odbc_retrieve_message(a,b)
1036#define DISPOSE(a,b) odbc_remove_files(a,b)
1037#define STORE(a,b,c,d,e,f,g,h,i,j,k) odbc_store_message(a,b,c,d)
1038#define EXISTS(a,b,c,d) (odbc_message_exists(a,b))
1039#define RENAME(a,b,c,d,e,f,g,h) (odbc_rename_message(a,b,c,d,e,f))
1040#define COPY(a,b,c,d,e,f,g,h) (odbc_copy_message(a,b,c,d,e,f))
1041#define DELETE(a,b,c,d) (odbc_delete_message(a,b))
1042#define UPDATE_MSG_ID(a, b, c, d, e, f) (odbc_update_msg_id((a), (b), (c)))
1045#define DISPOSE(a,b) (imap_remove_file(a,b))
1046#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))
1047#define RETRIEVE(a,b,c,d) imap_retrieve_file(a,b,c,d)
1048#define EXISTS(a,b,c,d) (ast_fileexists(c,NULL,d) > 0)
1049#define RENAME(a,b,c,d,e,f,g,h) (rename_file(g,h));
1050#define COPY(a,b,c,d,e,f,g,h) (copy_file(g,h));
1051#define DELETE(a,b,c,d) (vm_imap_delete(a,b,d))
1052#define UPDATE_MSG_ID(a, b, c, d, e, f) (vm_imap_update_msg_id((a), (b), (c), (d), (e), (f)))
1054#define COUNT(a, b) count_messages(a,b)
1055#define LAST_MSG_INDEX(a) last_message_index(a)
1056#define RETRIEVE(a,b,c,d)
1058#define STORE(a,b,c,d,e,f,g,h,i,j,k)
1059#define EXISTS(a,b,c,d) (ast_fileexists(c,NULL,d) > 0)
1060#define RENAME(a,b,c,d,e,f,g,h) (rename_file(g,h));
1061#define COPY(a,b,c,d,e,f,g,h) (copy_plain_file(g,h));
1062#define DELETE(a,b,c,d) (vm_delete(c))
1063#define UPDATE_MSG_ID(a, b, c, d, e, f)
1074#define PWDCHANGE_INTERNAL (1 << 1)
1075#define PWDCHANGE_EXTERNAL (1 << 2)
1079#define tdesc "Comedian Mail (Voicemail System) with ODBC Storage"
1082# define tdesc "Comedian Mail (Voicemail System) with IMAP Storage"
1084# define tdesc "Comedian Mail (Voicemail System)"
1130#define DEFAULT_POLL_FREQ 30
1153#define MAPPING_BUCKETS 511
1211static unsigned char adsifdn[4] =
"\x00\x00\x00\x0F";
1212static unsigned char adsisec[4] =
"\x9B\xDB\xF7\xAC";
1223 char *fmt,
int outsidecaller,
struct ast_vm_user *vmu,
int *duration,
int *sound_duration,
const char *unlockdir,
1224 signed char record_gain,
struct vm_state *vms,
char *
flag,
const char *msg_id,
int forwardintro);
1228static 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);
1230static 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);
1260static 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);
1261static 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);
1262static int vm_msg_remove(
const char *mailbox,
const char *context,
size_t num_msgs,
const char *folder,
const char *msgs[]);
1265#ifdef TEST_FRAMEWORK
1266static int vm_test_destroy_user(
const char *context,
const char *mailbox);
1267static int vm_test_create_user(
const char *context,
const char *mailbox);
1287 *context = mailbox_id;
1288 *mailbox =
strsep(context,
"@");
1293 *context =
"default";
1315 if (strcmp(i->
mailbox, j->mailbox)) {
1323 int context_len = strlen(
context) + 1;
1324 int mailbox_len = strlen(
mailbox) + 1;
1339 if (!(i =
ao2_alloc(
sizeof(*i) + context_len + mailbox_len,
NULL))) {
1353#if !(defined(ODBC_STORAGE) || defined(IMAP_STORAGE))
1366 for (; *input; input++) {
1371 if (bufptr ==
buf + buflen - 1) {
1398static size_t get_msg_path_len(
const char *dir)
1412#define MAX_SOUND_EXTEN_LEN 12
1425static size_t get_msg_path_ext_len(
const char *dir)
1431 return strlen(dir) + 1 +
MSGFILE_LEN + MAX_SOUND_EXTEN_LEN + 1;
1455#define MAKE_FILE_PTRA(dir, msgnum) \
1457 size_t __len = get_msg_path_len(dir); \
1460 __var = ast_strdupa(dir); \
1462 __var = ast_alloca(__len); \
1463 snprintf(__var, __len, "%s/msg%04d", dir, msgnum); \
1497#define MAKE_FILE_EXT_PTRA(dir, msgnum, ext) \
1499 size_t __len = get_msg_path_ext_len(dir); \
1500 char *__var = ast_alloca(__len); \
1502 snprintf(__var, __len, "%s.%s", dir, ext); \
1504 snprintf(__var, __len, "%s/msg%04d.%s", dir, msgnum, ext); \
1555 ast_copy_string(vmu->imapfolder, imapfolder,
sizeof(vmu->imapfolder));
1556 ast_copy_string(vmu->imapserver, imapserver,
sizeof(vmu->imapserver));
1573 if (!strcasecmp(
var,
"attach")) {
1575 }
else if (!strcasecmp(
var,
"attachfmt")) {
1577 }
else if (!strcasecmp(
var,
"attachextrecs")) {
1579 }
else if (!strcasecmp(
var,
"serveremail")) {
1581 }
else if (!strcasecmp(
var,
"fromstring")) {
1583 }
else if (!strcasecmp(
var,
"emailbody")) {
1586 }
else if (!strcasecmp(
var,
"emailsubject")) {
1589 }
else if (!strcasecmp(
var,
"language")) {
1591 }
else if (!strcasecmp(
var,
"tz")) {
1593 }
else if (!strcasecmp(
var,
"locale")) {
1596 }
else if (!strcasecmp(
var,
"imapuser")) {
1598 vmu->imapversion = imapversion;
1599 }
else if (!strcasecmp(
var,
"imapserver")) {
1601 vmu->imapversion = imapversion;
1602 }
else if (!strcasecmp(
var,
"imapport")) {
1604 vmu->imapversion = imapversion;
1605 }
else if (!strcasecmp(
var,
"imapflags")) {
1607 vmu->imapversion = imapversion;
1608 }
else if (!strcasecmp(
var,
"imappassword") || !strcasecmp(
var,
"imapsecret")) {
1610 vmu->imapversion = imapversion;
1611 }
else if (!strcasecmp(
var,
"imapfolder")) {
1613 vmu->imapversion = imapversion;
1614 }
else if (!strcasecmp(
var,
"imapvmshareid")) {
1616 vmu->imapversion = imapversion;
1618 }
else if (!strcasecmp(
var,
"delete") || !strcasecmp(
var,
"deletevoicemail")) {
1620 }
else if (!strcasecmp(
var,
"saycid")){
1622 }
else if (!strcasecmp(
var,
"sendvoicemail")){
1624 }
else if (!strcasecmp(
var,
"review")){
1626 }
else if (!strcasecmp(
var,
"leaveurgent")){
1628 }
else if (!strcasecmp(
var,
"tempgreetwarn")){
1630 }
else if (!strcasecmp(
var,
"messagewrap")){
1632 }
else if (!strcasecmp(
var,
"operator")) {
1634 }
else if (!strcasecmp(
var,
"envelope")){
1636 }
else if (!strcasecmp(
var,
"moveheard")){
1638 }
else if (!strcasecmp(
var,
"sayduration")){
1640 }
else if (!strcasecmp(
var,
"saydurationm")){
1641 if (sscanf(
value,
"%30d", &x) == 1) {
1646 }
else if (!strcasecmp(
var,
"forcename")){
1648 }
else if (!strcasecmp(
var,
"forcegreetings")){
1650 }
else if (!strcasecmp(
var,
"callback")) {
1652 }
else if (!strcasecmp(
var,
"dialout")) {
1654 }
else if (!strcasecmp(
var,
"exitcontext")) {
1656 }
else if (!strcasecmp(
var,
"minsecs")) {
1657 if (sscanf(
value,
"%30d", &x) == 1 && x >= 0) {
1663 }
else if (!strcasecmp(
var,
"maxsecs")) {
1671 }
else if (!strcasecmp(
var,
"maxmsg")) {
1681 }
else if (!strcasecmp(
var,
"nextaftercmd")) {
1683 }
else if (!strcasecmp(
var,
"backupdeleted")) {
1684 if (sscanf(
value,
"%30d", &x) == 1)
1698 }
else if (!strcasecmp(
var,
"volgain")) {
1700 }
else if (!strcasecmp(
var,
"passwordlocation")) {
1701 if (!strcasecmp(
value,
"spooldir")) {
1706 }
else if (!strcasecmp(
var,
"options")) {
1713 int fds[2], pid = 0;
1718 snprintf(
buf,
len,
"FAILURE: Pipe failed: %s", strerror(
errno));
1727 snprintf(
buf,
len,
"FAILURE: Fork failed");
1731 if (read(fds[0],
buf,
len) < 0) {
1743 dup2(fds[1], STDOUT_FILENO);
1749 execv(arg.v[0], arg.v);
1750 printf(
"FAILURE: %s", strerror(
errno));
1773 char cmd[255],
buf[255];
1775 ast_debug(1,
"Verify password policies for %s\n", password);
1780 if (!strncasecmp(
buf,
"VALID", 5)) {
1783 }
else if (!strncasecmp(
buf,
"FAILURE", 7)) {
1808 if (!strcmp(vmu->
password, password)) {
1813 if (strlen(password) > 10) {
1833 while ((s =
strsep(&stringp,
"|"))) {
1849 if (!strcasecmp(
var->name,
"vmsecret")) {
1851 }
else if (!strcasecmp(
var->name,
"secret") || !strcasecmp(
var->name,
"password")) {
1855 "\n\tmust be reset in voicemail.conf.\n", retval->
mailbox);
1860 }
else if (!strcasecmp(
var->name,
"uniqueid")) {
1862 }
else if (!strcasecmp(
var->name,
"pager")) {
1864 }
else if (!strcasecmp(
var->name,
"email")) {
1867 }
else if (!strcasecmp(
var->name,
"fullname")) {
1869 }
else if (!strcasecmp(
var->name,
"context")) {
1871 }
else if (!strcasecmp(
var->name,
"emailsubject")) {
1874 }
else if (!strcasecmp(
var->name,
"emailbody")) {
1878 }
else if (!strcasecmp(
var->name,
"imapuser")) {
1880 retval->imapversion = imapversion;
1881 }
else if (!strcasecmp(
var->name,
"imapserver")) {
1883 retval->imapversion = imapversion;
1884 }
else if (!strcasecmp(
var->name,
"imapport")) {
1886 retval->imapversion = imapversion;
1887 }
else if (!strcasecmp(
var->name,
"imapflags")) {
1889 retval->imapversion = imapversion;
1890 }
else if (!strcasecmp(
var->name,
"imappassword") || !strcasecmp(
var->name,
"imapsecret")) {
1892 retval->imapversion = imapversion;
1893 }
else if (!strcasecmp(
var->name,
"imapfolder")) {
1895 retval->imapversion = imapversion;
1896 }
else if (!strcasecmp(
var->name,
"imapvmshareid")) {
1898 retval->imapversion = imapversion;
1917 for (i = 0; i < strlen(key); ++i) {
1942 if ((retval = (ivm ? ivm :
ast_calloc(1,
sizeof(*retval))))) {
1944 memset(retval, 0,
sizeof(*retval));
1989 if (cur->imapversion != imapversion) {
2000 if ((vmu = (ivm ? ivm :
ast_calloc(1,
sizeof(*vmu))))) {
2027 char *search_mailbox =
NULL;
2028 char *search_context =
NULL;
2032 vmu =
find_user(ivm, search_mailbox, search_context);
2069 "Context",
S_OR(context,
"default"),
2071 "NewPassword", newpass);
2097 char *category =
NULL;
2098 const char *tmp =
NULL;
2112 ast_verb(4,
"Writing voicemail password to file %s succeeded\n", secretfn);
2117 ast_log(
LOG_WARNING,
"Writing voicemail password to file %s failed, falling back to config file\n", secretfn);
2123 if (!strcasecmp(category, vmu->
context)) {
2130 value = strstr(tmp,
",");
2133 sprintf(
new,
"%s", newpassword);
2136 sprintf(
new,
"%s%s", newpassword,
value);
2150 ast_test_suite_event_notify(
"PASSWORDCHANGED",
"Message: voicemail.conf updated with new password\r\nPasswordSource: voicemail.conf");
2190static int make_dir(
char *dest,
int len,
const char *context,
const char *
ext,
const char *folder)
2207static int make_file(
char *dest,
const int len,
const char *dir,
const int num)
2209 return snprintf(dest,
len,
"%s/msg%04d", dir, num);
2236 if (vmu &&
id == 0) {
2237 return vmu->imapfolder;
2295 int arraysize = (vmu->
maxmsg > count_msg ? vmu->
maxmsg : count_msg);
2308 if (arraysize > 0) {
2326static void vm_imap_delete(
char *file,
int msgnum,
struct ast_vm_user *vmu)
2330 unsigned long messageNum;
2333 if (msgnum < 0 && !imapgreetings) {
2338 if (!(vms = get_vm_state_by_mailbox(vmu->
mailbox, vmu->
context, 1)) && !(vms = get_vm_state_by_mailbox(vmu->
mailbox, vmu->
context, 0))) {
2339 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);
2344 imap_delete_old_greeting(file, vms);
2350 messageNum = vms->msgArray[msgnum];
2351 if (messageNum == 0) {
2352 ast_log(
LOG_WARNING,
"msgnum %d, mailbox message %lu is zero.\n", msgnum, messageNum);
2355 ast_debug(3,
"deleting msgnum %d, which is mailbox message %lu\n", msgnum, messageNum);
2357 snprintf (arg,
sizeof(arg),
"%lu", messageNum);
2359 mail_setflag (vms->mailstream, arg,
"\\DELETED");
2360 mail_expunge(vms->mailstream);
2364static 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)
2371 const char *duration_str;
2415 sscanf(duration_str,
"%30d", &duration);
2431 vm_imap_delete(dir, msgnum, vmu);
2437static int imap_retrieve_greeting(
const char *dir,
const int msgnum,
struct ast_vm_user *vmu)
2440 char *
file, *filename;
2450 if (msgnum > -1 || !imapgreetings) {
2457 ast_debug(1,
"Failed to procure file name from directory passed.\n");
2463 if (!(vms_p = get_vm_state_by_mailbox(vmu->
mailbox, vmu->
context, 1)) &&
2464 !(vms_p = get_vm_state_by_mailbox(vmu->
mailbox, vmu->
context, 0))) {
2469 if (!(vms_p = create_vm_state_from_user(vmu))) {
2476 *vms_p->introfn =
'\0';
2490 for (i = 0; i < vms_p->mailstream->nmsgs; i++) {
2491 mail_fetchstructure(vms_p->mailstream, i + 1, &body);
2493 if (body->nested.part && body->nested.part->next && body->nested.part->next->body.parameter->value) {
2494 char *attachment = body->nested.part->next->body.parameter->value;
2495 char copy[strlen(attachment) + 1];
2497 strcpy(
copy, attachment);
2500 filename =
strsep(&attachment,
".");
2501 if (!strcmp(filename, file)) {
2503 vms_p->msgArray[vms_p->
curmsg] = i + 1;
2505 save_body(body, vms_p,
"2", attachment, 0);
2516 if (curr_mbox != -1) {
2518 if (init_mailstream(vms_p, curr_mbox) || !vms_p->mailstream) {
2527static int imap_retrieve_file(
const char *dir,
const int msgnum,
const char *mailbox,
const char *
context)
2530 char *header_content;
2531 char *attachedfilefmt;
2535 FILE *text_file_ptr;
2546 if (imapgreetings) {
2547 res = imap_retrieve_greeting(dir, msgnum, vmu);
2558 if (!(vms = get_vm_state_by_mailbox(vmu->
mailbox, vmu->
context, 1)) && !(vms = get_vm_state_by_mailbox(vmu->
mailbox, vmu->
context, 0))) {
2573 if (curr_mbox < 0) {
2574 ast_debug(3,
"Mailbox folder curbox not set, defaulting to Inbox\n");
2577 init_mailstream(vms, curr_mbox);
2578 if (!vms->mailstream) {
2585 snprintf(vms->introfn,
sizeof(vms->introfn),
"%sintro", vms->
fn);
2593 ast_debug(3,
"Before mail_fetchheaders, curmsg is: %d, imap messages is %lu\n", msgnum, vms->msgArray[msgnum]);
2594 if (vms->msgArray[msgnum] == 0) {
2602 header_content = mail_fetchheader (vms->mailstream, vms->msgArray[msgnum]);
2606 ast_log(
LOG_ERROR,
"Could not fetch header for message number %ld\n", vms->msgArray[msgnum]);
2612 mail_fetchstructure(vms->mailstream, vms->msgArray[msgnum], &body);
2616 if (body->nested.part && body->nested.part->next && body->nested.part->next->body.parameter->value) {
2617 attachedfilefmt =
ast_strdupa(body->nested.part->next->body.parameter->value);
2626 strsep(&attachedfilefmt,
".");
2627 if (!attachedfilefmt) {
2628 ast_log(
LOG_ERROR,
"File format could not be obtained from IMAP message attachment\n");
2633 save_body(body, vms,
"2", attachedfilefmt, 0);
2634 if (save_body(body, vms,
"3", attachedfilefmt, 1)) {
2635 *vms->introfn =
'\0';
2639 snprintf(text_file,
sizeof(text_file),
"%s.%s", vms->
fn,
"txt");
2641 if (!(text_file_ptr = fopen(text_file,
"w"))) {
2646 fprintf(text_file_ptr,
"%s\n",
"[message]");
2648 if (get_header_by_tag(header_content,
"X-Asterisk-VM-Caller-ID-Name:",
buf,
sizeof(
buf))) {
2649 fprintf(text_file_ptr,
"callerid=\"%s\" ",
S_OR(
buf,
""));
2651 if (get_header_by_tag(header_content,
"X-Asterisk-VM-Caller-ID-Num:",
buf,
sizeof(
buf))) {
2652 fprintf(text_file_ptr,
"<%s>\n",
S_OR(
buf,
""));
2654 if (get_header_by_tag(header_content,
"X-Asterisk-VM-Context:",
buf,
sizeof(
buf))) {
2655 fprintf(text_file_ptr,
"context=%s\n",
S_OR(
buf,
""));
2657 if (get_header_by_tag(header_content,
"X-Asterisk-VM-Orig-time:",
buf,
sizeof(
buf))) {
2658 fprintf(text_file_ptr,
"origtime=%s\n",
S_OR(
buf,
""));
2660 if (get_header_by_tag(header_content,
"X-Asterisk-VM-Duration:",
buf,
sizeof(
buf))) {
2661 fprintf(text_file_ptr,
"duration=%s\n",
S_OR(
buf,
""));
2663 if (get_header_by_tag(header_content,
"X-Asterisk-VM-Category:",
buf,
sizeof(
buf))) {
2664 fprintf(text_file_ptr,
"category=%s\n",
S_OR(
buf,
""));
2666 if (get_header_by_tag(header_content,
"X-Asterisk-VM-Flag:",
buf,
sizeof(
buf))) {
2667 fprintf(text_file_ptr,
"flag=%s\n",
S_OR(
buf,
""));
2669 if (get_header_by_tag(header_content,
"X-Asterisk-VM-Message-ID:",
buf,
sizeof(
buf))) {
2670 fprintf(text_file_ptr,
"msg_id=%s\n",
S_OR(
buf,
""));
2672 fclose(text_file_ptr);
2679static int folder_int(
const char *folder)
2685 if (!strcasecmp(folder, imapfolder)) {
2687 }
else if (!strcasecmp(folder,
"Old")) {
2689 }
else if (!strcasecmp(folder,
"Work")) {
2691 }
else if (!strcasecmp(folder,
"Family")) {
2693 }
else if (!strcasecmp(folder,
"Friends")) {
2695 }
else if (!strcasecmp(folder,
"Cust1")) {
2697 }
else if (!strcasecmp(folder,
"Cust2")) {
2699 }
else if (!strcasecmp(folder,
"Cust3")) {
2701 }
else if (!strcasecmp(folder,
"Cust4")) {
2703 }
else if (!strcasecmp(folder,
"Cust5")) {
2705 }
else if (!strcasecmp(folder,
"Urgent")) {
2712static int __messagecount(
const char *
context,
const char *
mailbox,
const char *folder)
2720 int fold = folder_int(folder);
2733 memset(&vmus, 0,
sizeof(vmus));
2741 if (vmu->imapuser[0] ==
'\0') {
2749 if (vmu->imapuser[0] ==
'\0') {
2756 vms_p = get_vm_state_by_imapuser(vmu->imapuser, 1);
2758 vms_p = get_vm_state_by_mailbox(mailbox,
context, 1);
2761 ast_debug(3,
"Returning before search - user is logged in\n");
2773 vms_p = get_vm_state_by_imapuser(vmu->imapuser, 0);
2775 vms_p = get_vm_state_by_mailbox(mailbox,
context, 0);
2779 vms_p = create_vm_state_from_user(vmu);
2781 ret = init_mailstream(vms_p, fold);
2782 if (!vms_p->mailstream) {
2789 pgm = mail_newsearchpgm ();
2790 hdr = mail_newsearchheader (
"X-Asterisk-VM-Extension", (
char *)(!
ast_strlen_zero(vmu->imapvmshareid) ? vmu->imapvmshareid :
mailbox));
2791 hdr->next = mail_newsearchheader(
"X-Asterisk-VM-Context", (
char *)
S_OR(
context,
"default"));
2817 vms_p->vmArrayIndex = 0;
2818 mail_search_full (vms_p->mailstream,
NULL, pgm, NIL);
2819 if (fold == 0 && urgent == 0)
2823 if (fold == 0 && urgent == 1)
2826 mail_free_searchpgm(&pgm);
2830 return vms_p->vmArrayIndex;
2833 mail_ping(vms_p->mailstream);
2843 check_quota(vms, vmu->imapfolder);
2844 if (vms->quota_limit && vms->quota_usage >= vms->quota_limit) {
2845 ast_debug(1,
"*** QUOTA EXCEEDED!! %u >= %u\n", vms->quota_usage, vms->quota_limit);
2855 ast_log(
LOG_WARNING,
"Unable to leave message since we will exceed the maximum number of messages allowed (%u >= %u)\n", msgnum, vmu->
maxmsg);
2874static int messagecount(
const char *mailbox_id,
const char *folder)
2886 count = __messagecount(
context, mailbox,
"INBOX") + __messagecount(
context, mailbox,
"Urgent");
2888 count = __messagecount(
context, mailbox, folder);
2890 return count < 0 ? 0 : count;
2893static 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)
2901 char tmp[80] =
"/tmp/astmail-XXXXXX";
2907 char *imap_flags = NIL;
2911 snprintf(mailbox,
sizeof(mailbox),
"%s@%s", vmu->
mailbox, vmu->
context);
2916 if(!imapgreetings) {
2923 if (imap_check_limits(chan, vms, vmu, msgcount)) {
2929 ast_debug(3,
"Setting message flag \\\\FLAGGED.\n");
2930 imap_flags =
"\\FLAGGED";
2946 snprintf(introfn,
sizeof(introfn),
"%sintro",
fn);
2961 if (!strcmp(fmt,
"wav49"))
2963 ast_debug(3,
"Storing file '%s', format '%s'\n",
fn, fmt);
2976 if (msgnum < 0 && imapgreetings) {
2981 imap_delete_old_greeting(
fn, vms);
2987 fn, introfn, fmt, duration, 1, chan,
NULL, 1,
flag, msg_id);
2995 *(vmu->
email) =
'\0';
3004 ((
char *)
buf)[
len] =
'\0';
3006 ret = init_mailstream(vms, box);
3008 imap_mailbox_name(mailbox,
sizeof(mailbox), vms, box, 1);
3010 if(!mail_append_full(vms->mailstream, mailbox, imap_flags, NIL, &
str))
3026 *(vmu->
email) =
'\0';
3045static int inboxcount2(
const char *mailbox_context,
int *urgentmsgs,
int *newmsgs,
int *oldmsgs)
3060 ast_debug(3,
"Mailbox is set to %s\n", mailbox_context);
3067 if (strchr(mailbox_context,
',')) {
3068 int tmpnew, tmpold, tmpurgent;
3071 while ((cur =
strsep(&mb,
", "))) {
3081 *urgentmsgs += tmpurgent;
3093 mailboxnc = (
char *) mailbox_context;
3102 if ((count = __messagecount(
context, mailboxnc, vmu->imapfolder)) < 0) {
3110 if ((count = __messagecount(
context, mailboxnc,
"Old")) < 0) {
3116 if ((count = __messagecount(
context, mailboxnc,
"Urgent")) < 0) {
3119 *urgentmsgs = count;
3136 char tmp[256], *tmp2, *box, *
context;
3139 if (strchr(tmp2,
',') || strchr(tmp2,
'&')) {
3140 while ((box =
strsep(&tmp2,
",&"))) {
3148 if ((
context = strchr(tmp,
'@'))) {
3153 return __messagecount(
context, tmp, folder) > 0 ? 1 : 0;
3175 char messagestring[10];
3176 if (msgnum >= recip->
maxmsg) {
3180 if (!(sendvms = get_vm_state_by_imapuser(vmu->imapuser, 0))) {
3184 if (!get_vm_state_by_imapuser(recip->imapuser, 0)) {
3188 snprintf(messagestring,
sizeof(messagestring),
"%ld", sendvms->msgArray[msgnum]);
3190 if ((mail_copy(sendvms->mailstream, messagestring, (
char *)
mbox(vmu, imbox)) == T)) {
3199static void imap_mailbox_name(
char *spec,
size_t len,
struct vm_state *vms,
int box,
int use_folder)
3201 char tmp[256], *t = tmp;
3202 size_t left =
sizeof(tmp);
3235 snprintf(spec,
len,
"%s%s", tmp, use_folder? vms->imapfolder:
"INBOX");
3237 snprintf(spec,
len,
"%s%s", tmp, greetingfolder);
3241 snprintf(spec,
len,
"%s%s%c%s", tmp, imapparentfolder, delimiter,
mbox(
NULL, box));
3243 snprintf(spec,
len,
"%s%s", tmp,
mbox(
NULL, box));
3248static int init_mailstream(
struct vm_state *vms,
int box)
3250 MAILSTREAM *stream = NIL;
3258 ast_debug(3,
"vm_state user is:%s\n", vms->imapuser);
3259 if (vms->mailstream == NIL || !vms->mailstream) {
3262 stream = vms->mailstream;
3267 if (delimiter ==
'\0') {
3269#ifdef USE_SYSTEM_IMAP
3270#include <imap/linkage.c>
3271#elif defined(USE_SYSTEM_CCLIENT)
3272#include <c-client/linkage.c>
3277 imap_mailbox_name(tmp,
sizeof(tmp), vms, 0, 1);
3280 stream = mail_open (stream, tmp,
debug ? OP_DEBUG : NIL);
3283 if (stream == NIL) {
3287 get_mailbox_delimiter(vms, stream);
3289 for (cp = vms->imapfolder; *cp; cp++)
3294 imap_mailbox_name(tmp,
sizeof(tmp), vms, box, 1);
3295 ast_debug(3,
"Before mail_open, server: %s, box:%d\n", tmp, box);
3298 vms->mailstream = mail_open (stream, tmp,
debug ? OP_DEBUG : NIL);
3300 if (vms->mailstream && !mail_status(vms->mailstream, tmp, SA_UIDNEXT)) {
3301 mail_create(vms->mailstream, tmp);
3305 if (vms->mailstream == NIL) {
3325 ast_copy_string(vms->imapfolder, vmu->imapfolder,
sizeof(vms->imapfolder));
3326 ast_copy_string(vms->imapserver, vmu->imapserver,
sizeof(vms->imapserver));
3328 ast_copy_string(vms->imapflags, vmu->imapflags,
sizeof(vms->imapflags));
3329 vms->imapversion = vmu->imapversion;
3330 ast_debug(3,
"Before init_mailstream, user is %s\n", vmu->imapuser);
3332 if (init_mailstream(vms, box) || !vms->mailstream) {
3341 ast_debug(3,
"Mailbox name set to: %s, about to check quotas\n",
mbox(vmu, box));
3342 check_quota(vms, (
char *)
mbox(vmu, box));
3346 pgm = mail_newsearchpgm();
3349 hdr = mail_newsearchheader(
"X-Asterisk-VM-Extension", (!
ast_strlen_zero(vmu->imapvmshareid) ? vmu->imapvmshareid : vmu->
mailbox));
3350 hdr->next = mail_newsearchheader(
"X-Asterisk-VM-Context", vmu->
context);
3361 }
else if (box ==
NEW_FOLDER && urgent == 0) {
3371 ast_debug(3,
"Before mail_search_full, user is %s\n", vmu->imapuser);
3373 vms->vmArrayIndex = 0;
3374 mail_search_full (vms->mailstream,
NULL, pgm, NIL);
3375 vms->
lastmsg = vms->vmArrayIndex - 1;
3376 mail_free_searchpgm(&pgm);
3382 ast_log(
LOG_WARNING,
"The code expects the old messages to be checked first, fix the code.\n");
3393static void write_file(
char *filename,
char *buffer,
unsigned long len)
3397 if (!filename || !buffer) {
3401 if (!(output = fopen(filename,
"w"))) {
3406 if (fwrite(buffer,
len, 1, output) != 1) {
3407 if (ferror(output)) {
3414static void update_messages_by_imapuser(
const char *
user,
unsigned long number)
3416 struct vm_state *vms = get_vm_state_by_imapuser(
user, 1);
3418 if (!vms && !(vms = get_vm_state_by_imapuser(
user, 0))) {
3422 ast_debug(3,
"saving mailbox message number %lu as message %d. Interactive set to %d\n",
number, vms->vmArrayIndex, vms->interactive);
3425 if (vms->vmArrayIndex >= vms->msg_array_max) {
3426 long *new_mem =
ast_realloc(vms->msgArray, 2 * vms->msg_array_max *
sizeof(
long));
3430 vms->msgArray = new_mem;
3431 vms->msg_array_max *= 2;
3434 vms->msgArray[vms->vmArrayIndex++] =
number;
3437void mm_searched(MAILSTREAM *stream,
unsigned long number)
3441 if (!(
user = get_user_by_mailbox(mailbox,
buf,
sizeof(
buf))))
3447static struct ast_vm_user *find_user_realtime_imapuser(
const char *imapuser)
3472void mm_exists(MAILSTREAM * stream,
unsigned long number)
3481void mm_expunged(MAILSTREAM * stream,
unsigned long number)
3490void mm_flags(MAILSTREAM * stream,
unsigned long number)
3499void mm_notify(MAILSTREAM * stream,
char *
string,
long errflg)
3501 ast_debug(5,
"Entering NOTIFY callback, errflag is %ld, string is %s\n", errflg,
string);
3502 mm_log (
string, errflg);
3506void mm_list(MAILSTREAM * stream,
int delim,
char *
mailbox,
long attributes)
3508 if (delimiter ==
'\0') {
3513 if (attributes & LATT_NOINFERIORS)
3515 if (attributes & LATT_NOSELECT)
3517 if (attributes & LATT_MARKED)
3519 if (attributes & LATT_UNMARKED)
3524void mm_lsub(MAILSTREAM * stream,
int delim,
char *
mailbox,
long attributes)
3527 if (attributes & LATT_NOINFERIORS)
3529 if (attributes & LATT_NOSELECT)
3531 if (attributes & LATT_MARKED)
3533 if (attributes & LATT_UNMARKED)
3538void mm_status(MAILSTREAM * stream,
char *
mailbox, MAILSTATUS *
status)
3547 if (
status->flags & SA_MESSAGES) {
3550 if (
status->flags & SA_RECENT) {
3553 if (
status->flags & SA_UNSEEN) {
3556 if (
status->flags & SA_UIDVALIDITY) {
3559 if (
status->flags & SA_UIDNEXT) {
3568void mm_log(
char *
string,
long errflg)
3570 switch ((
short) errflg) {
3572 ast_debug(1,
"IMAP Info: %s\n",
string);
3585void mm_dlog(
char *
string)
3591void mm_login(NETMBX * mb,
char *
user,
char *pwd,
long trial)
3595 ast_debug(4,
"Entering callback mm_login\n");
3604 if (!strcasecmp(mb->user, vmu->imapuser)) {
3610 if ((vmu = find_user_realtime_imapuser(mb->user))) {
3619void mm_critical(MAILSTREAM * stream)
3624void mm_nocritical(MAILSTREAM * stream)
3629long mm_diskerror(MAILSTREAM * stream,
long errcode,
long serious)
3631 kill (getpid (), SIGSTOP);
3636void mm_fatal(
char *
string)
3642static void mm_parsequota(MAILSTREAM *stream,
unsigned char *msg, QUOTALIST *pquota)
3646 char buf[1024] =
"";
3647 unsigned long usage = 0, limit = 0;
3650 usage = pquota->usage;
3651 limit = pquota->limit;
3652 pquota = pquota->next;
3655 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)))) {
3662 vms->quota_usage =
usage;
3663 vms->quota_limit = limit;
3666static char *get_header_by_tag(
char *
header,
char *tag,
char *
buf,
size_t len)
3668 char *start, *eol_pnt;
3674 taglen = strlen(tag) + 1;
3685 if ((eol_pnt = strchr(
buf,
'\r')) || (eol_pnt = strchr(
buf,
'\n')))
3690static char *get_user_by_mailbox(
char *mailbox,
char *
buf,
size_t len)
3692 char *start, *eol_pnt, *
quote;
3697 if (!(start = strstr(mailbox,
"/user=")))
3703 if ((eol_pnt = strchr(
buf,
'/')) || (eol_pnt = strchr(
buf,
'}'))) {
3708 if ((eol_pnt = strchr(
quote + 1,
'"'))) {
3719 pthread_once(&ts_vmstate.once, ts_vmstate.key_init);
3720 if ((vms_p = pthread_getspecific(ts_vmstate.key)) && !strcmp(vms_p->imapuser, vmu->imapuser) && !strcmp(vms_p->
username, vmu->
mailbox)) {
3723 ast_debug(5,
"Adding new vmstate for %s\n", vmu->imapuser);
3725 if (!(vms_p =
ast_calloc(1,
sizeof(*vms_p))))
3727 ast_copy_string(vms_p->imapuser, vmu->imapuser,
sizeof(vms_p->imapuser));
3728 ast_copy_string(vms_p->imapfolder, vmu->imapfolder,
sizeof(vms_p->imapfolder));
3729 ast_copy_string(vms_p->imapserver, vmu->imapserver,
sizeof(vms_p->imapserver));
3730 ast_copy_string(vms_p->imapport, vmu->imapport,
sizeof(vms_p->imapport));
3731 ast_copy_string(vms_p->imapflags, vmu->imapflags,
sizeof(vms_p->imapflags));
3734 vms_p->mailstream = NIL;
3735 vms_p->imapversion = vmu->imapversion;
3736 ast_debug(5,
"Copied %s to %s\n", vmu->imapuser, vms_p->imapuser);
3740 init_vm_state(vms_p);
3741 vmstate_insert(vms_p);
3745static struct vm_state *get_vm_state_by_imapuser(
const char *
user,
int interactive)
3747 struct vmstate *vlist =
NULL;
3751 pthread_once(&ts_vmstate.once, ts_vmstate.key_init);
3752 if ((vms = pthread_getspecific(ts_vmstate.key)) && !strcmp(vms->imapuser,
user)) {
3763 if (vlist->vms->imapversion != imapversion) {
3767 if (!strcmp(vlist->vms->imapuser,
user) && (interactive == 2 || vlist->vms->interactive == interactive)) {
3779static struct vm_state *get_vm_state_by_mailbox(
const char *mailbox,
const char *
context,
int interactive)
3782 struct vmstate *vlist =
NULL;
3783 const char *local_context =
S_OR(context,
"default");
3787 pthread_once(&ts_vmstate.once, ts_vmstate.key_init);
3788 if ((vms = pthread_getspecific(ts_vmstate.key)) &&
3789 !strcmp(vms->
username,mailbox) && !strcmp(vms->
context, local_context)) {
3797 ast_debug(3,
"error: vms is NULL for %s\n", mailbox);
3800 if (vlist->vms->imapversion != imapversion) {
3804 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);
3806 if (!strcmp(vlist->vms->username, mailbox) && !strcmp(vlist->vms->context, local_context) && vlist->vms->interactive == interactive) {
3814 ast_debug(3,
"%s not found in vmstates\n", mailbox);
3819static void vmstate_insert(
struct vm_state *vms)
3827 if (vms->interactive == 1) {
3833 vms->vmArrayIndex = altvms->vmArrayIndex;
3838 vms->persist_vms = altvms;
3840#ifdef REALLY_FAST_EVEN_IF_IT_MEANS_RESOURCE_LEAKS
3841 vms->mailstream = altvms->mailstream;
3843 vms->mailstream = NIL;
3854 ast_debug(3,
"Inserting vm_state for user:%s, mailbox %s\n", vms->imapuser, vms->
username);
3861static void vmstate_delete(
struct vm_state *vms)
3863 struct vmstate *vc =
NULL;
3868 if (vms->interactive == 1 && (altvms = vms->persist_vms)) {
3872 altvms->updated = 1;
3873 vms->mailstream = mail_close(vms->mailstream);
3879 ast_debug(3,
"Removing vm_state for user:%s, mailbox %s\n", vms->imapuser, vms->
username);
3883 if (vc->vms == vms) {
3894 vc->vms->msgArray =
NULL;
3895 vc->vms->msg_array_max = 0;
3903static void set_update(MAILSTREAM * stream)
3907 char buf[1024] =
"";
3909 if (!(
user = get_user_by_mailbox(mailbox,
buf,
sizeof(
buf))) || !(vms = get_vm_state_by_imapuser(
user, 0))) {
3920static void init_vm_state(
struct vm_state *vms)
3923 vms->msgArray =
ast_calloc(vms->msg_array_max,
sizeof(
long));
3924 if (!vms->msgArray) {
3926 vms->msg_array_max = 0;
3928 vms->vmArrayIndex = 0;
3932static int save_body(BODY *body,
struct vm_state *vms,
char *section,
char *format,
int is_intro)
3936 char *
fn = is_intro ? vms->introfn : vms->
fn;
3937 unsigned long len = 0;
3938 unsigned long newlen = 0;
3941 if (!body || body == NIL)
3945 body_content = mail_fetchbody(vms->mailstream, vms->msgArray[vms->
curmsg], section, &
len);
3949 "Msgno %ld, section %s. The body's content size %ld is huge (max %ld). User:%s, mailbox %s\n",
3953 if (body_content != NIL &&
len) {
3954 snprintf(filename,
sizeof(filename),
"%s.%s",
fn, format);
3956 body_decoded = rfc822_base64((
unsigned char *) body_content,
len, &newlen);
3958 if (!newlen || !body_decoded) {
3961 write_file(filename, (
char *) body_decoded, newlen);
3963 ast_debug(5,
"Body of message is NULL.\n");
3977static void get_mailbox_delimiter(
struct vm_state *vms, MAILSTREAM *stream) {
3979 snprintf(tmp,
sizeof(tmp),
"{%s}",
S_OR(vms->imapserver, imapserver));
3980 mail_list(stream, tmp,
"*");
3990static void check_quota(
struct vm_state *vms,
char *mailbox) {
3992 mail_parameters(
NULL, SET_QUOTA, (
void *) mm_parsequota);
3993 ast_debug(3,
"Mailbox name set to: %s, about to check quotas\n", mailbox);
3994 if (vms && vms->mailstream !=
NULL) {
3995 imap_getquotaroot(vms->mailstream, mailbox);
4018#define MSG_ID_LEN 256
4041#define MAKE_SQL_PTRA(__sql_fmt) \
4044 char *__sql = ast_alloca(strlen(__sql_fmt) + odbc_table_len); \
4045 sprintf(__sql, __sql_fmt, odbc_table); \
4059#define MAKE_SQL_PTRA2(__sql_fmt) \
4062 char *__sql = ast_alloca(strlen(__sql_fmt) + (odbc_table_len * 2)); \
4063 sprintf(__sql, __sql_fmt, odbc_table, odbc_table); \
4067struct generic_prepare_struct {
4075 struct generic_prepare_struct *gps = data;
4079 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->
con, &stmt);
4080 if (!SQL_SUCCEEDED(res)) {
4085 if (!SQL_SUCCEEDED(res)) {
4087 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
4090 for (i = 0; i < gps->argc; i++)
4091 SQLBindParameter(stmt, i + 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(gps->argv[i]), 0, gps->argv[i], 0,
NULL);
4096static void odbc_update_msg_id(
char *dir,
int msg_num,
char *msg_id)
4099 char *sql = MAKE_SQL_PTRA(
"UPDATE %s SET msg_id=? WHERE dir=? AND msgnum=?");
4101 char msg_num_str[20];
4102 char *argv[] = { msg_id, dir, msg_num_str };
4103 struct generic_prepare_struct gps = { .sql = sql, .argc = 3, .argv = argv };
4104 SCOPE_ENTER(3,
"dir: %s msg_num: %d msg_id: %s\n", dir, msg_num, msg_id);
4111 snprintf(msg_num_str,
sizeof(msg_num_str),
"%d", msg_num);
4116 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
4122#define AUDIO_ON_DISK_MAGIC "AUDMAGIC"
4123#define AUDIO_ON_DISK_MAGIC_LEN 8
4125static void odbc_update_set_audmagic(
char *dir,
int msg_num)
4128 char *sql = MAKE_SQL_PTRA(
"UPDATE %s SET recording=? WHERE dir=? AND msgnum=?");
4130 SQLLEN datalen = AUDIO_ON_DISK_MAGIC_LEN;
4131 SQLLEN indlen = datalen;
4133 char msg_num_str[20];
4134 SCOPE_ENTER(3,
"dir: %s msg_num: %d\n", dir, msg_num);
4141 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->
con, &stmt);
4142 if (!SQL_SUCCEEDED(res)) {
4147 snprintf(msg_num_str,
sizeof(msg_num_str),
"%d", msg_num);
4149 SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_BINARY, SQL_LONGVARBINARY,
4150 datalen, 0, (
void *) AUDIO_ON_DISK_MAGIC,
4153 SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR,
4154 strlen(dir), 0, (
void *) dir, 0,
NULL);
4156 SQLBindParameter(stmt, 3, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR,
4157 strlen(msg_num_str), 0, (
void *) msg_num_str, 0,
NULL);
4160 if (!SQL_SUCCEEDED(res)) {
4164 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
4171static int odbc_store_message(
const char *dir,
const char *mailboxuser,
const char *mailboxcontext,
int msgnum);
4187static int odbc_retrieve_message(
char *dir,
int msgnum)
4193 void *fdm = MAP_FAILED;
4194 SQLSMALLINT colcount = 0;
4196 char *sql = MAKE_SQL_PTRA(
"SELECT * FROM %s WHERE dir=? AND msgnum=?");
4201 SQLSMALLINT datatype;
4202 SQLSMALLINT decimaldigits;
4203 SQLSMALLINT nullable;
4208 char *fn = MAKE_FILE_PTRA(dir, msgnum);
4209 char *full_fn = MAKE_FILE_EXT_PTRA(dir, msgnum,
"txt");
4211 char *mailboxuser =
NULL;
4212 char *mailboxcontext =
NULL;
4214 char *argv[] = { dir, msgnums };
4215 struct generic_prepare_struct gps = { .sql = sql, .argc = 2, .argv = argv };
4217 int storage_conversion_to_disk = 0;
4218 int storage_conversion_to_odbc = 0;
4219 SCOPE_ENTER(3,
"dir: %s msgnum: %d msgtype: %s\n", dir, msgnum, msgnum < 0 ?
"Greeting" :
"Message");
4227 c = strchr(fmt,
'|');
4230 if (!strcasecmp(fmt,
"wav49"))
4233 snprintf(msgnums,
sizeof(msgnums),
"%d", msgnum);
4235 ast_trace(-1,
"Opening '%s' for writing\n", full_fn);
4236 if (!(f = fopen(full_fn,
"w+"))) {
4241 sprintf(full_fn,
"%s.%s", fn, fmt);
4249 res = SQLFetch(stmt);
4250 if (!SQL_SUCCEEDED(res)) {
4251 if (res != SQL_NO_DATA) {
4254 goto bail_with_handle;
4257 res = SQLNumResultCols(stmt, &colcount);
4258 if (!SQL_SUCCEEDED(res)) {
4260 goto bail_with_handle;
4263 fprintf(f,
"[message]\n");
4264 for (x = 0; x < colcount; x++) {
4267 collen =
sizeof(coltitle);
4268 res = SQLDescribeCol(stmt, x + 1, (
unsigned char *) coltitle,
sizeof(coltitle), &collen,
4269 &datatype, &colsize, &decimaldigits, &nullable);
4270 if (!SQL_SUCCEEDED(res)) {
4272 goto bail_with_handle;
4275 if (!strcasecmp(coltitle,
"recording")) {
4279 res = SQLGetData(stmt, x + 1, SQL_BINARY, rowdata, 0, &colsize2);
4281 ast_trace(-1,
"Audio size: %ld\n", colsize2);
4282 if (colsize2 == AUDIO_ON_DISK_MAGIC_LEN) {
4283 res = SQLGetData(stmt, x + 1, SQL_BINARY, rowdata, AUDIO_ON_DISK_MAGIC_LEN,
NULL);
4284 if (memcmp(rowdata, AUDIO_ON_DISK_MAGIC, AUDIO_ON_DISK_MAGIC_LEN) != 0) {
4286 rowdata[0], rowdata[1], rowdata[2], rowdata[3], rowdata[4], rowdata[5], rowdata[6],
4287 rowdata[7], full_fn);
4288 goto bail_with_handle;
4290 ast_trace(-1,
"Audio is stored on disk. No need to write '%s'\n", full_fn);
4292 storage_conversion_to_odbc = 1;
4298 ast_trace(-1,
"Opening '%s' for writing\n", full_fn);
4302 goto bail_with_handle;
4305 storage_conversion_to_disk = 1;
4308 lseek(fd, fdlen - 1, SEEK_SET);
4309 if (write(fd, tmp, 1) != 1) {
4315 for (offset = 0; offset < colsize2; offset +=
CHUNKSIZE) {
4316 if ((fdm = mmap(
NULL,
CHUNKSIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset)) == MAP_FAILED) {
4318 goto bail_with_handle;
4320 res = SQLGetData(stmt, x + 1, SQL_BINARY, fdm,
CHUNKSIZE,
NULL);
4322 if (!SQL_SUCCEEDED(res)) {
4325 goto bail_with_handle;
4328 if (truncate(full_fn, fdlen) < 0) {
4331 ast_trace(-1,
"Wrote %d bytes to '%s'\n", (
int)fdlen, full_fn);
4333 res = SQLGetData(stmt, x + 1, SQL_CHAR, rowdata,
sizeof(rowdata),
NULL);
4334 if (res == SQL_NULL_DATA && !strcasecmp(coltitle,
"msg_id")) {
4340 ast_trace(-1,
"msg_id was NULL. Generating new one: %s\n", msg_id);
4341 snprintf(rowdata,
sizeof(rowdata),
"%s", msg_id);
4342 }
else if (!strcasecmp(coltitle,
"mailboxuser")) {
4344 }
else if (!strcasecmp(coltitle,
"mailboxcontext")) {
4346 }
else if (res == SQL_NULL_DATA && !strcasecmp(coltitle,
"category")) {
4348 ast_trace(-1,
"Ignoring null category column in ODBC voicemail retrieve_file.\n");
4350 }
else if (!SQL_SUCCEEDED(res)) {
4352 goto bail_with_handle;
4354 if (strcasecmp(coltitle,
"msgnum") && strcasecmp(coltitle,
"dir")) {
4355 fprintf(f,
"%s=%s\n", coltitle, rowdata);
4361 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
4375 odbc_update_msg_id(dir, msgnum, msg_id);
4378 if (SQL_SUCCEEDED(res)) {
4379 if (storage_conversion_to_disk) {
4385 SCOPE_CALL(-1, odbc_update_set_audmagic, dir, msgnum);
4387 if (storage_conversion_to_odbc) {
4394 SCOPE_CALL(-1, odbc_store_message, dir, mailboxuser, mailboxcontext, msgnum);
4410static int odbc_last_message_index(
char *dir)
4415 char *sql = MAKE_SQL_PTRA(
"SELECT msgnum FROM %s WHERE dir=? order by msgnum desc");
4417 char *argv[] = { dir };
4418 struct generic_prepare_struct gps = { .sql = sql, .argc = 1, .argv = argv };
4433 res = SQLFetch(stmt);
4434 if (!SQL_SUCCEEDED(res)) {
4435 if (res == SQL_NO_DATA) {
4436 ast_trace(-1,
"Directory '%s' has no messages and therefore no index was retrieved.\n", dir);
4440 goto bail_with_handle;
4443 res = SQLGetData(stmt, 1, SQL_CHAR, rowdata,
sizeof(rowdata),
NULL);
4444 if (!SQL_SUCCEEDED(res)) {
4446 goto bail_with_handle;
4449 if (sscanf(rowdata,
"%30d", &x) != 1) {
4454 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
4471static int odbc_message_exists(
char *dir,
int msgnum)
4476 char *sql = MAKE_SQL_PTRA(
"SELECT COUNT(*) FROM %s WHERE dir=? AND msgnum=?");
4479 char *argv[] = { dir, msgnums };
4480 struct generic_prepare_struct gps = { .sql = sql, .argc = 2, .argv = argv };
4482 SCOPE_ENTER(3,
"dir: %s msgnum: %d\n", dir, msgnum);
4489 snprintf(msgnums,
sizeof(msgnums),
"%d", msgnum);
4496 res = SQLFetch(stmt);
4497 if (!SQL_SUCCEEDED(res)) {
4499 goto bail_with_handle;
4502 res = SQLGetData(stmt, 1, SQL_CHAR, rowdata,
sizeof(rowdata),
NULL);
4503 if (!SQL_SUCCEEDED(res)) {
4505 goto bail_with_handle;
4508 if (sscanf(rowdata,
"%30d", &x) != 1) {
4513 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
4529static int odbc_count_messages(
struct ast_vm_user *vmu,
char *dir)
4534 char *sql = MAKE_SQL_PTRA(
"SELECT COUNT(*) FROM %s WHERE dir=?");
4536 char *argv[] = { dir };
4537 struct generic_prepare_struct gps = { .sql = sql, .argc = 1, .argv = argv };
4552 res = SQLFetch(stmt);
4553 if (!SQL_SUCCEEDED(res)) {
4555 goto bail_with_handle;
4558 res = SQLGetData(stmt, 1, SQL_CHAR, rowdata,
sizeof(rowdata),
NULL);
4559 if (!SQL_SUCCEEDED(res)) {
4561 goto bail_with_handle;
4564 if (sscanf(rowdata,
"%30d", &x) != 1) {
4569 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
4584#define DELETE_SQL_FMT "DELETE FROM %s WHERE dir=? AND msgnum=?"
4585static void odbc_delete_message(
const char *sdir,
int smsg)
4588 char *sql = MAKE_SQL_PTRA(DELETE_SQL_FMT);
4590 char *argv[] = {
NULL, msgnums };
4591 struct generic_prepare_struct gps = { .sql = sql, .argc = 2, .argv = argv };
4593 SCOPE_ENTER(3,
"sdir: %s smsg: %d\n", sdir, smsg);
4602 snprintf(msgnums,
sizeof(msgnums),
"%d", smsg);
4607 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
4612 char *src_fn = MAKE_FILE_PTRA(sdir, smsg);
4613 ast_trace(-1,
"Audio stored on disk. Deleting '%s'\n", src_fn);
4631#define COPY_SQL_FMT "INSERT INTO %s (dir, msgnum, msg_id, context, callerid, origtime, " \
4632 "duration, recording, flag, mailboxuser, mailboxcontext) " \
4633 "SELECT ?,?,msg_id,context,callerid,origtime,duration,recording,flag,?,? " \
4634 "FROM %s WHERE dir=? AND msgnum=?"
4635static void odbc_copy_message(
char *sdir,
int smsg,
char *ddir,
int dmsg,
char *dmailboxuser,
char *dmailboxcontext)
4638 char *sql = MAKE_SQL_PTRA2(COPY_SQL_FMT);
4642 char *argv[] = { ddir, msgnumd, dmailboxuser, dmailboxcontext, sdir, msgnums };
4643 struct generic_prepare_struct gps = { .sql = sql, .argc = 6, .argv = argv };
4644 SCOPE_ENTER(3,
"sdir: %s smsg: %d duser: %s dcontext: %s ddir: %s dmsg: %d\n",
4645 sdir, smsg, dmailboxuser, dmailboxcontext, ddir, dmsg);
4647 SCOPE_CALL(-1, odbc_delete_message, ddir, dmsg);
4654 snprintf(msgnums,
sizeof(msgnums),
"%d", smsg);
4655 snprintf(msgnumd,
sizeof(msgnumd),
"%d", dmsg);
4659 ast_log(
AST_LOG_WARNING,
"SQL Execute error!\n[%s] (You probably don't have MySQL 4.1 or later installed)\n\n", sql);
4661 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
4665 char *src_fn = MAKE_FILE_PTRA(sdir, smsg);
4666 char *dst_fn = MAKE_FILE_PTRA(ddir, dmsg);
4668 ast_trace(-1,
"Audio stored on disk. Copying '%s' to '%s'\n", src_fn, dst_fn);
4678 const char *msgnums;
4683 const char *callerid;
4684 const char *origtime;
4685 const char *duration;
4686 const char *mailboxuser;
4687 const char *mailboxcontext;
4688 const char *category;
4693#define STORE_SQL_FMT_CAT "INSERT INTO %s (dir, msgnum, recording, context, callerid, " \
4694 "origtime, duration, mailboxuser, mailboxcontext, flag, msg_id, category) " \
4695 "VALUES (?,?,?,?,?,?,?,?,?,?,?,?)"
4696#define STORE_SQL_FMT "INSERT INTO %s (dir, msgnum, recording, context, callerid, "\
4697 "origtime, duration, mailboxuser, mailboxcontext, flag, msg_id) "\
4698 "VALUES (?,?,?,?,?,?,?,?,?,?,?)"
4700static SQLHSTMT odbc_insert_data_cb(
struct odbc_obj *obj,
void *vdata)
4702 struct insert_data *data = vdata;
4707 SCOPE_ENTER(3,
"dir: %s msgnums: %s msg_id: %s\n", data->dir, data->msgnums,
4710 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->
con, &stmt);
4711 if (!SQL_SUCCEEDED(res)) {
4716 delete_sql = MAKE_SQL_PTRA(DELETE_SQL_FMT);
4717 SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->dir), 0, (
void *) data->dir, 0,
NULL);
4718 SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->msgnums), 0, (
void *) data->msgnums, 0,
NULL);
4720 if (!SQL_SUCCEEDED(res)) {
4721 ast_trace(-1,
"There wasn't an existing row. Good.\n");
4723 ast_trace(-1,
"There WAS an existing row. This is OK if we're replacing a message.\n");
4725 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
4728 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->
con, &stmt);
4729 if (!SQL_SUCCEEDED(res)) {
4733 SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->dir), 0, (
void *) data->dir, 0,
NULL);
4734 SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->msgnums), 0, (
void *) data->msgnums, 0,
NULL);
4735 SQLBindParameter(stmt, 3, SQL_PARAM_INPUT, SQL_C_BINARY, SQL_LONGVARBINARY, data->datalen, 0, (
void *) data->data, data->datalen, &data->indlen);
4736 SQLBindParameter(stmt, 4, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->context), 0, (
void *) data->context, 0,
NULL);
4737 SQLBindParameter(stmt, 5, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->callerid), 0, (
void *) data->callerid, 0,
NULL);
4738 SQLBindParameter(stmt, 6, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->origtime), 0, (
void *) data->origtime, 0,
NULL);
4739 SQLBindParameter(stmt, 7, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->duration), 0, (
void *) data->duration, 0,
NULL);
4740 SQLBindParameter(stmt, 8, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->mailboxuser), 0, (
void *) data->mailboxuser, 0,
NULL);
4741 SQLBindParameter(stmt, 9, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->mailboxcontext), 0, (
void *) data->mailboxcontext, 0,
NULL);
4742 SQLBindParameter(stmt, 10, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->flag), 0, (
void *) data->flag, 0,
NULL);
4743 SQLBindParameter(stmt, 11, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->msg_id), 0, (
void *) data->msg_id, 0,
NULL);
4745 insert_sql = MAKE_SQL_PTRA(STORE_SQL_FMT_CAT);
4746 SQLBindParameter(stmt, 12, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->category), 0, (
void *) data->category, 0,
NULL);
4748 insert_sql = MAKE_SQL_PTRA(STORE_SQL_FMT);
4751 if (!SQL_SUCCEEDED(res)) {
4754 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
4774static int odbc_store_message(
const char *dir,
const char *mailboxuser,
const char *mailboxcontext,
int msgnum)
4778 void *fdm = MAP_FAILED;
4782 char *fn = MAKE_FILE_PTRA(dir, msgnum);
4783 char *full_fn = MAKE_FILE_EXT_PTRA(dir, msgnum,
"txt");
4788 struct insert_data idata = { .msgnums = msgnums, .dir = dir, .mailboxuser = mailboxuser, .mailboxcontext = mailboxcontext,
4789 .context =
"", .callerid =
"", .origtime =
"", .duration =
"", .category =
"", .flag =
"", .msg_id =
"" };
4791 SCOPE_ENTER(3,
"dir: %s user: %s context: %s msgnum: %d msgtype: %s\n",
4792 dir, mailboxuser, mailboxcontext, msgnum, msgnum < 0 ?
"Greeting" :
"Message");
4801 c = strchr(fmt,
'|');
4804 if (!strcasecmp(fmt,
"wav49"))
4808 snprintf(msgnums,
sizeof(msgnums),
"%d", msgnum);
4811 ast_trace(-1,
"Opening '%s'\n", full_fn);
4815 ast_trace(-1,
"No information file found for '%s'. This is a greeting so this is OK.\n", full_fn);
4823 sprintf(full_fn,
"%s.%s", fn, fmt);
4825 ast_trace(-1,
"Audio stored on disk. No need to open '%s'\n", full_fn);
4827 ast_trace(-1,
"Opening '%s'\n", full_fn);
4828 fd = open(full_fn, O_RDWR);
4837 ast_trace(-1,
"Using information file '%s'\n", fn);
4842 idata.callerid =
"";
4845 idata.origtime =
"";
4848 idata.duration =
"";
4851 idata.category =
"";
4862 ast_trace(-1,
"Audio stored on disk. Not reading sound file '%s' but setting magic number.\n", full_fn);
4863 idata.data = AUDIO_ON_DISK_MAGIC;
4864 idata.datalen = idata.indlen = AUDIO_ON_DISK_MAGIC_LEN;
4866 ast_trace(-1,
"Reading sound file '%s'\n", full_fn);
4867 fdlen = lseek(fd, 0, SEEK_END);
4868 if (fdlen < 0 || lseek(fd, 0, SEEK_SET) < 0) {
4873 fdm = mmap(
NULL, fdlen, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
4874 if (fdm == MAP_FAILED) {
4880 idata.datalen = idata.indlen = fdlen;
4884 idata.origtime =
"0";
4888 idata.duration =
"0";
4892 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
4902 if (fdm != MAP_FAILED)
4909#undef STORE_SQL_FMT_CAT
4924static void odbc_rename_message(
char *sdir,
int smsg,
char *mailboxuser,
char *mailboxcontext,
char *ddir,
int dmsg)
4927 char *sql = MAKE_SQL_PTRA(
"UPDATE %s SET dir=?, msgnum=? WHERE mailboxuser=? AND mailboxcontext=? AND dir=? AND msgnum=?");
4931 char *argv[] = { ddir, msgnumd, mailboxuser, mailboxcontext, sdir, msgnums };
4932 struct generic_prepare_struct gps = { .sql = sql, .argc = 6, .argv = argv };
4933 SCOPE_ENTER(3,
"sdir: %s smsg: %d user: %s context: %s ddir: %s dmsg: %d\n", sdir, smsg,
4934 mailboxuser, mailboxcontext, ddir, dmsg);
4936 SCOPE_CALL(-1, odbc_delete_message, ddir, dmsg);
4943 snprintf(msgnums,
sizeof(msgnums),
"%d", smsg);
4944 snprintf(msgnumd,
sizeof(msgnumd),
"%d", dmsg);
4950 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
4954 char *src_fn = MAKE_FILE_PTRA(sdir, smsg);
4955 char *dst_fn = MAKE_FILE_PTRA(ddir, dmsg);
4957 ast_trace(-1,
"Recordings stored on disk. Renaming '%s' to '%s'\n", src_fn, dst_fn);
4975static int odbc_remove_files(
char *dir,
int msgnum)
4977 char *fn = MAKE_FILE_PTRA(dir, msgnum);
4978 char *full_fn = MAKE_FILE_EXT_PTRA(dir, msgnum,
"txt");
4979 SCOPE_ENTER(3,
"dir: %s msgnum: %d\n", dir, msgnum);
4982 ast_trace(-1,
"Audio stored on disk. Keeping '%s' sound files\n", fn);
4984 ast_trace(-1,
"Audio stored in ODBC. Removing '%s' sound files\n", fn);
4989 ast_trace(-1,
"Removing '%s' information file\n", full_fn);
5009 struct dirent *vment =
NULL;
5014 if ((vmdir = opendir(dir))) {
5015 while ((vment = readdir(vmdir))) {
5016 if (strlen(vment->d_name) > 7 && !strncmp(vment->d_name + 7,
".txt", 4)) {
5039 snprintf(stxt,
sizeof(stxt),
"%s.txt", sfn);
5040 snprintf(dtxt,
sizeof(dtxt),
"%s.txt", dfn);
5062 struct dirent *msgdirent;
5071 if (!(msgdir = opendir(dir))) {
5075 while ((msgdirent = readdir(msgdir))) {
5079 ast_debug(4,
"%s map[%d] = %d, count = %d\n", dir, msgdirint, map[msgdirint], stopcount);
5085 stopcount -= map[x];
5104static int copy(
char *infile,
char *outfile)
5112#ifdef HARDLINK_WHEN_POSSIBLE
5114 if (!link(infile, outfile)) {
5119 if ((ifd = open(infile, O_RDONLY)) < 0) {
5144 wrlen = write(ofd,
buf,
len);
5173 const char *origmailbox =
"", *context =
"", *exten =
"";
5174 const char *
priority =
"", *callerchan =
"", *callerid =
"", *origdate =
"";
5175 const char *origtime =
"", *category =
"", *duration =
"";
5178 snprintf(frompath2,
sizeof(frompath2),
"%s.txt", frompath);
5179 snprintf(topath2,
sizeof(topath2),
"%s.txt", topath);
5184 for (tmp =
var; tmp; tmp = tmp->
next) {
5185 if (!strcasecmp(tmp->
name,
"origmailbox")) {
5186 origmailbox = tmp->
value;
5187 }
else if (!strcasecmp(tmp->
name,
"context")) {
5188 context = tmp->
value;
5189 }
else if (!strcasecmp(tmp->
name,
"exten")) {
5191 }
else if (!strcasecmp(tmp->
name,
"priority")) {
5193 }
else if (!strcasecmp(tmp->
name,
"callerchan")) {
5194 callerchan = tmp->
value;
5195 }
else if (!strcasecmp(tmp->
name,
"callerid")) {
5196 callerid = tmp->
value;
5197 }
else if (!strcasecmp(tmp->
name,
"origdate")) {
5198 origdate = tmp->
value;
5199 }
else if (!strcasecmp(tmp->
name,
"origtime")) {
5200 origtime = tmp->
value;
5201 }
else if (!strcasecmp(tmp->
name,
"category")) {
5202 category = tmp->
value;
5203 }
else if (!strcasecmp(tmp->
name,
"duration")) {
5204 duration = tmp->
value;
5207 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);
5209 copy(frompath2, topath2);
5229 txtsize = (strlen(
file) + 5)*
sizeof(
char);
5237 snprintf(txt, txtsize,
"%s.txt",
file);
5245static 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)
5249 char fromdir[256], fromfile[256];
5251 const char *origcallerid, *origtime;
5252 char origcidname[80], origcidnum[80], origdate[80];
5259 snprintf(num,
sizeof(num),
"%d", msgnum);
5273 make_file(fromfile,
sizeof(fromfile), fromdir, msgnum - 1);
5274 if (strlen(fromfile) <
sizeof(fromfile) - 5) {
5275 strcat(fromfile,
".txt");
5278 ast_debug(1,
"Config load for message text file '%s' failed\n", fromfile);
5284 ast_callerid_split(origcallerid, origcidname,
sizeof(origcidname), origcidnum,
sizeof(origcidnum));
5289 if ((origtime =
ast_variable_retrieve(msg_cfg,
"message",
"origtime")) && sscanf(origtime,
"%30d", &inttime) == 1) {
5290 struct timeval tv = { inttime, };
5313 for (ptr = from; *ptr; ptr++) {
5314 if (*ptr ==
'"' || *ptr ==
'\\') {
5355 if (*
str > 126 || *
str < 32 || strchr(
"()<>@,:;/\"[]?.=", *
str)) {
5382 int first_section = 1;
5386 for (; *start; start++) {
5387 int need_encoding = 0;
5388 if (*start < 33 || *start > 126 || strchr(
"()<>@,:;/\"[]?.=_", *start)) {
5391 if ((first_section && need_encoding && preamble +
ast_str_strlen(tmp) > 70) ||
5392 (first_section && !need_encoding && preamble +
ast_str_strlen(tmp) > 72) ||
5394 (!first_section && !need_encoding &&
ast_str_strlen(tmp) > 72)) {
5400 if (need_encoding && *start ==
' ') {
5402 }
else if (need_encoding) {
5441 const char *fromfolder,
5448 int attach_user_voicemail,
5450 const char *category,
5461 char enc_cidnum[256] =
"", enc_cidname[256] =
"";
5463 char *greeting_attachment;
5469 if (!str1 || !str2) {
5481 gethostname(host,
sizeof(host) - 1);
5483 if (strchr(srcemail,
'@')) {
5486 snprintf(who,
sizeof(who),
"%s@%s", srcemail, host);
5489 greeting_attachment = strrchr(
ast_strdupa(attach),
'/');
5490 if (greeting_attachment) {
5491 *greeting_attachment++ =
'\0';
5494 snprintf(dur,
sizeof(dur),
"%d:%02d", duration / 60, duration % 60);
5496 fprintf(p,
"Date: %s" ENDL, date);
5506 prep_email_sub_vars(ast, vmu, msgnum + 1,
context, mailbox, fromfolder, enc_cidnum, enc_cidname, dur, date, category,
flag);
5528 fprintf(p,
"From: Asterisk PBX <%s>" ENDL, who);
5535 char *next = emailsbuf;
5553 fprintf(p,
"Subject: New greeting '%s' on %s." ENDL, greeting_attachment, date);
5558 prep_email_sub_vars(ast, vmu, msgnum + 1,
context, mailbox, fromfolder, cidnum, cidname, dur, date, category,
flag);
5581 fprintf(p,
"Subject: New message %d in mailbox %s" ENDL, msgnum + 1, mailbox);
5583 fprintf(p,
"Subject: New %s message %d in mailbox %s" ENDL,
flag, msgnum + 1, mailbox);
5587 fprintf(p,
"Subject: [PBX]: New message %d in mailbox %s" ENDL, msgnum + 1, mailbox);
5589 fprintf(p,
"Subject: [PBX]: New %s message %d in mailbox %s" ENDL,
flag, msgnum + 1, mailbox);
5593 fprintf(p,
"Message-ID: <Asterisk-%d-%u-%s-%d@%s>" ENDL, msgnum + 1,
5594 (
unsigned int)
ast_random(), mailbox, (
int) getpid(), host);
5597 fprintf(p,
"X-Asterisk-VM-Message-Num: %d" ENDL, msgnum + 1);
5600 fprintf(p,
"X-Asterisk-VM-Context: %s" ENDL,
context);
5602 fprintf(p,
"X-Asterisk-VM-Extension: %s" ENDL, (!
ast_strlen_zero(vmu->imapvmshareid) ? vmu->imapvmshareid : mailbox));
5604 fprintf(p,
"X-Asterisk-VM-Extension: %s" ENDL, mailbox);
5607 fprintf(p,
"X-Asterisk-VM-Flag: %s" ENDL,
S_OR(
flag,
""));
5609 fprintf(p,
"X-Asterisk-VM-Caller-ID-Num: %s" ENDL, enc_cidnum);
5610 fprintf(p,
"X-Asterisk-VM-Caller-ID-Name: %s" ENDL, enc_cidname);
5611 fprintf(p,
"X-Asterisk-VM-Duration: %d" ENDL, duration);
5613 fprintf(p,
"X-Asterisk-VM-Category: %s" ENDL, category);
5615 fprintf(p,
"X-Asterisk-VM-Category: " ENDL);
5617 fprintf(p,
"X-Asterisk-VM-Message-Type: %s" ENDL, msgnum > -1 ?
"Message" : greeting_attachment);
5618 fprintf(p,
"X-Asterisk-VM-Orig-date: %s" ENDL, date);
5619 fprintf(p,
"X-Asterisk-VM-Orig-time: %ld" ENDL, (
long) time(
NULL));
5620 fprintf(p,
"X-Asterisk-VM-Message-ID: %s" ENDL, msg_id);
5623 fprintf(p,
"X-Asterisk-CallerID: %s" ENDL, enc_cidnum);
5626 fprintf(p,
"X-Asterisk-CallerIDName: %s" ENDL, enc_cidname);
5628 fprintf(p,
"MIME-Version: 1.0" ENDL);
5629 if (attach_user_voicemail) {
5631 snprintf(bound,
sizeof(bound),
"----voicemail_%d%s%d%u", msgnum + 1, mailbox,
5632 (
int) getpid(), (
unsigned int)
ast_random());
5634 fprintf(p,
"Content-Type: multipart/mixed; boundary=\"%s\"" ENDL, bound);
5635 fprintf(p,
ENDL ENDL "This is a multi-part message in MIME format." ENDL ENDL);
5636 fprintf(p,
"--%s" ENDL, bound);
5638 fprintf(p,
"Content-Type: text/plain; charset=%s" ENDL "Content-Transfer-Encoding: 8bit" ENDL ENDL,
charset);
5640 fprintf(p,
"This message is to let you know that your greeting '%s' was changed on %s." ENDL
5641 "Please do not delete this message, lest your greeting vanish with it." ENDL ENDL,
5642 greeting_attachment, date);
5647 prep_email_sub_vars(ast, vmu, msgnum + 1,
context, mailbox, fromfolder, cidnum, cidname, dur, date, category,
flag);
5655 if ((next = strchr(line,
'\n'))) {
5658 fprintf(p,
"%s" ENDL, line);
5670 if (strcmp(vmu->
mailbox, mailbox)) {
5675 char fromdir[256], fromfile[256], origdate[80] =
"", origcallerid[80] =
"";
5679 make_file(fromfile,
sizeof(fromfile), fromdir, msgnum);
5680 if (strlen(fromfile) <
sizeof(fromfile) - 5) {
5681 strcat(fromfile,
".txt");
5690 if ((v =
ast_variable_retrieve(msg_cfg,
"message",
"origtime")) && sscanf(v,
"%30d", &inttime) == 1) {
5691 struct timeval tv = { inttime, };
5696 fprintf(p,
"Dear %s:" ENDL ENDL "\tJust wanted to let you know you were just forwarded"
5697 " a %s long message (number %d)" ENDL "in mailbox %s from %s, on %s" ENDL
5698 "(originally sent by %s on %s)" ENDL "so you might want to check it when you get a"
5700 msgnum + 1, mailbox, (cidname ? cidname : (cidnum ? cidnum :
"an unknown caller")),
5701 date, origcallerid, origdate);
5708 fprintf(p,
"Dear %s:" ENDL ENDL "\tJust wanted to let you know you were just left a "
5709 "%s long message (number %d)" ENDL "in mailbox %s from %s, on %s so you might" ENDL
5710 "want to check it when you get a chance. Thanks!" ENDL ENDL "\t\t\t\t--Asterisk"
5712 (cidname ? cidname : (cidnum ? cidnum :
"an unknown caller")), date);
5716 if (imap || attach_user_voicemail) {
5718 snprintf(filename,
sizeof(filename),
"msg%04d.%s", msgnum, format);
5719 ast_debug(5,
"creating second attachment filename %s\n", filename);
5720 add_email_attachment(p, vmu, format, attach, greeting_attachment, mailbox, bound, filename, 0, msgnum);
5721 snprintf(filename,
sizeof(filename),
"msgintro%04d.%s", msgnum, format);
5722 ast_debug(5,
"creating attachment filename %s\n", filename);
5723 add_email_attachment(p, vmu, format, attach2, greeting_attachment, mailbox, bound, filename, 1, msgnum);
5725 snprintf(filename,
sizeof(filename),
"msg%04d.%s", msgnum, format);
5726 ast_debug(5,
"creating attachment filename %s, no second attachment.\n", filename);
5727 add_email_attachment(p, vmu, format, attach, greeting_attachment, mailbox, bound, filename, 1, msgnum);
5738 char *file_to_delete =
NULL, *dir_to_delete =
NULL;
5742 char altformat[80] =
"";
5746 char *mime_type = (!strcasecmp(format,
"ogg")) ?
"application/" :
"audio/x-";
5749 snprintf(fname,
sizeof(fname),
"%s.%s", attach, format);
5752 c = strchr(altformat,
'|');
5757 snprintf(altfname,
sizeof(altfname),
"%s.%s", attach, altformat);
5771 res = snprintf(sox_gain_tmpdir,
sizeof(sox_gain_tmpdir),
"%s/vm-gain-XXXXXX", tmpdir);
5772 if (res >=
sizeof(sox_gain_tmpdir)) {
5773 ast_log(
LOG_ERROR,
"Failed to create temporary directory path %s: Out of buffer space\n", tmpdir);
5777 if (
mkdtemp(sox_gain_tmpdir)) {
5781 ast_debug(3,
"sox_gain_tmpdir: %s\n", sox_gain_tmpdir);
5784 dir_to_delete = sox_gain_tmpdir;
5786 res = snprintf(fname,
sizeof(fname),
"%s/output.%s", sox_gain_tmpdir, format);
5787 if (res >=
sizeof(fname)) {
5788 ast_log(
LOG_ERROR,
"Failed to create filename buffer for %s/output.%s: Too long\n", sox_gain_tmpdir, format);
5793 res = snprintf(sox_gain_cmd,
sizeof(sox_gain_cmd),
"sox -v %.4f %s.%s %s",
5794 vmu->
volgain, attach, format, fname);
5796 if (!strcasecmp(format,
"wav")) {
5798 res = snprintf(sox_gain_cmd,
sizeof(sox_gain_cmd),
"sox -v %.4f %s.%s -e signed-integer -b 16 %s",
5799 vmu->
volgain, attach, altformat, fname);
5801 res = snprintf(sox_gain_cmd,
sizeof(sox_gain_cmd),
"sox %s.%s -e signed-integer -b 16 %s",
5802 attach, altformat, fname);
5806 res = snprintf(sox_gain_cmd,
sizeof(sox_gain_cmd),
"sox -v %.4f %s.%s %s",
5807 vmu->
volgain, attach, altformat, fname);
5809 res = snprintf(sox_gain_cmd,
sizeof(sox_gain_cmd),
"sox %s.%s %s",
5810 attach, altformat, fname);
5815 if (res >=
sizeof(sox_gain_cmd)) {
5816 ast_log(
LOG_ERROR,
"Failed to generate sox command, out of buffer space\n");
5823 file_to_delete = fname;
5824 ast_debug(3,
"VOLGAIN: Stored at: %s - Level: %.4f - Mailbox: %s\n", fname, vmu->
volgain, mailbox);
5826 ast_log(
LOG_WARNING,
"Sox failed to re-encode %s: %s (have you installed support for all sox file formats?)\n",
5828 soxstatus == 1 ?
"Problem with command line options" :
"An error occurred during file processing");
5836 if (!file_to_delete) {
5837 res = snprintf(fname,
sizeof(fname),
"%s.%s", attach, format);
5838 if (res >=
sizeof(fname)) {
5839 ast_log(
LOG_ERROR,
"Failed to create filename buffer for %s.%s: Too long\n", attach, format);
5844 fprintf(p,
"--%s" ENDL, bound);
5846 fprintf(p,
"Content-Type: %s%s; name=\"%s\"" ENDL, mime_type, format, filename);
5848 fprintf(p,
"Content-Type: %s%s; name=\"%s.%s\"" ENDL, mime_type, format, greeting_attachment, format);
5849 fprintf(p,
"Content-Transfer-Encoding: base64" ENDL);
5850 fprintf(p,
"Content-Description: Voicemail sound attachment." ENDL);
5852 fprintf(p,
"Content-Disposition: attachment; filename=\"%s\"" ENDL ENDL, filename);
5854 fprintf(p,
"Content-Disposition: attachment; filename=\"%s.%s\"" ENDL ENDL, greeting_attachment, format);
5859 if (file_to_delete) {
5860 unlink(file_to_delete);
5863 if (dir_to_delete) {
5864 rmdir(dir_to_delete);
5875 const char *fromfolder,
5882 int attach_user_voicemail,
5884 const char *category,
5889 char tmp[80] =
"/tmp/astmail-XXXXXX";
5903 if (!strcmp(format,
"wav49"))
5912 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);
5914 snprintf(tmp2,
sizeof(tmp2),
"( %s < %s ; rm -f %s ) &",
mailcmd, tmp, tmp);
5921static 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)
5923 char enc_cidnum[256], enc_cidname[256];
5928 char tmp[80] =
"/tmp/astmail-XXXXXX";
5934 if (!str1 || !str2) {
5953 gethostname(host,
sizeof(host)-1);
5954 if (strchr(srcemail,
'@')) {
5957 snprintf(who,
sizeof(who),
"%s@%s", srcemail, host);
5959 snprintf(dur,
sizeof(dur),
"%d:%02d", duration / 60, duration % 60);
5961 fprintf(p,
"Date: %s\n", date);
5970 prep_email_sub_vars(ast, vmu, msgnum + 1,
context, mailbox, fromfolder, enc_cidnum, enc_cidname, dur, date, category,
flag);
5992 fprintf(p,
"From: Asterisk PBX <%s>" ENDL, who);
6014 prep_email_sub_vars(ast, vmu, msgnum + 1,
context, mailbox, fromfolder, cidnum, cidname, dur, date, category,
flag);
6037 fprintf(p,
"Subject: New VM" ENDL);
6039 fprintf(p,
"Subject: New %s VM" ENDL,
flag);
6049 prep_email_sub_vars(ast, vmu, msgnum + 1,
context, mailbox, fromfolder, cidnum, cidname, dur, date, category,
flag);
6057 fprintf(p,
"New %s long %s msg in box %s\n"
6058 "from %s, on %s", dur,
flag, mailbox, (cidname ? cidname : (cidnum ? cidnum :
"unknown")), date);
6062 snprintf(tmp2,
sizeof(tmp2),
"( %s < %s ; rm -f %s ) &",
mailcmd, tmp, tmp);
6095 snprintf(fn,
sizeof(fn),
"%s%s/%s/greet",
VM_SPOOL_DIR, context,
ext);
6129#define COUNT_MSGS_SQL_FMT "SELECT COUNT(*) FROM %s WHERE dir = '%s%s/%s/%s'"
6130static int count_messages_in_folder(
struct odbc_obj *odbc,
const char *context,
const char *mailbox,
const char *folder,
int *messages)
6133 char sql[
sizeof(COUNT_MSGS_SQL_FMT) + odbc_table_len + strlen(
VM_SPOOL_DIR)
6134 + strlen(context) + strlen(mailbox) + strlen(folder)];
6136 SQLHSTMT stmt =
NULL;
6137 struct generic_prepare_struct gps = { .sql = sql, .argc = 0 };
6138 SCOPE_ENTER(3,
"context: %s mb: %s folder: %s", context, mailbox, folder);
6144 snprintf(sql,
sizeof(sql), COUNT_MSGS_SQL_FMT, odbc_table,
VM_SPOOL_DIR, context, mailbox, folder);
6148 res = SQLFetch(stmt);
6149 if (!SQL_SUCCEEDED(res)) {
6150 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
6153 res = SQLGetData(stmt, 1, SQL_CHAR, rowdata,
sizeof(rowdata),
NULL);
6154 if (!SQL_SUCCEEDED(res)) {
6155 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
6159 *messages = atoi(rowdata);
6160 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
6164#undef COUNT_MSGS_SQL_FMT
6166static int inboxcount2(
const char *mailbox,
int *urgentmsgs,
int *newmsgs,
int *oldmsgs)
6187 if (strchr(mailbox,
' ') || strchr(mailbox,
',')) {
6189 char *
next, *remaining = tmp;
6204 SCOPE_EXIT_RTN_VALUE(0,
"Urgent: %d New: %d Old: %d\n", urgentmsgs ? *urgentmsgs : 0, newmsgs ? *newmsgs : 0, oldmsgs ? *oldmsgs : 0);
6219 if (count_messages_in_folder(obj, context, tmp,
"INBOX", newmsgs)
6220 || count_messages_in_folder(obj, context, tmp,
"Old", oldmsgs)
6221 || count_messages_in_folder(obj, context, tmp,
"Urgent", urgentmsgs)) {
6227 SCOPE_EXIT_RTN_VALUE(0,
"Urgent: %d New: %d Old: %d\n", urgentmsgs ? *urgentmsgs : 0, newmsgs ? *newmsgs : 0, oldmsgs ? *oldmsgs : 0);
6238#define MSGCOUNT_SQL_FMT_INBOX "SELECT COUNT(*) FROM %s WHERE dir = '%s%s/%s/INBOX' OR dir = '%s%s/%s/Urgent'"
6239#define MSGCOUNT_SQL_FMT "SELECT COUNT(*) FROM %s WHERE dir = '%s%s/%s/%s'"
6240static int messagecount(
const char *mailbox_id,
const char *folder)
6247 SQLHSTMT stmt =
NULL;
6249 struct generic_prepare_struct gps = { .argc = 0 };
6250 SCOPE_ENTER(3,
"mb: %s folder: %s", mailbox_id, folder);
6267 if (!strcmp(folder,
"INBOX")) {
6282 res = SQLFetch(stmt);
6283 if (!SQL_SUCCEEDED(res)) {
6285 goto bail_with_handle;
6287 res = SQLGetData(stmt, 1, SQL_CHAR, rowdata,
sizeof(rowdata),
NULL);
6288 if (!SQL_SUCCEEDED(res)) {
6290 goto bail_with_handle;
6292 nummsgs = atoi(rowdata);
6295 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
6302#undef MSGCOUNT_SQL_FMT
6303#undef MSGCOUNT_SQL_FMT_INBOX
6319 while ((mailbox =
strsep(&parse,
",&"))) {
6345 long duration,
struct ast_vm_user *recip,
char *fmt,
char *dir,
const char *
flag,
6346 const char *dest_folder)
6349 const char *frombox =
mbox(vmu, imbox);
6350 const char *userfolder;
6353 SCOPE_ENTER(3,
"mb: %s imb: %d msgnum: %d recip: %s dir: %s dest_folder: %s",
6359 userfolder =
"Urgent";
6361 userfolder = dest_folder;
6363 userfolder =
"INBOX";
6374 ast_trace(-1,
"fromdir: %s\n", fromdir);
6376 make_file(frompath,
sizeof(frompath), fromdir, msgnum);
6377 ast_trace(-1,
"frompath: %s\n", frompath);
6387 ast_trace(-1,
"recip msgnum: %d\n", recipmsgnum);
6392 make_file(topath,
sizeof(topath), todir, recipmsgnum);
6400 SCOPE_CALL(-1,
STORE, todir, recip->
mailbox, recip->
context, recipmsgnum, chan, recip, fmt, duration,
NULL,
NULL,
NULL);
6420#if !(defined(IMAP_STORAGE) || defined(ODBC_STORAGE))
6435static int __has_voicemail(
const char *context,
const char *mailbox,
const char *folder,
int shortcircuit)
6452 context =
"default";
6454 c = (
char *)context;
6468 snprintf(fn,
sizeof(fn),
"%s%s/%s/%s",
VM_SPOOL_DIR,
c, m, folder);
6470 if (!(dir = opendir(fn)))
6473 while ((de = readdir(dir))) {
6474 if (!strncasecmp(de->d_name,
"msg", 3)) {
6478 }
else if (!strncasecmp(de->d_name + 8,
"txt", 3)) {
6500 char tmp[256], *tmp2 = tmp, *box, *context;
6505 while ((box =
strsep(&tmp2,
",&"))) {
6506 if ((context = strchr(box,
'@')))
6509 context =
"default";
6513 if (!strcmp(folder,
"INBOX") &&
__has_voicemail(context, box,
"Urgent", 1)) {
6549 int tmpnew, tmpold, tmpurgent;
6554 while ((cur =
strsep(&mb,
", "))) {
6566 *urgentmsgs += tmpurgent;
6576 if ((context = strchr(tmp,
'@'))) {
6579 context =
"default";
6603 *newmsgs += urgentmsgs;
6610 char arguments[255];
6611 char ext_context[256] =
"";
6612 int newvoicemails = 0, oldvoicemails = 0, urgentvoicemails = 0;
6616 snprintf(ext_context,
sizeof(ext_context),
"%s@%s",
extension, context);
6628 if (!strncmp(mwi_msg->
cause,
"INV", 3))
6630 else if (!strncmp(mwi_msg->
cause,
"BLK", 3))
6640 if (
inboxcount2(ext_context, &urgentvoicemails, &newvoicemails, &oldvoicemails)) {
6643 snprintf(arguments,
sizeof(arguments),
"%s %s %s %d %d %d &",
6646 oldvoicemails, urgentvoicemails);
6647 ast_debug(1,
"Executing %s\n", arguments);
6672 snprintf(dst,
MSG_ID_LEN,
"%ld-%08x", (
long) time(
NULL), unique_counter);
6706 char ext_context[256] =
"";
6722 const char *category =
NULL;
6731 memset(&svm, 0,
sizeof(svm));
6743 duration = (int) (framelength / sample_rate);
6752 if (duration < recipient->minsecs) {
6753 ast_log(
LOG_NOTICE,
"Copying recording to voicemail %s@%s skipped because duration was shorter than "
6754 "minmessage of recipient\n", recdata->
mailbox, recdata->
context);
6764 snprintf(tmptxtfile,
sizeof(tmptxtfile),
"%s/XXXXXX", tmpdir);
6765 txtdes = mkstemp(tmptxtfile);
6775 txt = fdopen(txtdes,
"w+");
6781 "; Message Information file\n"
6804 date, (
long) time(
NULL),
6829 snprintf(ext_context,
sizeof(ext_context),
"%s@%s", recipient->
mailbox, recipient->
context);
6833 res =
inboxcount(ext_context, &newmsgs, &oldmsgs);
6840 if (!(vms = get_vm_state_by_mailbox(recipient->
mailbox, recipient->
context, 0))) {
6845 if (!(vms = create_vm_state_from_user(recipient))) {
6855 msgnum = newmsgs + oldmsgs;
6856 ast_debug(3,
"Messagecount set to %d\n", msgnum);
6857 snprintf(destination,
sizeof(destination),
"%simap/msg%s%04d",
VM_SPOOL_DIR, recipient->
mailbox, msgnum);
6861 if ((res = imap_check_limits(
NULL, vms, recipient, msgnum))) {
6872 ast_debug(3,
"mailbox = %d : inprocess = %d\n",
COUNT(recipient, dir),
6888 ast_log(
LOG_ERROR,
"Couldn't lock directory %s. Voicemail will be lost.\n", dir);
6896 make_file(destination,
sizeof(destination), dir, msgnum);
6898 make_file(tmpaudiofile,
sizeof(tmpaudiofile), tmpdir, msgnum);
6901 ast_log(
LOG_ERROR,
"Audio file failed to copy to tmp dir. Probably low disk space.\n");
6912 ast_log(
LOG_ERROR,
"Audio file failed to move to destination directory. Permissions/Overlap?\n");
6920 snprintf(desttxtfile,
sizeof(desttxtfile),
"%s.txt", destination);
6921 rename(tmptxtfile, desttxtfile);
6938 char cidnum[80], cidname[80];
6944 "origmailbox", recdata->
mailbox,
6951 "origtime", time(
NULL),
6952 "category",
S_OR(category,
""),
6953 "filename", tmptxtfile,
6954 "duration", duration,
6958 STORE(dir, recipient->
mailbox, recipient->
context, msgnum,
NULL, recipient, fmt, 0, vms,
"", msg_id);
7000 int newmsgs, oldmsgs;
7012 int sound_duration = 0;
7014 int greeting_only = 0;
7023 char ext_context[256] =
"";
7026 char ecodes[17] =
"#";
7031 const char *category =
NULL;
7033 const char *alldtmf =
"0123456789ABCD*#";
7045 tmpptr = strchr(
context,
'&');
7047 tmpptr = strchr(
ext,
'&');
7068 memset(&svm, 0,
sizeof(svm));
7083 if (strcmp(vmu->
context,
"default"))
7084 snprintf(ext_context,
sizeof(ext_context),
"%s@%s",
ext, vmu->
context);
7098 ast_trace(-1,
"prefile: %s\n", prefile);
7104 ast_trace(-1,
"tempfile: %s\n", tempfile);
7114 ast_trace(-1,
"new prefile: %s\n", prefile);
7134 strncat(ecodes,
"0",
sizeof(ecodes) - strlen(ecodes) - 1);
7139 strncat(ecodes,
"0",
sizeof(ecodes) - strlen(ecodes) - 1);
7147 strncat(ecodes,
"*",
sizeof(ecodes) - strlen(ecodes) - 1);
7151 strncat(ecodes,
"*",
sizeof(ecodes) - strlen(ecodes) - 1);
7155 for (code = alldtmf; *code; code++) {
7158 if (strchr(ecodes, e[0]) ==
NULL
7162 strncat(ecodes, e,
sizeof(ecodes) - strlen(ecodes) - 1);
7169#if defined(ODBC_STORAGE)
7171#elif defined(IMAP_STORAGE)
7185 if (success == -1) {
7187 ast_trace(-1,
"Greeting '%s' not retrieved from database, but found in file storage. Inserting into database\n", prefile);
7192 ast_trace(-1,
"%s doesn't exist, doing what we can\n", prefile);
7259 if (greeting_only) {
7260 ast_debug(3,
"Greetings only VM (maxmsg=0), Skipping voicemail recording\n");
7284 res =
inboxcount(ext_context, &newmsgs, &oldmsgs);
7291 if (!(vms = get_vm_state_by_mailbox(
ext,
context, 0))) {
7296 if (!(vms = create_vm_state_from_user(vmu))) {
7306 msgnum = newmsgs + oldmsgs;
7307 ast_debug(3,
"Messagecount set to %d\n", msgnum);
7312 if ((res = imap_check_limits(chan, vms, vmu, msgnum))) {
7327 snprintf(tmptxtfile,
sizeof(tmptxtfile),
"%s/XXXXXX", tmpdir);
7328 ast_trace(-1,
"Tempfile: %s\n", tmptxtfile);
7329 txtdes = mkstemp(tmptxtfile);
7353 snprintf(origtime,
sizeof(origtime),
"%ld", (
long) time(
NULL));
7365 "callerid", callerid,
7367 "origtime", origtime,
7368 "category",
S_OR(category,
""),
7369 "filename", tmptxtfile,
7374 txt = fdopen(txtdes,
"w+");
7384 "; Message Information file\n"
7406 date, (
long) time(
NULL),
7407 category ? category :
"",
7409 ast_trace(-1,
"Saving txt file mbox: %s msg_id: %s\n",
ext, msg_id);
7420 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);
7426 if (!strcmp(
flag,
"Urgent")) {
7431 fprintf(txt,
"flag=%s\n",
flag);
7432 if (sound_duration < vmu->
minsecs) {
7434 ast_verb(3,
"Recording was %d seconds long but needs to be at least %d - abandoning\n", sound_duration, vmu->
minsecs);
7442 fprintf(txt,
"duration=%d\n", duration);
7451 ast_debug(1,
"The recorded media file is gone, so we should remove the .txt file too!\n");
7471 snprintf(txtfile,
sizeof(txtfile),
"%s.txt", fn);
7473 ast_trace(-1,
"Renaming recordings '%s' -> fn '%s'\n", tmptxtfile, fn);
7477 ast_trace(-1,
"Renaming txt file '%s' -> fn '%s'\n", tmptxtfile, txtfile);
7478 rename(tmptxtfile, txtfile);
7487 snprintf(tmpdur,
sizeof(tmpdur),
"%d", duration);
7498 store_failed = odbc_store_message(dir, vmu->
mailbox, vmu->
context, msgnum);
7510 SCOPE_CALL(-1,
STORE, dir, vmu->
mailbox, vmu->
context, msgnum, chan, vmu, fmt, duration, vms,
flag, msg_id);
7521 exten =
strsep(&tmpptr,
"&");
7522 cntx = strchr(exten,
'@');
7527 memset(&recipu, 0,
sizeof(recipu));
7528 if ((recip =
find_user(&recipu, cntx, exten))) {
7560 }
else if (res > 0 && res !=
't')
7563 if (sound_duration < vmu->
minsecs)
7575 ast_debug(3,
"*** Checking if we can expunge, expungeonhangup set to %d\n", expungeonhangup);
7576 if (expungeonhangup == 1 && vms->mailstream !=
NULL) {
7578#ifdef HAVE_IMAP_TK2006
7579 if (LEVELUIDPLUS (vms->mailstream)) {
7580 mail_expunge_full(vms->mailstream, NIL, EX_UID);
7583 mail_expunge(vms->mailstream);
7592#if !defined(IMAP_STORAGE)
7605 for (x = 0, dest = 0; dest != stopcount && x <
MAXMSGLIMIT; x++) {
7641 snprintf(sequence,
sizeof(sequence),
"%ld", vms->msgArray[msg]);
7643 ast_debug(3,
"Copying sequence %s to mailbox %s\n", sequence,
mbox(vmu, box));
7647 mail_setflag(vms->mailstream, sequence,
"\\Seen");
7649 mail_clearflag(vms->mailstream, sequence,
"\\Seen");
7661 if (vms->mailstream && !mail_status(vms->mailstream,
mailbox, SA_UIDNEXT)) {
7662 if (mail_create(vms->mailstream,
mailbox) != NIL) {
7668 if (init_mailstream(vms, curr_mbox) || !vms->mailstream) {
7673 res = !mail_move(vms->mailstream, sequence, (
char *)
mbox(vmu, box));
7675 res = !mail_copy(vms->mailstream, sequence, (
char *)
mbox(vmu, box));
7687 const char *dbox =
mbox(vmu, box);
7689 SCOPE_ENTER(3,
"dir: %s msg: %d box: %d dbox: %s move? %d \n", dir, msg, box, dbox, move);
7701 ast_trace(-1,
"Deleting message %d\n", msg);
7703 for (i = 1; i <= x; i++) {
7706 make_file(dfn,
sizeof(dfn), ddir, i - 1);
7720 if (strcmp(sfn, dfn)) {
7721 ast_trace(-1,
"Copying message '%s' to '%s'\n", sfn, dfn);
7743 unsigned char buf[256];
7775 bytes += ast_adsi_logo(
buf);
7819 for (x = 0; x < 5; x++) {
7820 snprintf(num,
sizeof(num),
"%d", x);
7848 ast_debug(1,
"Done downloading scripts...\n");
7856 ast_debug(1,
"Restarting session...\n");
7892 unsigned char buf[256];
7894 unsigned char keys[8];
7899 for (x = 0; x < 8; x++)
7918 unsigned char buf[256];
7920 unsigned char keys[8];
7925 for (x = 0; x < 8; x++)
7940 unsigned char buf[256];
7942 unsigned char keys[8];
7948 for (x = 0; x < 5; x++) {
7970 unsigned char buf[256];
7971 char buf1[256], buf2[256];
7977 char datetime[21] =
"";
7980 unsigned char keys[8];
7988 snprintf(fn2,
sizeof(fn2),
"%s.txt", vms->
fn);
7989 f = fopen(fn2,
"r");
7992 if (!fgets((
char *)
buf,
sizeof(
buf), f)) {
7996 char *stringp =
NULL;
7997 stringp = (
char *)
buf;
8001 if (!strcmp((
char *)
buf,
"callerid"))
8003 if (!strcmp((
char *)
buf,
"origdate"))
8011 for (x = 0; x < 5; x++)
8038 name =
"Unknown Caller";
8054 snprintf(buf1,
sizeof(buf1),
"%s%s", vms->
curbox,
8055 strcasecmp(vms->
curbox,
"INBOX") ?
" Messages" :
"");
8056 snprintf(buf2,
sizeof(buf2),
"Message %d of %d", vms->
curmsg + 1, vms->
lastmsg + 1);
8072 unsigned char buf[256];
8073 unsigned char keys[8];
8081 for (x = 0; x < 5; x++)
8123 unsigned char buf[256] =
"";
8124 char buf1[256] =
"", buf2[256] =
"";
8126 unsigned char keys[8];
8129 char *newm = (vms->
newmessages == 1) ?
"message" :
"messages";
8130 char *oldm = (vms->
oldmessages == 1) ?
"message" :
"messages";
8134 snprintf(buf1,
sizeof(buf1),
"You have %d new", vms->
newmessages);
8136 strncat(buf1,
" and",
sizeof(buf1) - strlen(buf1) - 1);
8137 snprintf(buf2,
sizeof(buf2),
"%d old %s.", vms->
oldmessages, oldm);
8139 snprintf(buf2,
sizeof(buf2),
"%s.", newm);
8142 snprintf(buf1,
sizeof(buf1),
"You have %d old", vms->
oldmessages);
8143 snprintf(buf2,
sizeof(buf2),
"%s.", oldm);
8145 strcpy(buf1,
"You have no messages.");
8153 for (x = 0; x < 6; x++)
8170 unsigned char buf[256] =
"";
8171 char buf1[256] =
"", buf2[256] =
"";
8173 unsigned char keys[8];
8176 char *mess = (vms->
lastmsg == 0) ?
"message" :
"messages";
8182 for (x = 0; x < 6; x++)
8191 snprintf(buf1,
sizeof(buf1),
"%s%s has", vms->
curbox,
8192 strcasecmp(vms->
curbox,
"INBOX") ?
" folder" :
"");
8195 snprintf(buf2,
sizeof(buf2),
"%d %s.", vms->
lastmsg + 1, mess);
8197 strcpy(buf2,
"no messages.");
8226 unsigned char buf[256];
8252 for (x = start; x < 5; x++) {
8258 snprintf(fn,
sizeof(fn),
"vm-%s",
mbox(
NULL, x));
8267 ast_verb(4,
"Failed to find file %s; falling back to INBOX\n", fn);
8295 for (x = start; x < 5; x++) {
8299 snprintf(fn,
sizeof(fn),
"vm-%s",
mbox(
NULL, x));
8335 while (((res <
'0') || (res >
'9')) &&
8336 (res !=
'#') && (res >= 0) &&
8351 isprint(res) ? res :
'?', isprint(res) ? res :
'?');
8374 int curmsg,
char *vm_fmts,
char *
context,
signed char record_gain,
long *duration,
8378 int retries = 0, prepend_duration = 0, already_recorded = 0;
8384 signed char zero_gain = 0;
8386 const char *msg_id =
NULL;
8388 const char *duration_str;
8392 make_file(msgfile,
sizeof(msgfile), curdir, curmsg);
8393 ast_trace(-1,
"msgfile: %s\n", msgfile);
8394 strcpy(textfile, msgfile);
8395 strcpy(backup, msgfile);
8396 strcpy(backup_textfile, msgfile);
8397 strncat(textfile,
".txt",
sizeof(textfile) - strlen(textfile) - 1);
8398 strncat(backup,
"-bak",
sizeof(backup) - strlen(backup) - 1);
8399 strncat(backup_textfile,
"-bak.txt",
sizeof(backup_textfile) - strlen(backup_textfile) - 1);
8402 *duration = atoi(duration_str);
8407 while ((cmd >= 0) && (cmd !=
't') && (cmd !=
'*')) {
8418 make_file(vms->introfn,
sizeof(vms->introfn), curdir, curmsg);
8419 strncat(vms->introfn,
"intro",
sizeof(vms->introfn));
8422 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);
8430 ast_trace(-1,
"Prepending to message %d\n", curmsg);
8432 make_file(msgfile,
sizeof(msgfile), curdir, curmsg);
8433 ast_trace(-1,
"msgfile: %s\n", msgfile);
8435 strcpy(textfile, msgfile);
8436 strncat(textfile,
".txt",
sizeof(textfile) - 1);
8447 if (already_recorded) {
8448 ast_trace(-1,
"Restoring '%s' to '%s'\n", backup, msgfile);
8450 copy(backup_textfile, textfile);
8453 ast_trace(-1,
"Backing up '%s' to '%s'\n", backup, msgfile);
8455 copy(textfile, backup_textfile);
8458 already_recorded = 1;
8463 cmd =
SCOPE_CALL_WITH_INT_RESULT(-1,
ast_play_and_prepend, chan,
NULL, msgfile, 0, vm_fmts, &prepend_duration,
NULL, 1,
silencethreshold,
maxsilence);
8476 *duration = atoi(duration_str);
8478 if (prepend_duration) {
8481 char duration_buf[12];
8483 *duration += prepend_duration;
8484 ast_trace(-1,
"Prepending duration: %d total duration: %ld\n", prepend_duration, *duration);
8486 snprintf(duration_buf,
sizeof(duration_buf),
"%ld", *duration);
8497 *vms->introfn =
'\0';
8506 already_recorded = 0;
8524 isprint(cmd) ? cmd :
'?', isprint(cmd) ? cmd :
'?');
8530 if (prepend_duration)
8531 *duration = prepend_duration;
8533 if (already_recorded && cmd == -1) {
8535 ast_trace(-1,
"Restoring '%s' to '%s'\n", backup, msgfile);
8537 rename(backup_textfile, textfile);
8540 if (cmd ==
't' || cmd ==
'S') {
8546static void queue_mwi_event(
const char *channel_id,
const char *box,
int urgent,
int new,
int old)
8555 ast_debug(3,
"Queueing event for mailbox %s New: %d Old: %d\n", box,
new + urgent, old);
8568 ast_debug(3,
"Found alias mapping: %s -> %s\n", mapping->
alias, box);
8594 int newmsgs = 0, oldmsgs = 0, urgentmsgs = 0;
8595 const char *category;
8607 snprintf(todir,
sizeof(todir),
"%simap",
VM_SPOOL_DIR);
8609 make_file(fn,
sizeof(fn), todir, msgnum);
8610 snprintf(ext_context,
sizeof(ext_context),
"%s@%s", vmu->
mailbox, vmu->
context);
8629 char *msg_id =
NULL;
8635 snprintf(filename,
sizeof(filename),
"%s.txt", fn);
8643 if (attach_user_voicemail)
8647 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);
8649 if (attach_user_voicemail)
8654 sendpage(myserveremail, vmu->
pager, msgnum, vmu->
context, vmu->
mailbox,
mbox(vmu, 0), cidnum, cidname, duration, vmu, category,
flag);
8658 DELETE(todir, msgnum, fn, vmu);
8713 char ecodes[16] =
"#";
8714 int res = 0, cmd = 0;
8719 const char mailbox_context[256];
8720 int saved_messages = 0;
8721 int valid_extensions = 0;
8724 char urgent_str[7] =
"";
8725 int prompt_played = 0;
8733 ast_copy_string(urgent_str, urgent ?
"Urgent" :
"",
sizeof(urgent_str));
8743 while (!res && !valid_extensions) {
8744 int use_directory = 0;
8749 while ((cmd >= 0) && !
done ){
8779 isprint(cmd) ? cmd :
'?', isprint(cmd) ? cmd :
'?');
8782 if (cmd < 0 || cmd ==
't')
8786 if (use_directory) {
8789 struct ast_app* directory_app;
8792 if (directory_app) {
8793 char vmcontext[256];
8803 snprintf(vmcontext,
sizeof(vmcontext),
"%s,,v", context ? context :
"default");
8804 res =
pbx_exec(chan, directory_app, vmcontext);
8820 if (res || prompt_played > 4)
8822 if ((res =
ast_readstring(chan, username,
sizeof(username) - 1, 2000, 10000,
"#")) < 0)
8830 s =
strsep(&stringp,
"*");
8832 valid_extensions = 1;
8834 snprintf((
char*)mailbox_context,
sizeof(mailbox_context),
"%s@%s", s, context ? context :
"default");
8835 if ((is_new_message == 1 || strcmp(s, sender->
mailbox)) && (receiver =
find_user(
NULL, context, s))) {
8840 if (
inboxcount(mailbox_context, &newmsgs, &oldmsgs)) {
8841 ast_log(
LOG_ERROR,
"Problem in calculating number of voicemail messages available for extension %s\n", mailbox_context);
8844 valid_extensions = 0;
8848 if (!(dstvms = get_vm_state_by_mailbox(s, context, 0))) {
8849 if (!(dstvms = create_vm_state_from_user(receiver))) {
8853 valid_extensions = 0;
8857 check_quota(dstvms, imapfolder);
8858 if (dstvms->quota_limit && dstvms->quota_usage >= dstvms->quota_limit) {
8859 ast_log(
LOG_NOTICE,
"Mailbox '%s' is exceeded quota %u >= %u\n", mailbox_context, dstvms->quota_usage, dstvms->quota_limit);
8861 valid_extensions = 0;
8870 if ((newmsgs + oldmsgs) >= capacity) {
8871 ast_log(
LOG_NOTICE,
"Mailbox '%s' is full with capacity of %d, prompting for another extension.\n", mailbox_context, capacity);
8873 valid_extensions = 0;
8894 valid_extensions = 0;
8912 s =
strsep(&stringp,
"*");
8915 if (valid_extensions)
8921 if (is_new_message == 1) {
8924 snprintf(mailbox,
sizeof(mailbox),
"%s@%s", username, context);
8927 memset(&leave_options, 0,
sizeof(leave_options));
8935 int copy_msg_result = 0;
8939 const char *msg_id =
NULL;
8942 memcpy(&vmstmp, vms,
sizeof(vmstmp));
8946 make_file(filename,
sizeof(filename), dir, curmsg);
8947 strncat(filename,
".txt",
sizeof(filename) - strlen(filename) - 1);
8955 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);
8959 int attach_user_voicemail;
8963 dstvms = get_vm_state_by_mailbox(vmtmp->mailbox, vmtmp->context, 0);
8965 dstvms = create_vm_state_from_user(vmtmp);
8968 init_mailstream(dstvms, 0);
8969 if (!dstvms->mailstream) {
8972 copy_msg_result =
STORE(vmstmp.
curdir, vmtmp->mailbox, vmtmp->context, curmsg, chan, vmtmp, fmt, duration, dstvms, urgent_str, msg_id);
8979 myserveremail = vmtmp->serveremail;
8982 sendmail(myserveremail, vmtmp, todircount, vmtmp->context, vmtmp->mailbox,
8986 vmstmp.
fn, vmstmp.introfn, fmt, duration, attach_user_voicemail, chan,
8987 NULL, urgent_str, msg_id);
8989 copy_msg_result =
SCOPE_CALL_WITH_INT_RESULT(-1,
copy_message, chan, sender, 0, curmsg, duration, vmtmp, fmt, dir, urgent_str,
NULL);
8999 if (saved_messages > 0 && !copy_msg_result) {
9016 make_file(msgfile,
sizeof(msgfile), dir, curmsg);
9017 strcpy(textfile, msgfile);
9018 strcpy(backup, msgfile);
9019 strcpy(backup_textfile, msgfile);
9020 strncat(textfile,
".txt",
sizeof(textfile) - strlen(textfile) - 1);
9021 strncat(backup,
"-bak",
sizeof(backup) - strlen(backup) - 1);
9022 strncat(backup_textfile,
"-bak.txt",
sizeof(backup_textfile) - strlen(backup_textfile) - 1);
9025 rename(backup_textfile, textfile);
9032 make_file(msgfile,
sizeof(msgfile), dir, curmsg);
9033 strcpy(textfile, msgfile);
9034 strcpy(backup_textfile, msgfile);
9035 strncat(textfile,
".txt",
sizeof(textfile) - strlen(textfile) - 1);
9036 strncat(backup_textfile,
"-bak.txt",
sizeof(backup_textfile) - strlen(backup_textfile) - 1);
9037 rename(backup_textfile, textfile);
9112 if (time_now.tm_year == time_then.tm_year)
9113 snprintf(temp,
sizeof(temp),
"%d", time_now.tm_yday);
9115 snprintf(temp,
sizeof(temp),
"%d", (time_now.tm_year - time_then.tm_year) * 365 + (time_now.tm_yday - time_then.tm_yday));
9161 char *callerid, *
name;
9171 if ((cid ==
NULL)||(context ==
NULL))
9175 ast_debug(1,
"VM-CID: composite caller ID received: %s, context: %s\n", cid, context);
9187 snprintf(prefile,
sizeof(prefile),
"%s%s/%s/greet",
VM_SPOOL_DIR, context, callerid);
9192 ast_verb(3,
"Playing envelope info: CID number '%s' matches mailbox number, playing recorded name\n", callerid);
9197 ast_verb(3,
"Playing envelope info: message from '%s'\n", callerid);
9200 res =
wait_file2(chan, vms,
"vm-from-extension");
9206 ast_debug(1,
"VM-CID: Numeric caller id: (%s)\n", callerid);
9212 ast_verb(3,
"Playing recorded name for CID number '%s' - '%s'\n", callerid,prefile);
9215 ast_verb(3,
"Played recorded name result '%d'\n", res);
9218 wait_file2(chan, vms,
"vm-from-phonenumber");
9227 ast_debug(1,
"VM-CID: From an unknown number\n");
9229 res =
wait_file2(chan, vms,
"vm-unknown-caller");
9240 if (duration ==
NULL)
9244 durations = atoi(duration);
9245 durationm = (durations / 60);
9247 ast_debug(1,
"VM-Duration: duration is: %d seconds converted to: %d minutes\n", durations, durationm);
9249 if ((!res) && (durationm >= minduration)) {
9254 div_t num = div(durationm, 10);
9256 if (durationm == 1) {
9259 }
else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
9288 const char *origtime, *context, *category, *duration, *
flag;
9303 snprintf(filename,
sizeof(filename),
"%s.txt", vms->
fn);
9324 ten = (vms->
curmsg + 1) / 10;
9325 one = (vms->
curmsg + 1) % 10;
9328 snprintf(nextmsg,
sizeof(nextmsg),
"digits/n-%d", vms->
curmsg + 1);
9331 snprintf(nextmsg,
sizeof(nextmsg),
"digits/n-%d", ten * 10);
9335 snprintf(nextmsg,
sizeof(nextmsg),
"digits/n-%d", one);
9377 res =
wait_file2(chan, vms,
"vm-meddelandet");
9444 isprint(res) ? res :
'?', isprint(res) ? res :
'?');
9451static int imap_remove_file(
char *dir,
int msgnum)
9459 snprintf(
intro,
sizeof(
intro),
"%sintro", fn);
9463 if ((msgnum < 0 && imapgreetings) || msgnum > -1) {
9468 snprintf(full_fn,
sizeof(full_fn),
"%s.txt", fn);
9476static int imap_delete_old_greeting (
char *dir,
struct vm_state *vms)
9478 char *
file, *filename;
9488 ast_log(
AST_LOG_ERROR,
"Failed to procure file name from directory passed. You should never see this.\n");
9503 for (i = 0; i < vms->mailstream->nmsgs; i++) {
9504 mail_fetchstructure(vms->mailstream, i + 1, &body);
9506 if (body->nested.part->next && body->nested.part->next->body.parameter->value) {
9507 char *attachment = body->nested.part->next->body.parameter->value;
9508 char copy[strlen(attachment) + 1];
9510 strcpy(
copy, attachment);
9513 filename =
strsep(&attachment,
".");
9514 if (!strcmp(filename, file)) {
9515 snprintf(arg,
sizeof(arg),
"%d", i + 1);
9516 mail_setflag(vms->mailstream, arg,
"\\DELETED");
9524 mail_expunge(vms->mailstream);
9526 if (curr_mbox != -1) {
9528 if (init_mailstream(vms, curr_mbox) || !vms->mailstream) {
9537#elif !defined(IMAP_STORAGE)
9540 int count_msg, last_msg;
9541 SCOPE_ENTER(3,
"user: %s dir: %s msg: %d box %d\n",
9556 if (count_msg < 0) {
9581 if (last_msg < -1) {
9583 }
else if (vms->
lastmsg != last_msg) {
9584 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);
9595 int last_msg_idx = 0;
9598 int res = 0, nummsg;
9605 ast_trace(-1,
"No messages in mailbox\n");
9618 if (last_msg_idx != vms->
lastmsg) {
9623 for (x = 0; x < last_msg_idx + 1; x++) {
9632 if (strcmp(vms->
fn, fn2)) {
9649 ast_trace(-1,
"Unable to lock path. Not moving message to deleted folder.\n");
9668 for (x = vms->
curmsg + 1; x <= nummsg; x++) {
9682 for (x = last_msg_idx - 1; x >= 0; x--) {
9723 if (!strcasecmp(box,
"vm-INBOX") || !strcasecmp(box,
"vm-Old")){
9736 if (!strcasecmp(box,
"vm-INBOX") || !strcasecmp(box,
"vm-Old")) {
9749 if (!strcasecmp(box,
"vm-INBOX") || !strcasecmp(box,
"vm-Old")) {
9750 if (!strcasecmp(box,
"vm-INBOX"))
9765 if (!strcasecmp(box,
"vm-Family") || !strcasecmp(box,
"vm-Friends") || !strcasecmp(box,
"vm-Work")){
10124 snprintf(recname,
sizeof(recname),
"digits/1kvk");
10126 snprintf(recname,
sizeof(recname),
"digits/%dhk", vms->
urgentmessages);
10139 snprintf(recname,
sizeof(recname),
"digits/1kvk");
10141 snprintf(recname,
sizeof(recname),
"digits/%dhk", vms->
newmessages);
10156 snprintf(recname,
sizeof(recname),
"digits/1kvk");
10158 snprintf(recname,
sizeof(recname),
"digits/%dhk", vms->
oldmessages);
10234 }
else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
10235 if (num.rem == 2) {
10261 }
else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
10262 if (num.rem == 2) {
10936 if (skipadvanced) {
10951 if (!res && !skipadvanced)
10966 int curmsg_deleted;
10975 if (!curmsg_deleted) {
11025 if (skipadvanced) {
11046 if (!res && !skipadvanced)
11061 int curmsg_deleted;
11069 if (!curmsg_deleted) {
11140 char newpassword[80] =
"";
11141 char newpassword2[80] =
"";
11143 unsigned char buf[256];
11160 cmd =
play_record_review(chan,
"vm-rec-name", prefile,
maxgreet, fmtc, 0, vmu, &duration,
NULL,
NULL, record_gain, vms,
NULL,
NULL, 0);
11161 if (cmd < 0 || cmd ==
't' || cmd ==
'#')
11170 cmd =
play_record_review(chan,
"vm-rec-unv", prefile,
maxgreet, fmtc, 0, vmu, &duration,
NULL,
NULL, record_gain, vms,
NULL,
NULL, 0);
11171 if (cmd < 0 || cmd ==
't' || cmd ==
'#')
11177 cmd =
play_record_review(chan,
"vm-rec-busy", prefile,
maxgreet, fmtc, 0, vmu, &duration,
NULL,
NULL, record_gain, vms,
NULL,
NULL, 0);
11178 if (cmd < 0 || cmd ==
't' || cmd ==
'#')
11188 newpassword[1] =
'\0';
11191 newpassword[0] =
'\0';
11192 if (cmd < 0 || cmd ==
't' || cmd ==
'#')
11194 cmd =
ast_readstring(chan, newpassword + strlen(newpassword),
sizeof(newpassword) - 1, 2000, 10000,
"#");
11195 if (cmd < 0 || cmd ==
't' || cmd ==
'#')
11202 newpassword2[1] =
'\0';
11205 newpassword2[0] =
'\0';
11206 if (cmd < 0 || cmd ==
't' || cmd ==
'#')
11208 cmd =
ast_readstring(chan, newpassword2 + strlen(newpassword2),
sizeof(newpassword2) - 1, 2000, 10000,
"#");
11209 if (cmd < 0 || cmd ==
't' || cmd ==
'#')
11211 if (!strcmp(newpassword, newpassword2))
11227 ast_debug(1,
"User %s set password to %s of length %d\n", vms->
username, newpassword, (
int) strlen(newpassword));
11238 char newpassword[80] =
"";
11239 char newpassword2[80] =
"";
11241 unsigned char buf[256];
11254 while ((cmd >= 0) && (cmd !=
't')) {
11260 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);
11264 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);
11268 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);
11278 newpassword[1] =
'\0';
11281 newpassword[0] =
'\0';
11285 if ((cmd =
ast_readstring(chan, newpassword + strlen(newpassword),
sizeof(newpassword) - 1, 2000, 10000,
"#")) < 0) {
11298 newpassword2[1] =
'\0';
11301 newpassword2[0] =
'\0';
11306 if ((cmd =
ast_readstring(chan, newpassword2 + strlen(newpassword2),
sizeof(newpassword2) - 1, 2000, 10000,
"#")) < 0) {
11310 if (strcmp(newpassword, newpassword2)) {
11326 ast_debug(1,
"User %s set password to %s of length %d\n",
11327 vms->
username, newpassword, (
int) strlen(newpassword));
11354 isprint(cmd) ? cmd :
'?', isprint(cmd) ? cmd :
'?');
11384 unsigned char buf[256];
11398 while ((cmd >= 0) && (cmd !=
't')) {
11403 cmd =
play_record_review(chan,
"vm-rec-temp", prefile,
maxgreet, fmtc, 0, vmu, &duration,
NULL,
NULL, record_gain, vms,
NULL,
NULL, 0);
11411 cmd =
play_record_review(chan,
"vm-rec-temp", prefile,
maxgreet, fmtc, 0, vmu, &duration,
NULL,
NULL, record_gain, vms,
NULL,
NULL, 0);
11414 DELETE(prefile, -1, prefile, vmu);
11424 "vm-tempgreeting2" :
"vm-tempgreeting");
11435 isprint(cmd) ? cmd :
'?', isprint(cmd) ? cmd :
'?');
11461 if (!strcasecmp(vms->
vmbox,
"vm-INBOX") ||!strcasecmp(vms->
vmbox,
"vm-Old")){
11463 snprintf(vms->
fn,
sizeof(vms->
fn),
"vm-%ss", vms->
curbox);
11472 snprintf(vms->
fn,
sizeof(vms->
fn),
"vm-%s", vms->
curbox);
11488 if (!strcasecmp(vms->
fn,
"INBOX")) {
11516 snprintf(vms->
fn,
sizeof(vms->
fn),
"vm-%s", vms->
curbox);
11544 snprintf(vms->
fn,
sizeof(vms->
fn),
"vm-%s", vms->
curbox);
11566 snprintf(vms->
fn,
sizeof(vms->
fn),
"vm-%s", vms->
curbox);
11597 snprintf(vms->
fn,
sizeof(vms->
fn),
"vm-%s", vms->
curbox);
11621 snprintf(vms->
fn,
sizeof(vms->
fn),
"vm-%s", vms->
curbox);
11651 snprintf(vms->
fn,
sizeof(vms->
fn),
"vm-%s", vms->
curbox);
11675 snprintf(vms->
fn,
sizeof(vms->
fn),
"vm-%s", vms->
curbox);
11718 int skipuser,
int max_logins,
int silent)
11720 int useadsi = 0, valid = 0, logretries = 0;
11726 if (!skipuser && useadsi)
11735 while (!valid && (logretries < max_logins)) {
11745 ast_verb(3,
"Username not entered\n");
11748 }
else if (
mailbox[0] ==
'*') {
11750 ast_verb(4,
"Mailbox begins with '*', attempting jump to extension 'a'\n");
11755 ast_verb(4,
"Jump to extension 'a' failed; setting mailbox to NULL\n");
11763 char fullusername[80];
11766 strncat(fullusername,
mailbox,
sizeof(fullusername) - 1 - strlen(fullusername));
11771 memset(&vmus, 0,
sizeof(vmus));
11790 ast_verb(4,
"Password begins with '*', attempting jump to extension 'a'\n");
11797 ast_verb(4,
"Jump to extension 'a' failed; setting mailbox and user to NULL\n");
11807 if (passptr[0] ==
'-') passptr++;
11809 if (vmu && !strcmp(passptr,
password))
11818 if (skipuser || logretries >= max_logins) {
11839 if (!valid && (logretries >= max_logins)) {
11845 if (vmu && !skipuser) {
11854 const char *msg_id)
11903 memset(&vmus, 0,
sizeof(vmus));
11904 memset(&vms, 0,
sizeof(vms));
11907 goto play_msg_cleanup;
11919 goto play_msg_cleanup;
11931 goto play_msg_cleanup;
11947 vmstate_delete(&vms);
11997#define VMBOX_STRING_HEADER_FORMAT "%-32.32s %-32.32s %-16.16s %-16.16s %-16.16s %-16.16s\n"
11998#define VMBOX_STRING_DATA_FORMAT "%-32.32s %-32.32s %-16.16s %-16.16s %-16.16s %-16.16s\n"
12004 memset(&vmus, 0,
sizeof(vmus));
12005 memset(&vms, 0,
sizeof(vms));
12020#define VM_STRING_HEADER_FORMAT "%-8.8s %-32.32s %-32.32s %-9.9s %-6.6s %-30.30s\n"
12029 if (!mailbox_snapshot) {
12030 ast_cli(
a->fd,
"Can't create snapshot for voicemail user %s@%s\n", mailbox, context);
12036 for (i = 0; i < mailbox_snapshot->
folders; i++) {
12039 msg->flag,
msg->msg_id);
12061 const char *from_mailbox =
a->argv[2];
12062 const char *from_context =
a->argv[3];
12063 const char *from_folder =
a->argv[4];
12064 const char *
id[] = {
a->argv[5] };
12065 const char *to_mailbox =
a->argv[6];
12066 const char *to_context =
a->argv[7];
12067 const char *to_folder =
a->argv[8];
12068 int ret =
vm_msg_forward(from_mailbox, from_context, from_folder, to_mailbox, to_context, to_folder, 1,
id, 0);
12070 ast_cli(
a->fd,
"Error forwarding message %s from mailbox %s@%s %s to mailbox %s@%s %s\n",
12071 id[0], from_mailbox, from_context, from_folder, to_mailbox, to_context, to_folder);
12073 ast_cli(
a->fd,
"Forwarded message %s from mailbox %s@%s %s to mailbox %s@%s %s\n",
12074 id[0], from_mailbox, from_context, from_folder, to_mailbox, to_context, to_folder);
12081 const char *mailbox =
a->argv[2];
12082 const char *context =
a->argv[3];
12083 const char *from_folder =
a->argv[4];
12084 const char *
id[] = {
a->argv[5] };
12085 const char *to_folder =
a->argv[6];
12086 int ret =
vm_msg_move(mailbox, context, 1, from_folder,
id, to_folder);
12088 ast_cli(
a->fd,
"Error moving message %s from mailbox %s@%s %s to %s\n",
12089 id[0], mailbox, context, from_folder, to_folder);
12091 ast_cli(
a->fd,
"Moved message %s from mailbox %s@%s %s to %s\n",
12092 id[0], mailbox, context, from_folder, to_folder);
12099 const char *mailbox =
a->argv[2];
12100 const char *context =
a->argv[3];
12101 const char *folder =
a->argv[4];
12102 const char *
id[] = {
a->argv[5] };
12105 ast_cli(
a->fd,
"Error removing message %s from mailbox %s@%s %s\n",
12106 id[0], mailbox, context, folder);
12108 ast_cli(
a->fd,
"Removed message %s from mailbox %s@%s %s\n",
12109 id[0], mailbox, context, folder);
12116 const char *
word =
a->word;
12127 wordlen = strlen(
word);
12130 if (!strncasecmp(
word, vmu->
mailbox , wordlen)) {
12140 }
else if (pos == 4) {
12142 const char *box =
a->argv[3];
12143 wordlen = strlen(
word);
12165 e->
command =
"voicemail show mailbox";
12167 "Usage: voicemail show mailbox <mailbox> <context>\n"
12168 " Show contents of mailbox <mailbox>@<context>\n";
12176 if (
a->argc != 5) {
12206 const char *
word =
a->word;
12212 const char *
context =
"", *
mailbox =
"", *folder =
"", *
id =
"";
12215 if (pos > maxpos) {
12221 if (pos == 2 || (pos == 6 && maxpos == 8)) {
12223 wordlen = strlen(
word);
12226 if (!strncasecmp(
word, vmu->
mailbox , wordlen)) {
12236 }
else if (pos == 3 || pos == 7) {
12238 mailbox = (pos == 3) ?
a->argv[2] :
a->argv[6];
12239 wordlen = strlen(
word);
12252 }
else if (pos == 4 || pos == 8 || (pos == 6 && maxpos == 6) ) {
12255 wordlen = strlen(
word);
12262 }
else if (pos == 5) {
12266 mailbox =
a->argv[2];
12267 context =
a->argv[3];
12268 folder =
a->argv[4];
12269 wordlen = strlen(
word);
12281 if (
id && !strncasecmp(
word,
msg->msg_id, wordlen) && ++which >
state) {
12299 e->
command =
"voicemail forward";
12301 "Usage: voicemail forward <from_mailbox> <from_context> <from_folder> <messageid> <to_mailbox> <to_context> <to_folder>\n"
12302 " Forward message <messageid> in mailbox <mailbox>@<context> <from_folder>\n"
12303 " to mailbox <mailbox>@<context> <to_folder>\n";
12311 if (
a->argc != 9) {
12326 e->
command =
"voicemail move";
12328 "Usage: voicemail move <mailbox> <context> <from_folder> <messageid> <to_folder>\n"
12329 " Move message <messageid> in mailbox <mailbox>&<context> from <from_folder> to <to_folder>\n";
12337 if (
a->argc != 7) {
12352 e->
command =
"voicemail remove";
12354 "Usage: voicemail remove <mailbox> <context> <from_folder> <messageid>\n"
12355 " Remove message <messageid> from <from_folder> in mailbox <mailbox>@<context>\n";
12363 if (
a->argc != 6) {
12382 char prefixstr[80] =
"";
12383 char ext_context[256]=
"";
12390 int silentexit = 0;
12392 signed char record_gain = 0;
12394 int play_folder = 0;
12423 if (
args.argc == 2) {
12433 record_gain = (
signed char) gain;
12453 if (play_folder > 9 || play_folder < 0) {
12455 "Invalid value '%s' provided for folder autoplay option. Defaulting to 'INBOX'\n",
12465 while (*(
args.argv0)) {
12466 if (*(
args.argv0) ==
's')
12468 else if (*(
args.argv0) ==
'p')
12479 if ((context = strchr(
args.argv0,
'@')))
12533 pthread_once(&ts_vmstate.once, ts_vmstate.key_init);
12534 pthread_setspecific(ts_vmstate.key, &vms);
12536 vms.interactive = 1;
12540 vmstate_insert(&vms);
12541 init_vm_state(&vms);
12547 ast_channel_language_set(chan, vmu->
language);
12552 ast_trace(-1,
"Before open_mailbox\n");
12555 ast_trace(-1,
"open mailbox: %d\n", res);
12563 ast_trace(-1,
"open mailbox: %d\n", res);
12572 ast_trace(-1,
"open mailbox: %d\n", res);
12589 ast_trace(-1,
"open mailbox: %d\n", res);
12627 if ((cmd ==
't') || (cmd ==
'#')) {
12633 }
else if (cmd < 0) {
12642 ast_debug(3,
"Checking quotas: comparing %u to %u\n", vms.quota_usage, vms.quota_limit);
12643 if (vms.quota_limit && vms.quota_usage >= vms.quota_limit) {
12644 ast_debug(1,
"*** QUOTA EXCEEDED!!\n");
12661 isprint(cmd) ? cmd :
'?', isprint(cmd) ? cmd :
'?');
12665 while ((cmd > -1) && (cmd !=
't') && (cmd !=
'#')) {
12667 ast_trace(-1,
"Main menu: %d %c\n", cmd, (cmd >= 32 && cmd <= 126 ? cmd :
' '));
12683 isprint(cmd) ? cmd :
'?', isprint(cmd) ? cmd :
'?');
12686 }
else if (cmd > 0) {
12690 ast_trace(-1,
"close mailbox: %d\n", res);
12694 if (cmd != 11) in_urgent = 0;
12697 ast_trace(-1,
"open mailbox: %d\n", res);
12717 while ((cmd > -1) && (cmd !=
't') && (cmd !=
'#')) {
12724 ast_trace(-1,
"advanced options: %d\n", cmd);
12734 ast_verb(3,
"Callback Requested\n");
12737 ast_trace(-1,
"advanced options: %d\n", cmd);
12755 ast_trace(-1,
"advanced options: %d\n", cmd);
12782 ast_trace(-1,
"forward message: %d\n", cmd);
12825 isprint(cmd) ? cmd :
'?', isprint(cmd) ? cmd :
'?');
12848 ast_trace(-1,
"close mailbox: %d\n", res);
12853 ast_trace(-1,
"open mailbox: %d\n", res);
12856 ast_debug(1,
"No more new messages, opened INBOX and got %d Urgent messages\n", vms.
lastmsg + 1);
12883 ast_trace(-1,
"close mailbox: %d\n", res);
12888 ast_trace(-1,
"open mailbox: %d\n", res);
12891 ast_debug(1,
"No more urgent messages, opened INBOX and got %d new messages\n", vms.
lastmsg + 1);
12910 if (play_folder == 0) {
12917 else if (play_folder == 1)
12921 if (play_folder == 0) {
12928 else if (play_folder == 1)
12944 if (in_urgent == 1) {
12949 ast_trace(-1,
"close mailbox: %d\n", res);
12954 ast_trace(-1,
"open mailbox: %d\n", res);
12957 ast_debug(1,
"No more urgent messages, opened INBOX and got %d new messages\n", vms.
lastmsg + 1);
12979 ast_trace(-1,
"forward message: %d\n", res);
12992 ast_trace(-1,
"close mailbox: %d\n", res);
12997 ast_trace(-1,
"open mailbox: %d\n", res);
13000 ast_debug(1,
"No more urgent messages, opened INBOX and got %d new messages\n", vms.
lastmsg + 1);
13021 isprint(cmd) ? cmd :
'?', isprint(cmd) ? cmd :
'?');
13026 }
else if (cmd > 0) {
13027 box = cmd = cmd -
'0';
13031 ast_trace(-1,
"save to folder: %d\n", res);
13033#ifndef IMAP_STORAGE
13045 snprintf(vms.
fn,
sizeof(vms.
fn),
"vm-%s",
mbox(vmu, box));
13074 ast_trace(-1,
"close mailbox: %d\n", res);
13079 ast_trace(-1,
"open mailbox: %d\n", res);
13082 ast_debug(1,
"No more urgent messages, opened INBOX and got %d new messages\n", vms.
lastmsg + 1);
13131 ast_trace(-1,
"open mailbox: %d\n", res);
13142 if ((cmd ==
't') || (cmd ==
'#')) {
13170 int new = 0, old = 0, urgent = 0;
13171 snprintf(ext_context,
sizeof(ext_context),
"%s@%s", vms.
username, vmu->
context);
13179 ast_debug(3,
"*** Checking if we can expunge, deleted set to %d, expungeonhangup set to %d\n", deleted, expungeonhangup);
13180 if (vmu && deleted == 1 && expungeonhangup == 1 && vms.mailstream !=
NULL) {
13182#ifdef HAVE_IMAP_TK2006
13183 if (LEVELUIDPLUS (vms.mailstream)) {
13184 mail_expunge_full(vms.mailstream, NIL, EX_UID);
13187 mail_expunge(vms.mailstream);
13193 vmstate_delete(&vms);
13200 pthread_setspecific(ts_vmstate.key,
NULL);
13218 memset(&leave_options, 0,
sizeof(leave_options));
13223 if (
args.argc == 2) {
13249 res =
ast_app_getdata(chan,
"vm-whichbox", temp,
sizeof(temp) - 1, 0);
13299 ast_log(
LOG_ERROR,
"Voicemail data file %s/%d.txt has no [message] category?\n", dir, msg);
13320 ast_log(
LOG_WARNING,
"Mailbox %s in context %s begins with '*' character. The '*' character,"
13321 "\n\twhen it is the first character in a mailbox or password, is used to jump to a"
13322 "\n\tpredefined extension 'a'. A mailbox or password beginning with '*' is not valid"
13323 "\n\tand will be ignored.\n", box,
context);
13330 ast_log(
LOG_WARNING,
"\nIt has been detected that you have defined mailbox '%s' in separate\
13331 \n\tcontexts and that you have the 'searchcontexts' option on. This type of\
13332 \n\tconfiguration creates an ambiguity that you likely do not want. Please\
13333 \n\tamend your voicemail.conf file to avoid this situation.\n", box);
13363 int new = 0, old = 0, urgent = 0;
13374 if ((s =
strsep(&stringp,
","))) {
13377 "\n\tmust be reset in voicemail.conf.\n", box);
13382 if (stringp && (s =
strsep(&stringp,
","))) {
13385 if (stringp && (s =
strsep(&stringp,
","))) {
13388 if (stringp && (s =
strsep(&stringp,
","))) {
13408 imap_logout(mailbox_full);
13415#ifdef TEST_FRAMEWORK
13421 static const char options_string[] =
"attach=yes|attachfmt=wav49|"
13422 "serveremail=someguy@digium.com|fromstring=Voicemail System|tz=central|delete=yes|saycid=yes|"
13423 "sendvoicemail=yes|review=yes|tempgreetwarn=yes|messagewrap=yes|operator=yes|leaveurgent=yes|"
13424 "envelope=yes|moveheard=yes|sayduration=yes|saydurationm=5|forcename=yes|"
13425 "forcegreetings=yes|callback=somecontext|dialout=somecontext2|"
13426 "exitcontext=somecontext3|minsecs=10|maxsecs=100|nextaftercmd=yes|"
13427 "backupdeleted=50|volgain=1.3|passwordlocation=spooldir|emailbody="
13428 "Dear ${VM_NAME}:\n\n\tYou were just left a ${VM_DUR} long message|emailsubject="
13429 "[PBX]: New message \\\\${VM_MSGNUM}\\\\ in mailbox ${VM_MAILBOX}";
13431 static const char option_string2[] =
"imapuser=imapuser|imappassword=imappasswd|"
13432 "imapfolder=INBOX|imapvmshareid=6000|imapserver=imapserver|imapport=1234|imapflags=flagged";
13437 info->name =
"vmuser";
13438 info->category =
"/apps/app_voicemail/";
13439 info->summary =
"Vmuser unit test";
13440 info->description =
13441 "This tests passing all supported parameters to apply_options, the voicemail user config parser";
13459 if (strcasecmp(vmu->
attachfmt,
"wav49")) {
13463 if (strcasecmp(vmu->
fromstring,
"Voicemail System")) {
13467 if (strcasecmp(vmu->
serveremail,
"someguy@digium.com")) {
13471 if (!vmu->
emailsubject || strcasecmp(vmu->
emailsubject,
"[PBX]: New message \\${VM_MSGNUM}\\ in mailbox ${VM_MAILBOX}")) {
13475 if (!vmu->
emailbody || strcasecmp(vmu->
emailbody,
"Dear ${VM_NAME}:\n\n\tYou were just left a ${VM_DUR} long message")) {
13479 if (strcasecmp(vmu->
zonetag,
"central")) {
13539 if (strcasecmp(vmu->
callback,
"somecontext")) {
13543 if (strcasecmp(vmu->
dialout,
"somecontext2")) {
13547 if (strcasecmp(vmu->
exit,
"somecontext3")) {
13578 if (strcasecmp(vmu->imapuser,
"imapuser")) {
13582 if (strcasecmp(vmu->imappassword,
"imappasswd")) {
13586 if (strcasecmp(vmu->imapfolder,
"INBOX")) {
13590 if (strcasecmp(vmu->imapvmshareid,
"6000")) {
13594 if (strcasecmp(vmu->imapserver,
"imapserver")) {
13598 if (strcasecmp(vmu->imapport,
"1234")) {
13602 if (strcasecmp(vmu->imapflags,
"flagged")) {
13632 ast_log(
LOG_ERROR,
"VM_INFO requires an argument (<mailbox>[@<context>],attribute[,folder])\n");
13642 ast_log(
LOG_ERROR,
"VM_INFO requires an argument (<mailbox>[@<context>],attribute[,folder])\n");
13646 memset(&svm, 0,
sizeof(svm));
13649 if (!strncasecmp(arg.attribute,
"exists", 5)) {
13656 if (!strncasecmp(arg.attribute,
"password", 8)) {
13658 }
else if (!strncasecmp(arg.attribute,
"fullname", 8)) {
13660 }
else if (!strncasecmp(arg.attribute,
"email", 5)) {
13662 }
else if (!strncasecmp(arg.attribute,
"pager", 5)) {
13664 }
else if (!strncasecmp(arg.attribute,
"language", 8)) {
13666 }
else if (!strncasecmp(arg.attribute,
"locale", 6)) {
13668 }
else if (!strncasecmp(arg.attribute,
"tz", 2)) {
13670 }
else if (!strncasecmp(arg.attribute,
"count", 5)) {
13679 ast_log(
LOG_ERROR,
"Unable to retrieve message count for mailbox %s\n", arg.mailbox_context);
13683 snprintf(
buf,
len,
"%d", res);
13685 ast_log(
LOG_ERROR,
"Unknown attribute '%s' for VM_INFO\n", arg.attribute);
13705 int silent = 0, skipuser = 0;
13731 }
else if (
mailbox[0] ==
'*') {
13744 const char *cat =
NULL;
13753 "=============================================================\n"
13754 "=== Configured Voicemail Users ==============================\n"
13755 "=============================================================\n"
13761 "=== Mailbox ...\n"
13767 "=== ---------------------------------------------------------\n"
13772 "=============================================================\n"
13791 wordlen = strlen(
word);
13812#define HVSU_OUTPUT_FORMAT "%-10s %-5s %-25s %-10s %6s\n"
13814 int users_counter = 0;
13818 e->
command =
"voicemail show users [for]";
13820 "Usage: voicemail show users [for <context>]\n"
13821 " Lists all mailboxes currently set up\n";
13827 if ((
a->argc < 3) || (
a->argc > 5) || (
a->argc == 4))
13829 if (
a->argc == 5) {
13830 if (strcmp(
a->argv[3],
"for"))
13837 ast_cli(
a->fd,
"You must specify a specific context to show users from realtime!\n");
13845 ast_cli(
a->fd,
"There are no voicemail users currently defined\n");
13868 int newmsgs = 0, oldmsgs = 0;
13869 char count[12], tmp[256] =
"";
13874 snprintf(count,
sizeof(count),
"%d", newmsgs);
13880 ast_cli(
a->fd,
"%d voicemail users configured.\n", users_counter);
13888#define HVSZ_OUTPUT_FORMAT "%-15s %-20s %-45s\n"
13893 e->
command =
"voicemail show zones";
13895 "Usage: voicemail show zones\n"
13896 " Lists zone message formats\n";
13912 ast_cli(
a->fd,
"There are no voicemail zones currently defined\n");
13925#define ALIASES_OUTPUT_FORMAT "%-32s %-32s\n"
13930 e->
command =
"voicemail show aliases";
13932 "Usage: voicemail show aliases\n"
13933 " Lists mailbox aliases\n";
13943 ast_cli(
a->fd,
"Aliases are not enabled\n");
13965 e->
command =
"voicemail reload";
13967 "Usage: voicemail reload\n"
13968 " Reload voicemail configuration\n";
13977 ast_cli(
a->fd,
"Reloading voicemail configuration...\n");
13996 int new = 0, old = 0, urgent = 0;
14006 if (imap_poll_logout) {
14022 struct timespec ts = { 0, };
14023 struct timeval wait;
14032 ts.tv_sec = wait.tv_sec;
14033 ts.tv_nsec = wait.tv_usec * 1000;
14044static void imap_logout(
const char *mailbox_id)
14057 memset(&vmus, 0,
sizeof(vmus));
14059 if (!(vmu =
find_user(&vmus,
context, mailbox)) || vmu->imapuser[0] ==
'\0') {
14063 vms = get_vm_state_by_imapuser(vmu->imapuser, 0);
14065 vms = get_vm_state_by_mailbox(mailbox,
context, 0);
14072 vms->mailstream = mail_close(vms->mailstream);
14075 vmstate_delete(vms);
14078static int imap_close_subscribed_mailbox(
struct ast_mwi_state *mwi_state,
void *data)
14101 imap_close_subscribed_mailbox(mwi_state,
NULL);
14175 const char* event_name,
14176 const char* actionid
14184 if((s ==
NULL) || (vmu ==
NULL) || (event_name ==
NULL) || (actionid ==
NULL)) {
14204 ast_log(
LOG_ERROR,
"Could not get mailbox count. user[%s], context[%s]\n",
14212 "VMContext: %s\r\n"
14213 "VoiceMailbox: %s\r\n"
14217 "ServerEmail: %s\r\n"
14218 "FromString: %s\r\n"
14219 "MailCommand: %s\r\n"
14225 "ExitContext: %s\r\n"
14226 "SayDurationMinimum: %d\r\n"
14227 "SayEnvelope: %s\r\n"
14229 "AttachMessage: %s\r\n"
14230 "AttachmentFormat: %s\r\n"
14231 "DeleteMessage: %s\r\n"
14232 "VolumeGain: %.2f\r\n"
14233 "CanReview: %s\r\n"
14234 "CanMarkUrgent: %s\r\n"
14235 "CallOperator: %s\r\n"
14236 "MaxMessageCount: %d\r\n"
14237 "MaxMessageLength: %d\r\n"
14238 "NewMessageCount: %d\r\n"
14239 "OldMessageCount: %d\r\n"
14242 "IMAPServer: %s\r\n"
14244 "IMAPFlags: %s\r\n"
14300 const char* event_name,
14301 const char* actionid)
14305 int nummessages = 0;
14310 if (!mailbox_snapshot) {
14318 for (i = 0; i < mailbox_snapshot->
folders; i++) {
14363 (at = strchr(mwi_state->
uniqueid,
'@')) &&
14367 (at = strchr(mwi_state->
uniqueid,
'@')) &&
14368 strcmp(context, at + 1) == 0) ||
14371 (at = strchr(mwi_state->
uniqueid,
'@')) &&
14373 strcmp(context, at + 1) == 0)
14393 char actionid[128];
14405 actionid[0] =
'\0';
14407 snprintf(actionid,
sizeof(actionid),
"ActionID: %s\r\n",
id);
14411 memset(&svm, 0,
sizeof(svm));
14415 astman_send_ack(s, m,
"There is no voicemail user of the given info.");
14439 char actionid[128];
14443 actionid[0] =
'\0';
14445 snprintf(actionid,
sizeof(actionid),
"ActionID: %s\r\n",
id);
14451 astman_send_ack(s, m,
"There are no voicemail users currently defined.");
14480 char actionid[128];
14491 actionid[0] =
'\0';
14493 snprintf(actionid,
sizeof(actionid),
"ActionID: %s\r\n",
id);
14497 memset(&svm, 0,
sizeof(svm));
14501 astman_send_ack(s, m,
"There is no voicemail user matching the given user.");
14624 if (
vm_msg_forward(from_mailbox, from_context, from_folder, to_mailbox, to_context, to_folder, 1,
id, 0)) {
14681 if (!
str->used ||
str->str[
str->used - 1] !=
'\r') {
14736#ifdef TEST_FRAMEWORK
14748 size_t from_len = strlen(
alias) + 1;
14749 size_t to_len = strlen(
mailbox) + 1;
14751 mapping =
ao2_alloc(
sizeof(*mapping) + from_len + to_len,
NULL);
14791 char storage[strlen(
var->value) + 1];
14798 strcpy(storage,
var->value);
14823 if (strcasecmp(cat,
"general") == 0
14825 || strcasecmp(cat,
"zonemessages") == 0) {
14840 char *q, *stringp, *tmp;
14842 unsigned int tmpadsi[4];
14843 long tps_queue_low;
14844 long tps_queue_high;
14896 strcpy(odbc_database,
"asterisk");
14901 strcpy(odbc_table,
"voicemessages");
14905 odbc_table_len = strlen(odbc_table);
14941 if (sscanf(
val,
"%30d", &x) == 1)
15010 expungeonhangup = 0;
15012 expungeonhangup = 1;
15014 expungeonhangup = 1;
15041 imap_poll_logout = 0;
15049 mail_parameters(NIL, SET_READTIMEOUT, (
void *) (atol(
val)));
15051 mail_parameters(NIL, SET_READTIMEOUT, (
void *) 60L);
15055 mail_parameters(NIL, SET_WRITETIMEOUT, (
void *) (atol(
val)));
15057 mail_parameters(NIL, SET_WRITETIMEOUT, (
void *) 60L);
15061 mail_parameters(NIL, SET_OPENTIMEOUT, (
void *) (atol(
val)));
15063 mail_parameters(NIL, SET_OPENTIMEOUT, (
void *) 60L);
15067 mail_parameters(NIL, SET_CLOSETIMEOUT, (
void *) (atol(
val)));
15069 mail_parameters(NIL, SET_CLOSETIMEOUT, (
void *) 60L);
15085 ast_debug(1,
"Enabled SMDI voicemail notification\n");
15089 ast_debug(1,
"No SMDI interface set, trying default (/dev/ttyS0)\n");
15093 ast_log(
AST_LOG_ERROR,
"No valid SMDI interface specified, disabling SMDI voicemail notification\n");
15108 if (sscanf(
val,
"%30d", &x) == 1) {
15117 if (sscanf(
val,
"%30d", &x) == 1) {
15134 ast_log(
LOG_ERROR,
"Error processing format string, defaulting to format 'wav'\n");
15142 if (sscanf(
val,
"%30d", &x) == 1) {
15150 if (sscanf(
val,
"%30d", &x) == 1) {
15159 if (sscanf(
val,
"%30d", &x) == 1) {
15168 if (sscanf(
val,
"%30d", &x) == 1) {
15186 ast_debug(1,
"VM_CID Internal context string: %s\n",
val);
15190 q =
strsep(&stringp,
",");
15191 while ((*q ==
' ')||(*q ==
'\t'))
15201 ast_debug(1,
"VM Review Option disabled globally\n");
15209 ast_debug(1,
"VM leave urgent messages disabled globally\n");
15216 ast_debug(1,
"VM Temporary Greeting Reminder Option disabled globally\n");
15219 ast_debug(1,
"VM Temporary Greeting Reminder Option enabled globally\n");
15223 ast_debug(1,
"VM next message wrap disabled globally\n");
15229 ast_debug(1,
"VM Operator break disabled globally\n");
15235 ast_debug(1,
"VM CID Info before msg disabled globally\n");
15241 ast_debug(1,
"Send Voicemail msg disabled globally\n");
15247 ast_debug(1,
"ENVELOPE before msg enabled globally\n");
15253 ast_debug(1,
"Move Heard enabled globally\n");
15259 ast_debug(1,
"Autoset of Urgent flag on forwarded Urgent messages disabled globally\n");
15265 ast_debug(1,
"Duration info before msg enabled globally\n");
15272 if (sscanf(
val,
"%30d", &x) == 1) {
15280 ast_debug(1,
"We are not going to skip to the next msg after save/delete\n");
15346 val =
"voicemail.conf";
15348 if (!(strcmp(
val,
"spooldir"))) {
15368 strcpy(
charset,
"ISO-8859-1");
15394 sscanf(
val,
"%2x%2x%2x%2x", &tmpadsi[0], &tmpadsi[1], &tmpadsi[2], &tmpadsi[3]);
15395 for (x = 0; x < 4; x++) {
15396 memcpy(&
adsifdn[x], &tmpadsi[x], 1);
15400 sscanf(
val,
"%2x%2x%2x%2x", &tmpadsi[0], &tmpadsi[1], &tmpadsi[2], &tmpadsi[3]);
15401 for (x = 0; x < 4; x++) {
15402 memcpy(&
adsisec[x], &tmpadsi[x], 1);
15431 if (sscanf(
val,
"%30ld", &tps_queue_high) != 1 || tps_queue_high <= 0) {
15436 tps_queue_low = -1;
15438 if (sscanf(
val,
"%30ld", &tps_queue_low) != 1 ||
15439 tps_queue_low < -1 || tps_queue_high < tps_queue_low) {
15441 tps_queue_low = -1;
15479 snprintf(dir,
sizeof(dir),
"%s%s/%s/greet",
VM_SPOOL_DIR, context, mailbox);
15480 ast_debug(2,
"About to try retrieving name file %s\n", dir);
15481 RETRIEVE(dir, -1, mailbox, context);
15509 return sayname(chan, mailbox, context);
15526 ast_log(
LOG_NOTICE,
"Failed reading voicemail password from %s, using secret from config file\n", secretfn);
15574 if ((res =
sayname(chan, mailbox, context)) < 0) {
15575 ast_debug(3,
"Greeting not found for '%s@%s', falling back to mailbox number.\n", mailbox, context);
15585#ifdef TEST_FRAMEWORK
15600 static const char TEST_CONTEXT[] =
"very_long_unique_context_so_that_nobody_will_ever_have_the_same_one_configured_3141592653";
15608 .
write = fake_write,
15614 info->name =
"vmsayname_exec";
15615 info->category =
"/apps/app_voicemail/";
15616 info->summary =
"Vmsayname unit test";
15617 info->description =
15618 "This tests passing various parameters to vmsayname";
15625 NULL,
NULL, 0, 0,
"TestChannel1"))) {
15626 goto exit_vmsayname_test;
15632 goto exit_vmsayname_test;
15652 goto exit_vmsayname_test;
15657 goto exit_vmsayname_test;
15662 if ((res = symlink(dir, dir2))) {
15664 goto exit_vmsayname_test;
15679exit_vmsayname_test:
15702 struct test_files *tmp =
ast_alloca(
sizeof(
struct test_files) * 3);
15704 const char origweasels[] =
"tt-weasels";
15705 const char testcontext[] =
"test";
15706 const char testmailbox[] =
"00000000";
15707 const char testspec[] =
"00000000@test";
15709 int new, old, urgent;
15710 const char *folders[3] = {
"Old",
"Urgent",
"INBOX" };
15711 const int folder2mbox[3] = { 1, 11, 0 };
15712 const int expected_results[3][12] = {
15714 { 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0 },
15715 { 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1 },
15716 { 1, 1, 1, 1, 0, 2, 1, 1, 1, 1, 1, 2 },
15721 info->name =
"test_voicemail_msgcount";
15722 info->category =
"/apps/app_voicemail/";
15723 info->summary =
"Test Voicemail status checks";
15724 info->description =
15725 "Verify that message counts are correct when retrieved through the public API";
15732 snprintf(syscmd,
sizeof(syscmd),
"rm -rf \"%s%s/%s\"",
VM_SPOOL_DIR, testcontext, testmailbox);
15735 syserr > 0 ? strerror(syserr) :
"unable to fork()");
15746 memset(&svm, 0,
sizeof(svm));
15747 if (!(vmu =
find_user(&svm, testcontext, testmailbox)) &&
15757 memset(&vms, 0,
sizeof(vms));
15760 for (i = 0; i < 3; i++) {
15761 create_dirpath(tmp[i].dir,
sizeof(tmp[i].dir), testcontext, testmailbox, folders[i]);
15762 make_file(tmp[i].file,
sizeof(tmp[i].file), tmp[i].dir, 0);
15763 snprintf(tmp[i].txtfile,
sizeof(tmp[i].txtfile),
"%s.txt", tmp[i].file);
15766 snprintf(syscmd,
sizeof(syscmd),
"cp \"%s/sounds/en/%s.gsm\" \"%s/%s/%s/%s/msg0000.gsm\"",
ast_config_AST_DATA_DIR, origweasels,
15770 syserr > 0 ? strerror(syserr) :
"unable to fork()");
15779 if ((txt = fopen(tmp[i].txtfile,
"w+"))) {
15780 fprintf(txt,
"; just a stub\n[message]\nflag=%s\n", strcmp(folders[i],
"Urgent") ?
"" :
"Urgent");
15788 STORE(tmp[i].dir, testmailbox, testcontext, 0, chan, vmu,
"gsm", 600, &vms, strcmp(folders[i],
"Urgent") ?
"" :
"Urgent",
NULL);
15791 for (j = 0; j < 3; j++) {
15800 new = old = urgent = 0;
15804 }
else if (old != expected_results[i][3 + 0] ||
new != expected_results[i][3 + 2]) {
15806 testspec, old, expected_results[i][3 + 0],
new, expected_results[i][3 + 2]);
15810 new = old = urgent = 0;
15814 }
else if (old != expected_results[i][6 + 0] ||
15815 urgent != expected_results[i][6 + 1] ||
15816 new != expected_results[i][6 + 2] ) {
15817 ast_test_status_update(
test,
"inboxcount2(%s) returned old=%d (expected %d), urgent=%d (expected %d), and new=%d (expected %d)\n",
15818 testspec, old, expected_results[i][6 + 0], urgent, expected_results[i][6 + 1],
new, expected_results[i][6 + 2]);
15822 new = old = urgent = 0;
15823 for (j = 0; j < 3; j++) {
15826 testspec, folders[j],
ast_app_messagecount(testspec, folders[j]), expected_results[i][9 + j]);
15832 for (i = 0; i < 3; i++) {
15836 DELETE(tmp[i].dir, 0, tmp[i].file, vmu);
15852 snprintf(syscmd,
sizeof(syscmd),
"rm -rf \"%s%s/%s\"",
VM_SPOOL_DIR, testcontext, testmailbox);
15855 syserr > 0 ? strerror(syserr) :
"unable to fork()");
15866 char testcontext[] =
"test";
15867 char testmailbox[] =
"00000000";
15868 char from[] =
"test@example.net", cidnum[] =
"1234", cidname[] =
"Mark Spencer", format[] =
"gsm";
15869 char attach[256], attach2[256];
15870 char buf[256] =
"";
15878 enum { INT, FLAGVAL, STATIC, STRPTR }
type;
15885 {
"plain jane config", STATIC, vmus.
password, .u.strval =
"1234" },
15886 {
"emailsubject", STRPTR, vmus.
emailsubject, .u.strval =
"Oogly boogly\xf8koogly with what appears to be UTF-8" },
15887 {
"emailbody", STRPTR, vmus.
emailbody, .u.strval =
"This is a test\n\twith multiple\nlines\nwithin\n" },
15888 {
"serveremail", STATIC, vmus.
serveremail, .u.strval =
"\"\xf8Something\xe8that\xd8seems to have UTF-8 chars\" <test@example.net>" },
15889 {
"attachment flag", FLAGVAL, &vmus.
flags, .u.intval =
VM_ATTACH },
15890 {
"attach2", STRPTR, attach2, .u.strval =
"" },
15891 {
"attach", STRPTR, attach, .u.strval =
"" },
15897 info->name =
"test_voicemail_notify_endl";
15898 info->category =
"/apps/app_voicemail/";
15899 info->summary =
"Test Voicemail notification end-of-line";
15900 info->description =
15901 "Verify that notification emails use a consistent end-of-line character";
15910 if (!(vmu =
find_user(&vmus, testcontext, testmailbox)) &&
15916 if (vmu != &vmus && !(vmu =
find_user(&vmus, testcontext, testmailbox))) {
15928 for (which = 0; which <
ARRAY_LEN(test_items); which++) {
15931 if (ftruncate(fileno(file), 0)) {
15938 if (test_items[which].
type == INT) {
15939 *((
int *) test_items[which].location) = test_items[which].u.intval;
15940 }
else if (test_items[which].
type == FLAGVAL) {
15946 }
else if (test_items[which].
type == STATIC) {
15947 strcpy(test_items[which].location, test_items[which].u.strval);
15948 }
else if (test_items[which].
type == STRPTR) {
15949 test_items[which].location = test_items[which].u.strval;
15952 make_email_file(file, from, vmu, 0, testcontext, testmailbox,
"INBOX", cidnum, cidname, attach, attach2, format, 999, 1, chan,
NULL, 0,
NULL,
NULL);
15954 while (fgets(
buf,
sizeof(
buf), file)) {
15956 (strlen(
buf) > 1 &&
15958 buf[strlen(
buf) - 2] !=
'\r'
15960 buf[strlen(
buf) - 2] ==
'\r'
15963 ||
buf[strlen(
buf) - 1] !=
'\n') {
15986 info->name =
"test_voicemail_load_config";
15987 info->category =
"/apps/app_voicemail/";
15988 info->summary =
"Test loading Voicemail config";
15989 info->description =
15990 "Verify that configuration is loaded consistently. "
15991 "This is to test regressions of ASTERISK-18838 where it was noticed that "
15992 "some options were loaded after the mailboxes were instantiated, causing "
15993 "those options not to be set correctly.";
16003 if (!(file = fdopen(fd,
"w"))) {
16008 fputs(
"[general]\ncallback=somecontext\nlocale=de_DE.UTF-8\ntz=european\n[test]", file);
16009 fputs(
"00000001 => 9999,Mr. Test,,,callback=othercontext|locale=nl_NL.UTF-8|tz=central\n", file);
16010 fputs(
"00000002 => 9999,Mrs. Test\n", file);
16018 load_config_from_memory(1, cfg);
16021#define CHECK(u, attr, value) else if (strcmp(u->attr, value)) { \
16022 ast_test_status_update(test, "mailbox %s should have %s '%s', but has '%s'\n", \
16023 u->mailbox, #attr, value, u->attr); res = AST_TEST_FAIL; break; }
16027 if (!strcmp(vmu->
mailbox,
"00000001")) {
16029 CHECK(vmu,
callback,
"othercontext")
16030 CHECK(vmu,
locale, "nl_NL.UTF-8")
16031 CHECK(vmu,
zonetag, "central")
16032 } else
if (!strcmp(vmu->mailbox, "00000002")) {
16034 CHECK(vmu,
callback,
"somecontext")
16035 CHECK(vmu,
locale, "de_DE.UTF-8")
16036 CHECK(vmu,
zonetag, "european")
16055 const char testcontext[] =
"test";
16056 const char testmailbox[] =
"00000000";
16057 const char vminfo_cmd[] =
"VM_INFO";
16058 char vminfo_buf[256], vminfo_args[256];
16061 int test_counter = 0;
16064 char *vminfo_test_args;
16065 char *vminfo_expected;
16069 {
"00000000@test,badparam",
"", -1 },
16070 {
"00000000@test",
"", -1 },
16071 {
"00000000@test,exists",
"1", 0 },
16072 {
"11111111@test,exists",
"0", 0 },
16073 {
"00000000@test,email",
"vm-info-test@example.net", 0 },
16074 {
"11111111@test,email",
"", 0 },
16075 {
"00000000@test,fullname",
"Test Framework Mailbox", 0 },
16076 {
"00000000@test,pager",
"vm-info-pager-test@example.net", 0 },
16077 {
"00000000@test,locale",
"en_US", 0 },
16078 {
"00000000@test,tz",
"central", 0 },
16079 {
"00000000@test,language",
"en", 0 },
16080 {
"00000000@test,password",
"9876", 0 },
16085 info->name =
"test_voicemail_vm_info";
16086 info->category =
"/apps/app_voicemail/";
16087 info->summary =
"VM_INFO unit test";
16088 info->description =
16089 "This tests passing various parameters to VM_INFO";
16122 for (test_counter = 0; test_counter <
ARRAY_LEN(test_items); test_counter++) {
16123 ast_copy_string(vminfo_args, test_items[test_counter].vminfo_test_args,
sizeof(vminfo_args));
16124 test_ret =
acf_vm_info(chan, vminfo_cmd, vminfo_args, vminfo_buf,
sizeof(vminfo_buf));
16125 if (strcmp(vminfo_buf, test_items[test_counter].vminfo_expected)) {
16126 ast_test_status_update(
test,
"VM_INFO response was: '%s', but expected: '%s'\n", vminfo_buf, test_items[test_counter].vminfo_expected);
16129 if (!(test_ret == test_items[test_counter].vminfo_ret)) {
16130 ast_test_status_update(
test,
"VM_INFO return code was: '%i', but expected '%i'\n", test_ret, test_items[test_counter].vminfo_ret);
16188#ifdef TEST_FRAMEWORK
16199#ifdef TEST_FRAMEWORK
16200 ast_uninstall_vm_test_functions();
16231 prnt(where,
"Alias: %s Mailbox: %s", mapping->
alias, mapping->
mailbox);
16261 alias_mailbox_mapping_hash_fn,
NULL, alias_mailbox_mapping_cmp_fn);
16263 ast_log(
LOG_ERROR,
"Unable to create alias_mailbox_mappings container\n");
16269 ast_log(
LOG_ERROR,
"Unable to register alias_mailbox_mappings container\n");
16276 mailbox_alias_mapping_hash_fn,
NULL, mailbox_alias_mapping_cmp_fn);
16278 ast_log(
LOG_ERROR,
"Unable to create mailbox_alias_mappings container\n");
16286 ast_log(
LOG_ERROR,
"Unable to register mailbox_alias_mappings container\n");
16319#ifdef TEST_FRAMEWORK
16329 ast_log(
LOG_ERROR,
"Failure registering applications, functions or tests\n");
16352#ifdef TEST_FRAMEWORK
16353 ast_install_vm_test_functions(vm_test_create_user, vm_test_destroy_user);
16365 char destination[80] =
"";
16369 ast_verb(3,
"Destination number will be entered manually\n");
16370 while (retries < 3 && cmd !=
't') {
16371 destination[1] =
'\0';
16380 destination[0] = cmd;
16389 ast_verb(3,
"User hit '*' to cancel outgoing call\n");
16392 if ((cmd =
ast_readstring(chan, destination + strlen(destination),
sizeof(destination) - 1, 6000, 10000,
"#")) < 0)
16398 isprint(cmd) ? cmd :
'?', isprint(cmd) ? cmd :
'?');
16400 if (retries >= 3) {
16405 ast_verb(3,
"Destination number is CID number '%s'\n", num);
16410 if (destination[strlen(destination) -1 ] ==
'*')
16412 ast_verb(3,
"Placing outgoing call to extension '%s' in context '%s' from context '%s'\n", destination, outgoing_context,
ast_channel_context(chan));
16439 const char *origtime, *context;
16450 snprintf(filename,
sizeof(filename),
"%s.txt", vms->
fn);
16485 while ((res > -1) && (res !=
't')) {
16509 ast_verb(3,
"Caller can not specify callback number - no dialout context available\n");
16531 ast_verb(3,
"Confirm CID number '%s' is number to use for callback\n", num);
16562 isprint(res) ? res :
'?', isprint(res) ? res :
'?');
16568 else if (res ==
'*')
16580 ast_verb(3,
"No CID number available, no reply sent\n");
16587 memset(&vmu2, 0,
sizeof(vmu2));
16592 snprintf(mailbox,
sizeof(mailbox),
"%s@%s", num, vmu->
context);
16594 ast_verb(3,
"Leaving voicemail for '%s' in context '%s'\n", num, vmu->
context);
16596 memset(&leave_options, 0,
sizeof(leave_options));
16607 ast_verb(3,
"No mailbox number '%s' in context '%s', no reply sent\n", num, vmu->
context);
16621#ifndef IMAP_STORAGE
16624 vms->
heard[msg] = 1;
16632 int outsidecaller,
struct ast_vm_user *vmu,
int *duration,
int *sound_duration,
const char *unlockdir,
16638 int max_attempts = 3;
16641 int msg_exists = 0;
16642 signed char zero_gain = 0;
16644 char *acceptdtmf =
"#";
16645 char *canceldtmf =
"";
16646 int canceleddtmf = 0;
16647 SCOPE_ENTER(3,
"%s: rf: %s fmt: %s type: %s vmu: %s\n",
16648 ast_channel_name(chan), recordfile, fmt, outsidecaller ?
"msg" :
"greeting",
16653 if (duration ==
NULL) {
16657 if (!outsidecaller)
16658 snprintf(tempfile,
sizeof(tempfile),
"%s.tmp", recordfile);
16664 while ((cmd >= 0) && (cmd !=
't')) {
16673 ast_verb(3,
"Saving message as is\n");
16674 if (!outsidecaller) {
16675 ast_trace(-1,
"Renaming greeting '%s' to '%s'\n", tempfile, recordfile);
16678 if (!forwardintro) {
16681 if (!outsidecaller) {
16683 ast_trace(-1,
"Saving greeting '%s'\n", recordfile);
16684 SCOPE_CALL(-1,
STORE, recordfile, vmu->
mailbox, vmu->
context, -1, chan, vmu, fmt, *duration, vms,
flag, msg_id);
16692 ast_verb(3,
"Reviewing the message\n");
16693 ast_trace(-1,
"Reviewing '%s'\n", tempfile);
16700 ast_verb(3,
"Re-recording the message\n");
16702 ast_verb(3,
"Recording the message\n");
16704 if (recorded && outsidecaller) {
16705 if (forwardintro) {
16715 SCOPE_EXIT_RTN_VALUE(cmd,
"User hung up before message could be rerecorded. Deleted '%s'\n", tempfile);
16723 ast_trace(-1,
"Recording '%s'\n", tempfile);
16724 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);
16725 if (strchr(canceldtmf, cmd)) {
16733 if (!outsidecaller) {
16738 outsidecaller ?
"Saved message " :
"Deleted greeting \n", tempfile);
16742 }
else if (cmd ==
'*') {
16745 }
else if (vmu->review && sound_duration && (*sound_duration < 5)) {
16747 ast_verb(3,
"Message too short\n");
16751 }
else if (vmu->review && (cmd == 2 && sound_duration && *sound_duration < (
maxsilence + 3))) {
16753 ast_verb(3,
"Nothing recorded\n");
16770 ast_verb(3,
"marking message as Urgent\n");
16772 strcpy(
flag,
"Urgent");
16774 ast_verb(3,
"UNmarking message as Urgent\n");
16801 if (outsidecaller) {
16813 if (msg_exists || recorded) {
16814 ast_trace(-1,
"Reviewing '%s'\n", tempfile);
16819 ast_trace(-1,
"Saving '%s' to '%s'\n", tempfile, recordfile);
16823 }
else if (cmd ==
'4') {
16826 strcpy(
flag,
"Urgent");
16831 ast_trace(-1,
"Deleting '%s'\n", tempfile);
16875 if (attempts > max_attempts) {
16880 if (!outsidecaller && (cmd == -1 || cmd ==
't')) {
16882 ast_trace(-1,
"Deleting '%s' on hangup or timeout\n", tempfile);
16886 if (cmd !=
't' && outsidecaller)
16896 if (!(msg_snapshot =
ast_calloc(1,
sizeof(*msg_snapshot)))) {
16905 return msg_snapshot;
16916#ifdef TEST_FRAMEWORK
16918static int vm_test_destroy_user(
const char *context,
const char *mailbox)
16936static int vm_test_create_user(
const char *
context,
const char *
mailbox)
16963 int snapshot_index,
16979 snprintf(filename,
sizeof(filename),
"%s.txt", vms->
fn);
17003 filename,
id,
sizeof(
id), vmu, mailbox_index))) {
17034 switch (sort_val) {
17047 if (descending &&
val >= 0) {
17051 }
else if (!descending &&
val <= 0) {
17076 const char *context,
17077 const char *folder,
17080 int combine_INBOX_and_OLD)
17087 int this_index_only = -1;
17094 ast_log(
LOG_WARNING,
"Cannot create a mailbox snapshot since no mailbox was specified\n");
17098 memset(&vmus, 0,
sizeof(vmus));
17104 this_index_only = i;
17108 if (this_index_only == -1) {
17119 if (!(mailbox_snapshot =
ast_calloc(1,
sizeof(*mailbox_snapshot)))) {
17133 for (i = 0; i < mailbox_snapshot->
folders; i++) {
17134 int msg_folder_index = i;
17141 if (!(this_index_only == -1 || this_index_only == i || (this_index_only == inbox_index && combine_INBOX_and_OLD && (i == old_index || i == urgent_index)))) {
17146 if (combine_INBOX_and_OLD && (i == old_index || i == urgent_index)) {
17147 msg_folder_index = inbox_index;
17150 memset(&vms, 0,
sizeof(vms));
17158 goto snapshot_cleanup;
17166 goto snapshot_cleanup;
17172 goto snapshot_cleanup;
17184 vmstate_delete(&vms);
17189 return mailbox_snapshot;
17197 for (i = 0; i < mailbox_snapshot->
folders; i++) {
17230 for (i = 0; i < num_msgs; ++i) {
17231 const char *
msg_id = msg_ids[i];
17234 const char *other_msg_id;
17240 snprintf(filename,
sizeof(filename),
"%s.txt", vms->
fn);
17251 if (!
ast_strlen_zero(other_msg_id) && !strcmp(other_msg_id, msg_id)) {
17256 msg_nums[i] = vms->
curmsg;
17277 int new = 0, old = 0, urgent = 0;
17278 char ext_context[1024];
17280 snprintf(ext_context,
sizeof(ext_context),
"%s@%s", vmu->
mailbox, vmu->
context);
17287 const char *from_context,
17288 const char *from_folder,
17289 const char *to_mailbox,
17290 const char *to_context,
17291 const char *to_folder,
17293 const char *msg_ids [],
17302 int from_folder_index;
17309 ast_log(
LOG_WARNING,
"Cannot forward message because either the from or to mailbox was not specified\n");
17314 ast_log(
LOG_WARNING,
"Invalid number of messages specified to forward: %zu\n", num_msgs);
17319 ast_log(
LOG_WARNING,
"Cannot forward message because the from_folder or to_folder was not specified\n");
17323 memset(&vmus, 0,
sizeof(vmus));
17324 memset(&to_vmus, 0,
sizeof(to_vmus));
17325 memset(&from_vms, 0,
sizeof(from_vms));
17328 if (from_folder_index == -1) {
17336 if (!(vmu =
find_user(&vmus, from_context, from_mailbox))) {
17337 ast_log(
LOG_WARNING,
"Can't find voicemail user to forward from (%s@%s)\n", from_mailbox, from_context);
17341 if (!(to_vmu =
find_user(&to_vmus, to_context, to_mailbox))) {
17342 ast_log(
LOG_WARNING,
"Can't find voicemail user to forward to (%s@%s)\n", to_mailbox, to_context);
17352 if ((res =
open_mailbox(&from_vms, vmu, from_folder_index)) < 0) {
17355 goto vm_forward_cleanup;
17360 if ((from_vms.
lastmsg + 1) < num_msgs) {
17361 ast_log(
LOG_WARNING,
"Folder %s has less than %zu messages\n", from_folder, num_msgs);
17363 goto vm_forward_cleanup;
17366 msg_nums =
ast_alloca(
sizeof(
int) * num_msgs);
17369 goto vm_forward_cleanup;
17373 for (i = 0; i < num_msgs; i++) {
17374 int cur_msg = msg_nums[i];
17379 snprintf(filename,
sizeof(filename),
"%s.txt", from_vms.
fn);
17391 duration = atoi(
value);
17397 from_vms.
deleted[cur_msg] = 1;
17406 goto vm_forward_cleanup;
17416 vmstate_delete(&from_vms);
17430 const char *context,
17432 const char *oldfolder,
17433 const char *old_msg_ids [],
17434 const char *newfolder)
17438 int old_folder_index;
17439 int new_folder_index;
17451 ast_log(
LOG_WARNING,
"Invalid number of messages specified to move: %zu\n", num_msgs);
17456 ast_log(
LOG_WARNING,
"Cannot move message because either oldfolder or newfolder was not specified\n");
17463 memset(&vmus, 0,
sizeof(vmus));
17464 memset(&vms, 0,
sizeof(vms));
17466 if (old_folder_index == -1 || new_folder_index == -1) {
17479 if ((res =
open_mailbox(&vms, vmu, old_folder_index)) < 0) {
17482 goto vm_move_cleanup;
17487 if ((vms.
lastmsg + 1) < num_msgs) {
17488 ast_log(
LOG_WARNING,
"Folder %s has less than %zu messages\n", oldfolder, num_msgs);
17490 goto vm_move_cleanup;
17493 old_msg_nums =
ast_alloca(
sizeof(
int) * num_msgs);
17496 goto vm_move_cleanup;
17500 for (i = 0; i < num_msgs; ++i) {
17503 goto vm_move_cleanup;
17505 vms.
deleted[old_msg_nums[i]] = 1;
17511 goto vm_move_cleanup;
17521 vmstate_delete(&vms);
17536 const char *folder,
17537 const char *msgs[])
17553 ast_log(
LOG_WARNING,
"Invalid number of messages specified to remove: %zu\n", num_msgs);
17562 memset(&vmus, 0,
sizeof(vmus));
17563 memset(&vms, 0,
sizeof(vms));
17566 if (folder_index == -1) {
17581 if ((res =
open_mailbox(&vms, vmu, folder_index)) < 0) {
17584 goto vm_remove_cleanup;
17589 if ((vms.
lastmsg + 1) < num_msgs) {
17592 goto vm_remove_cleanup;
17595 msg_nums =
ast_alloca(
sizeof(
int) * num_msgs);
17598 goto vm_remove_cleanup;
17601 for (i = 0; i < num_msgs; i++) {
17602 vms.
deleted[msg_nums[i]] = 1;
17609 goto vm_remove_cleanup;
17619 vmstate_delete(&vms);
17634 const char *folder,
17635 const char *msg_id,
17660 ast_log(
LOG_WARNING,
"Cannot play message because no message number was specified\n");
17664 memset(&vmus, 0,
sizeof(vmus));
17665 memset(&vms, 0,
sizeof(vms));
17668 context =
"default";
17671 if (!(vmu =
find_user(&vmus, context, mailbox))) {
17680 goto play2_msg_cleanup;
17686 goto play2_msg_cleanup;
17691 snprintf(filename,
sizeof(filename),
"%s.txt", vms.
fn);
17698 goto play2_msg_cleanup;
17701 duration = atoi(
value);
17714 cb(chan, vms.
fn, duration);
17715 }
else if ((
wait_file(chan, &vms, vms.
fn)) < 0) {
17733 vmstate_delete(&vms);
17754 .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.
void ast_cli_unregister_multiple(void)
static int load_config(void)
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)
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 actual_load_config(int reload, struct ast_config *cfg)
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 occurrences 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 password 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)
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 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 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 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 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 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)
char * strsep(char **str, const char *delims)
char * mkdtemp(char *template_s)
char * strcasestr(const char *, const char *)
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_STRING_FIELD_CMP_FN(stype, field)
Creates a compare function for a structure string field.
#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.
#define AO2_STRING_FIELD_HASH_FN(stype, field)
Creates a hash function for a structure string field.
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
static struct ast_channel * callback(struct ast_channelstorage_instance *driver, ao2_callback_data_fn *cb_fn, void *arg, void *data, int ao2_flags, int rdlock)
Standard Command Line Interface.
#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 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)
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
@ CONFIG_FLAG_WITHCOMMENTS
@ CONFIG_FLAG_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.
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.
#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.
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 check_password(void)
static char intro[ADSI_MAX_INTRO][20]
static struct stasis_rest_handlers mailboxes
REST handler for /api-docs/mailboxes.json.
static struct stasis_subscription * sub
Statsd channel stats. Exmaple of how to subscribe to Stasis events.
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 load_users(void)
static void cleanup(void)
Clean up any old apps that we don't need any more.
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.
int AST_OPTIONAL_API_NAME() ast_smdi_mwi_unset(struct ast_smdi_interface *iface, const char *mailbox)
Unset the MWI indicator for a mailbox.
int AST_OPTIONAL_API_NAME() ast_smdi_mwi_set(struct ast_smdi_interface *iface, const char *mailbox)
Set the MWI indicator for a mailbox.
struct ast_smdi_interface *AST_OPTIONAL_API_NAME() ast_smdi_interface_find(const char *iface_name)
Find an SMDI interface with the specified name.
struct ast_smdi_mwi_message *AST_OPTIONAL_API_NAME() ast_smdi_mwi_message_wait_station(struct ast_smdi_interface *iface, int timeout, const char *station)
#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.
size_t attribute_pure ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within 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.
char *attribute_pure ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str 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
struct ast_app::@406 list
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.
char context[AST_MAX_CONTEXT]
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.
struct ast_variable * next
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::@192 * snapshots
const ast_string_field origtime
struct ast_vm_msg_snapshot::@191 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 context[MAX_VM_CONTEXT_LEN]
char mailbox[MAX_VM_MBOX_ID_LEN]
struct ast_vm_user::@86 list
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 phoneprov_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.
#define ast_taskprocessor_push(tps, task_exe, datap)
#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.