56#include <imap/c-client.h>
57#include <imap/imap4r1.h>
58#include <imap/linkage.h>
59#elif defined (USE_SYSTEM_CCLIENT)
60#include <c-client/c-client.h>
61#include <c-client/imap4r1.h>
62#include <c-client/linkage.h>
76#if defined(__FreeBSD__) || defined(__OpenBSD__)
568static char imapserver[48] =
"localhost";
569static char imapport[8] =
"143";
570static char imapflags[128];
571static char imapfolder[64] =
"INBOX";
572static char imapparentfolder[64];
573static char greetingfolder[64] =
"INBOX";
574static char authuser[32];
575static char authpassword[42];
576static int imapversion = 1;
578static int expungeonhangup = 1;
579static int imapgreetings;
580static int imap_poll_logout;
581static char delimiter;
592static int init_mailstream(
struct vm_state *vms,
int box);
593static void write_file(
char *filename,
char *buffer,
unsigned long len);
594static char *get_header_by_tag(
char *
header,
char *tag,
char *
buf,
size_t len);
595static void vm_imap_delete(
char *
file,
int msgnum,
struct ast_vm_user *vmu);
596static char *get_user_by_mailbox(
char *
mailbox,
char *
buf,
size_t len);
597static struct vm_state *get_vm_state_by_imapuser(
const char *
user,
int interactive);
598static struct vm_state *get_vm_state_by_mailbox(
const char *
mailbox,
const char *
context,
int interactive);
600static void vmstate_insert(
struct vm_state *vms);
601static void vmstate_delete(
struct vm_state *vms);
602static void set_update(MAILSTREAM * stream);
603static void init_vm_state(
struct vm_state *vms);
604static int save_body(BODY *body,
struct vm_state *vms,
char *section,
char *format,
int is_intro);
605static void get_mailbox_delimiter(
struct vm_state *vms, MAILSTREAM *stream);
606static void mm_parsequota (MAILSTREAM *stream,
unsigned char *msg, QUOTALIST *pquota);
607static void imap_mailbox_name(
char *spec,
size_t len,
struct vm_state *vms,
int box,
int target);
608static int imap_store_file(
const char *dir,
const char *mailboxuser,
const char *mailboxcontext,
int msgnum,
struct ast_channel *chan,
struct ast_vm_user *vmu,
char *fmt,
int duration,
struct vm_state *vms,
const char *
flag,
const char *msg_id);
609static void vm_imap_update_msg_id(
char *dir,
int msgnum,
const char *msg_id,
struct ast_vm_user *vmu,
struct ast_config *msg_cfg,
int folder);
610static void update_messages_by_imapuser(
const char *
user,
unsigned long number);
613static int imap_remove_file (
char *dir,
int msgnum);
614static int imap_retrieve_file (
const char *dir,
const int msgnum,
const char *
mailbox,
const char *
context);
615static int imap_delete_old_greeting (
char *dir,
struct vm_state *vms);
618static void imap_logout(
const char *mailbox_id);
629#define SMDI_MWI_WAIT_TIMEOUT 1000
631#define COMMAND_TIMEOUT 5000
633#define VOICEMAIL_DIR_MODE 0777
634#define VOICEMAIL_FILE_MODE 0666
635#define CHUNKSIZE 65536
637#define VOICEMAIL_CONFIG "voicemail.conf"
638#define ASTERISK_USERNAME "asterisk"
643#define DEFAULT_LISTEN_CONTROL_FORWARD_KEY "#"
644#define DEFAULT_LISTEN_CONTROL_REVERSE_KEY "*"
645#define DEFAULT_LISTEN_CONTROL_PAUSE_KEY "0"
646#define DEFAULT_LISTEN_CONTROL_RESTART_KEY "2"
647#define DEFAULT_LISTEN_CONTROL_STOP_KEY "13456789"
648#define VALID_DTMF "1234567890*#"
652#define SENDMAIL "/usr/sbin/sendmail -t"
653#define INTRO "vm-intro"
655#define MAX_MAIL_BODY_CONTENT_SIZE 134217728L
658#define MAXMSGLIMIT 9999
668#define MAX_DATETIME_FORMAT 512
669#define MAX_NUM_CID_CONTEXTS 10
671#define VM_REVIEW (1 << 0)
672#define VM_OPERATOR (1 << 1)
673#define VM_SAYCID (1 << 2)
674#define VM_SVMAIL (1 << 3)
675#define VM_ENVELOPE (1 << 4)
676#define VM_SAYDURATION (1 << 5)
677#define VM_SKIPAFTERCMD (1 << 6)
678#define VM_FORCENAME (1 << 7)
679#define VM_FORCEGREET (1 << 8)
680#define VM_PBXSKIP (1 << 9)
681#define VM_DIRECTFORWARD (1 << 10)
682#define VM_ATTACH (1 << 11)
683#define VM_DELETE (1 << 12)
684#define VM_ALLOCED (1 << 13)
685#define VM_SEARCH (1 << 14)
686#define VM_TEMPGREETWARN (1 << 15)
687#define VM_MOVEHEARD (1 << 16)
688#define VM_MESSAGEWRAP (1 << 17)
689#define VM_FWDURGAUTO (1 << 18)
690#define VM_EMAIL_EXT_RECS (1 << 19)
691#define VM_MARK_URGENT (1 << 20)
692#define ERROR_LOCK_PATH -100
693#define ERROR_MAX_MSGS -101
694#define OPERATOR_EXIT 300
781#define force_reload_config() load_config_force(1, 1)
881#define MAX_VM_MBOX_ID_LEN (AST_MAX_EXTENSION)
882#define MAX_VM_CONTEXT_LEN (AST_MAX_CONTEXT)
884#define MAX_VM_MAILBOX_LEN (MAX_VM_MBOX_ID_LEN + MAX_VM_CONTEXT_LEN)
919 char imappassword[80];
921 char imapvmshareid[80];
936#define VMSTATE_MAX_MSG_ARRAY 256
961 unsigned msg_array_max;
962 MAILSTREAM *mailstream;
972 unsigned int quota_limit;
973 unsigned int quota_usage;
979static char odbc_database[80] =
"asterisk";
980static char odbc_table[80] =
"voicemessages";
981#define RETRIEVE(a,b,c,d) retrieve_file(a,b)
982#define DISPOSE(a,b) remove_file(a,b)
983#define STORE(a,b,c,d,e,f,g,h,i,j,k) store_file(a,b,c,d)
984#define EXISTS(a,b,c,d) (message_exists(a,b))
985#define RENAME(a,b,c,d,e,f,g,h) (rename_file(a,b,c,d,e,f))
986#define COPY(a,b,c,d,e,f,g,h) (copy_file(a,b,c,d,e,f))
987#define DELETE(a,b,c,d) (delete_file(a,b))
988#define UPDATE_MSG_ID(a, b, c, d, e, f) (odbc_update_msg_id((a), (b), (c)))
991#define DISPOSE(a,b) (imap_remove_file(a,b))
992#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))
993#define RETRIEVE(a,b,c,d) imap_retrieve_file(a,b,c,d)
994#define EXISTS(a,b,c,d) (ast_fileexists(c,NULL,d) > 0)
995#define RENAME(a,b,c,d,e,f,g,h) (rename_file(g,h));
996#define COPY(a,b,c,d,e,f,g,h) (copy_file(g,h));
997#define DELETE(a,b,c,d) (vm_imap_delete(a,b,d))
998#define UPDATE_MSG_ID(a, b, c, d, e, f) (vm_imap_update_msg_id((a), (b), (c), (d), (e), (f)))
1000#define RETRIEVE(a,b,c,d)
1002#define STORE(a,b,c,d,e,f,g,h,i,j,k)
1003#define EXISTS(a,b,c,d) (ast_fileexists(c,NULL,d) > 0)
1004#define RENAME(a,b,c,d,e,f,g,h) (rename_file(g,h));
1005#define COPY(a,b,c,d,e,f,g,h) (copy_plain_file(g,h));
1006#define DELETE(a,b,c,d) (vm_delete(c))
1007#define UPDATE_MSG_ID(a, b, c, d, e, f)
1018#define PWDCHANGE_INTERNAL (1 << 1)
1019#define PWDCHANGE_EXTERNAL (1 << 2)
1023#define tdesc "Comedian Mail (Voicemail System) with ODBC Storage"
1026# define tdesc "Comedian Mail (Voicemail System) with IMAP Storage"
1028# define tdesc "Comedian Mail (Voicemail System)"
1076#define DEFAULT_POLL_FREQ 30
1099#define MAPPING_BUCKETS 511
1157static unsigned char adsifdn[4] =
"\x00\x00\x00\x0F";
1158static unsigned char adsisec[4] =
"\x9B\xDB\xF7\xAC";
1169 char *fmt,
int outsidecaller,
struct ast_vm_user *vmu,
int *duration,
int *sound_duration,
const char *unlockdir,
1170 signed char record_gain,
struct vm_state *vms,
char *
flag,
const char *msg_id,
int forwardintro);
1174static 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);
1206static 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);
1207static 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);
1211#ifdef TEST_FRAMEWORK
1212static int vm_test_destroy_user(
const char *
context,
const char *
mailbox);
1213static int vm_test_create_user(
const char *
context,
const char *
mailbox);
1261 if (strcmp(i->
mailbox, j->mailbox)) {
1269 int context_len = strlen(
context) + 1;
1270 int mailbox_len = strlen(
mailbox) + 1;
1285 if (!(i =
ao2_alloc(
sizeof(*i) + context_len + mailbox_len,
NULL))) {
1299#if !(defined(ODBC_STORAGE) || defined(IMAP_STORAGE))
1317 if (bufptr ==
buf + buflen - 1) {
1371 ast_copy_string(vmu->imapfolder, imapfolder,
sizeof(vmu->imapfolder));
1372 ast_copy_string(vmu->imapserver, imapserver,
sizeof(vmu->imapserver));
1389 if (!strcasecmp(
var,
"attach")) {
1391 }
else if (!strcasecmp(
var,
"attachfmt")) {
1393 }
else if (!strcasecmp(
var,
"attachextrecs")) {
1395 }
else if (!strcasecmp(
var,
"serveremail")) {
1397 }
else if (!strcasecmp(
var,
"fromstring")) {
1399 }
else if (!strcasecmp(
var,
"emailbody")) {
1402 }
else if (!strcasecmp(
var,
"emailsubject")) {
1405 }
else if (!strcasecmp(
var,
"language")) {
1407 }
else if (!strcasecmp(
var,
"tz")) {
1409 }
else if (!strcasecmp(
var,
"locale")) {
1412 }
else if (!strcasecmp(
var,
"imapuser")) {
1414 vmu->imapversion = imapversion;
1415 }
else if (!strcasecmp(
var,
"imapserver")) {
1417 vmu->imapversion = imapversion;
1418 }
else if (!strcasecmp(
var,
"imapport")) {
1420 vmu->imapversion = imapversion;
1421 }
else if (!strcasecmp(
var,
"imapflags")) {
1423 vmu->imapversion = imapversion;
1424 }
else if (!strcasecmp(
var,
"imappassword") || !strcasecmp(
var,
"imapsecret")) {
1426 vmu->imapversion = imapversion;
1427 }
else if (!strcasecmp(
var,
"imapfolder")) {
1429 vmu->imapversion = imapversion;
1430 }
else if (!strcasecmp(
var,
"imapvmshareid")) {
1432 vmu->imapversion = imapversion;
1434 }
else if (!strcasecmp(
var,
"delete") || !strcasecmp(
var,
"deletevoicemail")) {
1436 }
else if (!strcasecmp(
var,
"saycid")){
1438 }
else if (!strcasecmp(
var,
"sendvoicemail")){
1440 }
else if (!strcasecmp(
var,
"review")){
1442 }
else if (!strcasecmp(
var,
"leaveurgent")){
1444 }
else if (!strcasecmp(
var,
"tempgreetwarn")){
1446 }
else if (!strcasecmp(
var,
"messagewrap")){
1448 }
else if (!strcasecmp(
var,
"operator")) {
1450 }
else if (!strcasecmp(
var,
"envelope")){
1452 }
else if (!strcasecmp(
var,
"moveheard")){
1454 }
else if (!strcasecmp(
var,
"sayduration")){
1456 }
else if (!strcasecmp(
var,
"saydurationm")){
1457 if (sscanf(
value,
"%30d", &x) == 1) {
1462 }
else if (!strcasecmp(
var,
"forcename")){
1464 }
else if (!strcasecmp(
var,
"forcegreetings")){
1466 }
else if (!strcasecmp(
var,
"callback")) {
1468 }
else if (!strcasecmp(
var,
"dialout")) {
1470 }
else if (!strcasecmp(
var,
"exitcontext")) {
1472 }
else if (!strcasecmp(
var,
"minsecs")) {
1473 if (sscanf(
value,
"%30d", &x) == 1 && x >= 0) {
1479 }
else if (!strcasecmp(
var,
"maxmessage") || !strcasecmp(
var,
"maxsecs")) {
1487 if (!strcasecmp(
var,
"maxmessage"))
1488 ast_log(
AST_LOG_WARNING,
"Option 'maxmessage' has been deprecated in favor of 'maxsecs'. Please make that change in your voicemail config.\n");
1489 }
else if (!strcasecmp(
var,
"maxmsg")) {
1499 }
else if (!strcasecmp(
var,
"nextaftercmd")) {
1501 }
else if (!strcasecmp(
var,
"backupdeleted")) {
1502 if (sscanf(
value,
"%30d", &x) == 1)
1516 }
else if (!strcasecmp(
var,
"volgain")) {
1518 }
else if (!strcasecmp(
var,
"passwordlocation")) {
1519 if (!strcasecmp(
value,
"spooldir")) {
1524 }
else if (!strcasecmp(
var,
"options")) {
1531 int fds[2], pid = 0;
1536 snprintf(
buf,
len,
"FAILURE: Pipe failed: %s", strerror(
errno));
1545 snprintf(
buf,
len,
"FAILURE: Fork failed");
1549 if (read(fds[0],
buf,
len) < 0) {
1561 dup2(fds[1], STDOUT_FILENO);
1567 execv(arg.v[0], arg.v);
1568 printf(
"FAILURE: %s", strerror(
errno));
1591 char cmd[255],
buf[255];
1593 ast_debug(1,
"Verify password policies for %s\n", password);
1598 if (!strncasecmp(
buf,
"VALID", 5)) {
1601 }
else if (!strncasecmp(
buf,
"FAILURE", 7)) {
1626 if (!strcmp(vmu->
password, password)) {
1631 if (strlen(password) > 10) {
1651 while ((s =
strsep(&stringp,
"|"))) {
1667 if (!strcasecmp(
var->name,
"vmsecret")) {
1669 }
else if (!strcasecmp(
var->name,
"secret") || !strcasecmp(
var->name,
"password")) {
1673 "\n\tmust be reset in voicemail.conf.\n",
retval->mailbox);
1678 }
else if (!strcasecmp(
var->name,
"uniqueid")) {
1680 }
else if (!strcasecmp(
var->name,
"pager")) {
1682 }
else if (!strcasecmp(
var->name,
"email")) {
1685 }
else if (!strcasecmp(
var->name,
"fullname")) {
1687 }
else if (!strcasecmp(
var->name,
"context")) {
1689 }
else if (!strcasecmp(
var->name,
"emailsubject")) {
1692 }
else if (!strcasecmp(
var->name,
"emailbody")) {
1696 }
else if (!strcasecmp(
var->name,
"imapuser")) {
1698 retval->imapversion = imapversion;
1699 }
else if (!strcasecmp(
var->name,
"imapserver")) {
1701 retval->imapversion = imapversion;
1702 }
else if (!strcasecmp(
var->name,
"imapport")) {
1704 retval->imapversion = imapversion;
1705 }
else if (!strcasecmp(
var->name,
"imapflags")) {
1707 retval->imapversion = imapversion;
1708 }
else if (!strcasecmp(
var->name,
"imappassword") || !strcasecmp(
var->name,
"imapsecret")) {
1710 retval->imapversion = imapversion;
1711 }
else if (!strcasecmp(
var->name,
"imapfolder")) {
1713 retval->imapversion = imapversion;
1714 }
else if (!strcasecmp(
var->name,
"imapvmshareid")) {
1716 retval->imapversion = imapversion;
1735 for (i = 0; i < strlen(key); ++i) {
1807 if (cur->imapversion != imapversion) {
1818 if ((vmu = (ivm ? ivm :
ast_calloc(1,
sizeof(*vmu))))) {
1845 char *search_mailbox =
NULL;
1846 char *search_context =
NULL;
1850 vmu =
find_user(ivm, search_mailbox, search_context);
1889 "NewPassword", newpass);
1916 char *category =
NULL;
1931 ast_verb(4,
"Writing voicemail password to file %s succeeded\n", secretfn);
1936 ast_log(
LOG_WARNING,
"Writing voicemail password to file %s failed, falling back to config file\n", secretfn);
1942 if (!strcasecmp(category, vmu->
context)) {
1952 sprintf(
new,
"%s", newpassword);
1955 sprintf(
new,
"%s%s", newpassword,
value);
1969 ast_test_suite_event_notify(
"PASSWORDCHANGED",
"Message: voicemail.conf updated with new password\r\nPasswordSource: voicemail.conf");
1986 ast_debug(4,
"users.conf: %s\n", category);
1987 if (!strcasecmp(category, vmu->
mailbox)) {
1988 char new[strlen(newpassword) + 1];
1990 ast_debug(3,
"looks like we need to make vmsecret!\n");
1996 sprintf(
new,
"%s", newpassword);
1998 ast_debug(4,
"failed to get category!\n");
2067static int make_file(
char *dest,
const int len,
const char *dir,
const int num)
2069 return snprintf(dest,
len,
"%s/msg%04d", dir, num);
2096 if (vmu &&
id == 0) {
2097 return vmu->imapfolder;
2155 int arraysize = (vmu->
maxmsg > count_msg ? vmu->
maxmsg : count_msg);
2168 if (arraysize > 0) {
2186static void vm_imap_delete(
char *
file,
int msgnum,
struct ast_vm_user *vmu)
2190 unsigned long messageNum;
2193 if (msgnum < 0 && !imapgreetings) {
2198 if (!(vms = get_vm_state_by_mailbox(vmu->
mailbox, vmu->
context, 1)) && !(vms = get_vm_state_by_mailbox(vmu->
mailbox, vmu->
context, 0))) {
2199 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);
2204 imap_delete_old_greeting(
file, vms);
2210 messageNum = vms->msgArray[msgnum];
2211 if (messageNum == 0) {
2212 ast_log(
LOG_WARNING,
"msgnum %d, mailbox message %lu is zero.\n", msgnum, messageNum);
2215 ast_debug(3,
"deleting msgnum %d, which is mailbox message %lu\n", msgnum, messageNum);
2217 snprintf (arg,
sizeof(arg),
"%lu", messageNum);
2219 mail_setflag (vms->mailstream, arg,
"\\DELETED");
2220 mail_expunge(vms->mailstream);
2224static 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)
2231 const char *duration_str;
2275 sscanf(duration_str,
"%30d", &duration);
2291 vm_imap_delete(dir, msgnum, vmu);
2297static int imap_retrieve_greeting(
const char *dir,
const int msgnum,
struct ast_vm_user *vmu)
2300 char *
file, *filename;
2310 if (msgnum > -1 || !imapgreetings) {
2317 ast_debug(1,
"Failed to procure file name from directory passed.\n");
2323 if (!(vms_p = get_vm_state_by_mailbox(vmu->
mailbox, vmu->
context, 1)) &&
2324 !(vms_p = get_vm_state_by_mailbox(vmu->
mailbox, vmu->
context, 0))) {
2329 if (!(vms_p = create_vm_state_from_user(vmu))) {
2336 *vms_p->introfn =
'\0';
2350 for (i = 0; i < vms_p->mailstream->nmsgs; i++) {
2351 mail_fetchstructure(vms_p->mailstream, i + 1, &body);
2353 if (body->nested.part && body->nested.part->next && body->nested.part->next->body.parameter->value) {
2354 char *attachment = body->nested.part->next->body.parameter->value;
2355 char copy[strlen(attachment) + 1];
2357 strcpy(
copy, attachment);
2360 filename =
strsep(&attachment,
".");
2361 if (!strcmp(filename,
file)) {
2363 vms_p->msgArray[vms_p->
curmsg] = i + 1;
2365 save_body(body, vms_p,
"2", attachment, 0);
2376 if (curr_mbox != -1) {
2378 if (init_mailstream(vms_p, curr_mbox) || !vms_p->mailstream) {
2387static int imap_retrieve_file(
const char *dir,
const int msgnum,
const char *
mailbox,
const char *
context)
2390 char *header_content;
2391 char *attachedfilefmt;
2395 FILE *text_file_ptr;
2406 if (imapgreetings) {
2407 res = imap_retrieve_greeting(dir, msgnum, vmu);
2418 if (!(vms = get_vm_state_by_mailbox(vmu->
mailbox, vmu->
context, 1)) && !(vms = get_vm_state_by_mailbox(vmu->
mailbox, vmu->
context, 0))) {
2433 if (curr_mbox < 0) {
2434 ast_debug(3,
"Mailbox folder curbox not set, defaulting to Inbox\n");
2437 init_mailstream(vms, curr_mbox);
2438 if (!vms->mailstream) {
2445 snprintf(vms->introfn,
sizeof(vms->introfn),
"%sintro", vms->
fn);
2453 ast_debug(3,
"Before mail_fetchheaders, curmsg is: %d, imap messages is %lu\n", msgnum, vms->msgArray[msgnum]);
2454 if (vms->msgArray[msgnum] == 0) {
2462 header_content = mail_fetchheader (vms->mailstream, vms->msgArray[msgnum]);
2466 ast_log(
LOG_ERROR,
"Could not fetch header for message number %ld\n", vms->msgArray[msgnum]);
2472 mail_fetchstructure(vms->mailstream, vms->msgArray[msgnum], &body);
2476 if (body->nested.part && body->nested.part->next && body->nested.part->next->body.parameter->value) {
2477 attachedfilefmt =
ast_strdupa(body->nested.part->next->body.parameter->value);
2486 strsep(&attachedfilefmt,
".");
2487 if (!attachedfilefmt) {
2488 ast_log(
LOG_ERROR,
"File format could not be obtained from IMAP message attachment\n");
2493 save_body(body, vms,
"2", attachedfilefmt, 0);
2494 if (save_body(body, vms,
"3", attachedfilefmt, 1)) {
2495 *vms->introfn =
'\0';
2499 snprintf(text_file,
sizeof(text_file),
"%s.%s", vms->
fn,
"txt");
2501 if (!(text_file_ptr = fopen(text_file,
"w"))) {
2506 fprintf(text_file_ptr,
"%s\n",
"[message]");
2508 if (get_header_by_tag(header_content,
"X-Asterisk-VM-Caller-ID-Name:",
buf,
sizeof(
buf))) {
2509 fprintf(text_file_ptr,
"callerid=\"%s\" ",
S_OR(
buf,
""));
2511 if (get_header_by_tag(header_content,
"X-Asterisk-VM-Caller-ID-Num:",
buf,
sizeof(
buf))) {
2512 fprintf(text_file_ptr,
"<%s>\n",
S_OR(
buf,
""));
2514 if (get_header_by_tag(header_content,
"X-Asterisk-VM-Context:",
buf,
sizeof(
buf))) {
2515 fprintf(text_file_ptr,
"context=%s\n",
S_OR(
buf,
""));
2517 if (get_header_by_tag(header_content,
"X-Asterisk-VM-Orig-time:",
buf,
sizeof(
buf))) {
2518 fprintf(text_file_ptr,
"origtime=%s\n",
S_OR(
buf,
""));
2520 if (get_header_by_tag(header_content,
"X-Asterisk-VM-Duration:",
buf,
sizeof(
buf))) {
2521 fprintf(text_file_ptr,
"duration=%s\n",
S_OR(
buf,
""));
2523 if (get_header_by_tag(header_content,
"X-Asterisk-VM-Category:",
buf,
sizeof(
buf))) {
2524 fprintf(text_file_ptr,
"category=%s\n",
S_OR(
buf,
""));
2526 if (get_header_by_tag(header_content,
"X-Asterisk-VM-Flag:",
buf,
sizeof(
buf))) {
2527 fprintf(text_file_ptr,
"flag=%s\n",
S_OR(
buf,
""));
2529 if (get_header_by_tag(header_content,
"X-Asterisk-VM-Message-ID:",
buf,
sizeof(
buf))) {
2530 fprintf(text_file_ptr,
"msg_id=%s\n",
S_OR(
buf,
""));
2532 fclose(text_file_ptr);
2539static int folder_int(
const char *folder)
2545 if (!strcasecmp(folder, imapfolder)) {
2547 }
else if (!strcasecmp(folder,
"Old")) {
2549 }
else if (!strcasecmp(folder,
"Work")) {
2551 }
else if (!strcasecmp(folder,
"Family")) {
2553 }
else if (!strcasecmp(folder,
"Friends")) {
2555 }
else if (!strcasecmp(folder,
"Cust1")) {
2557 }
else if (!strcasecmp(folder,
"Cust2")) {
2559 }
else if (!strcasecmp(folder,
"Cust3")) {
2561 }
else if (!strcasecmp(folder,
"Cust4")) {
2563 }
else if (!strcasecmp(folder,
"Cust5")) {
2565 }
else if (!strcasecmp(folder,
"Urgent")) {
2572static int __messagecount(
const char *
context,
const char *
mailbox,
const char *folder)
2580 int fold = folder_int(folder);
2593 memset(&vmus, 0,
sizeof(vmus));
2601 if (vmu->imapuser[0] ==
'\0') {
2609 if (vmu->imapuser[0] ==
'\0') {
2616 vms_p = get_vm_state_by_imapuser(vmu->imapuser, 1);
2621 ast_debug(3,
"Returning before search - user is logged in\n");
2633 vms_p = get_vm_state_by_imapuser(vmu->imapuser, 0);
2639 vms_p = create_vm_state_from_user(vmu);
2641 ret = init_mailstream(vms_p, fold);
2642 if (!vms_p->mailstream) {
2649 pgm = mail_newsearchpgm ();
2650 hdr = mail_newsearchheader (
"X-Asterisk-VM-Extension", (
char *)(!
ast_strlen_zero(vmu->imapvmshareid) ? vmu->imapvmshareid :
mailbox));
2651 hdr->next = mail_newsearchheader(
"X-Asterisk-VM-Context", (
char *)
S_OR(
context,
"default"));
2677 vms_p->vmArrayIndex = 0;
2678 mail_search_full (vms_p->mailstream,
NULL, pgm, NIL);
2679 if (fold == 0 && urgent == 0)
2683 if (fold == 0 && urgent == 1)
2686 mail_free_searchpgm(&pgm);
2690 return vms_p->vmArrayIndex;
2693 mail_ping(vms_p->mailstream);
2703 check_quota(vms, vmu->imapfolder);
2704 if (vms->quota_limit && vms->quota_usage >= vms->quota_limit) {
2705 ast_debug(1,
"*** QUOTA EXCEEDED!! %u >= %u\n", vms->quota_usage, vms->quota_limit);
2715 ast_log(
LOG_WARNING,
"Unable to leave message since we will exceed the maximum number of messages allowed (%u >= %u)\n", msgnum, vmu->
maxmsg);
2734static int messagecount(
const char *mailbox_id,
const char *folder)
2750 return count < 0 ? 0 : count;
2753static 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)
2761 char tmp[80] =
"/tmp/astmail-XXXXXX";
2767 char *imap_flags = NIL;
2776 if(!imapgreetings) {
2783 if (imap_check_limits(chan, vms, vmu, msgcount)) {
2789 ast_debug(3,
"Setting message flag \\\\FLAGGED.\n");
2790 imap_flags =
"\\FLAGGED";
2806 snprintf(introfn,
sizeof(introfn),
"%sintro",
fn);
2821 if (!strcmp(fmt,
"wav49"))
2823 ast_debug(3,
"Storing file '%s', format '%s'\n",
fn, fmt);
2836 if (msgnum < 0 && imapgreetings) {
2841 imap_delete_old_greeting(
fn, vms);
2847 fn, introfn, fmt, duration, 1, chan,
NULL, 1,
flag, msg_id);
2855 *(vmu->
email) =
'\0';
2864 ((
char *)
buf)[
len] =
'\0';
2866 ret = init_mailstream(vms, box);
2870 if(!mail_append_full(vms->mailstream,
mailbox, imap_flags, NIL, &
str))
2886 *(vmu->
email) =
'\0';
2905static int inboxcount2(
const char *mailbox_context,
int *urgentmsgs,
int *newmsgs,
int *oldmsgs)
2920 ast_debug(3,
"Mailbox is set to %s\n", mailbox_context);
2927 if (strchr(mailbox_context,
',')) {
2928 int tmpnew, tmpold, tmpurgent;
2931 while ((cur =
strsep(&mb,
", "))) {
2941 *urgentmsgs += tmpurgent;
2953 mailboxnc = (
char *) mailbox_context;
2962 if ((count = __messagecount(
context, mailboxnc, vmu->imapfolder)) < 0) {
2970 if ((count = __messagecount(
context, mailboxnc,
"Old")) < 0) {
2976 if ((count = __messagecount(
context, mailboxnc,
"Urgent")) < 0) {
2979 *urgentmsgs = count;
2999 if (strchr(tmp2,
',') || strchr(tmp2,
'&')) {
3000 while ((box =
strsep(&tmp2,
",&"))) {
3013 return __messagecount(
context,
tmp, folder) > 0 ? 1 : 0;
3035 char messagestring[10];
3036 if (msgnum >= recip->
maxmsg) {
3040 if (!(sendvms = get_vm_state_by_imapuser(vmu->imapuser, 0))) {
3044 if (!get_vm_state_by_imapuser(recip->imapuser, 0)) {
3048 snprintf(messagestring,
sizeof(messagestring),
"%ld", sendvms->msgArray[msgnum]);
3050 if ((mail_copy(sendvms->mailstream, messagestring, (
char *)
mbox(vmu, imbox)) == T)) {
3059static void imap_mailbox_name(
char *spec,
size_t len,
struct vm_state *vms,
int box,
int use_folder)
3062 size_t left =
sizeof(
tmp);
3095 snprintf(spec,
len,
"%s%s",
tmp, use_folder? vms->imapfolder:
"INBOX");
3097 snprintf(spec,
len,
"%s%s",
tmp, greetingfolder);
3101 snprintf(spec,
len,
"%s%s%c%s",
tmp, imapparentfolder, delimiter,
mbox(
NULL, box));
3108static int init_mailstream(
struct vm_state *vms,
int box)
3110 MAILSTREAM *stream = NIL;
3118 ast_debug(3,
"vm_state user is:%s\n", vms->imapuser);
3119 if (vms->mailstream == NIL || !vms->mailstream) {
3122 stream = vms->mailstream;
3127 if (delimiter ==
'\0') {
3129#ifdef USE_SYSTEM_IMAP
3130#include <imap/linkage.c>
3131#elif defined(USE_SYSTEM_CCLIENT)
3132#include <c-client/linkage.c>
3137 imap_mailbox_name(
tmp,
sizeof(
tmp), vms, 0, 1);
3140 stream = mail_open (stream,
tmp,
debug ? OP_DEBUG : NIL);
3143 if (stream == NIL) {
3147 get_mailbox_delimiter(vms, stream);
3149 for (cp = vms->imapfolder; *cp; cp++)
3154 imap_mailbox_name(
tmp,
sizeof(
tmp), vms, box, 1);
3155 ast_debug(3,
"Before mail_open, server: %s, box:%d\n",
tmp, box);
3158 vms->mailstream = mail_open (stream,
tmp,
debug ? OP_DEBUG : NIL);
3160 if (vms->mailstream && !mail_status(vms->mailstream,
tmp, SA_UIDNEXT)) {
3161 mail_create(vms->mailstream,
tmp);
3165 if (vms->mailstream == NIL) {
3185 ast_copy_string(vms->imapfolder, vmu->imapfolder,
sizeof(vms->imapfolder));
3186 ast_copy_string(vms->imapserver, vmu->imapserver,
sizeof(vms->imapserver));
3188 ast_copy_string(vms->imapflags, vmu->imapflags,
sizeof(vms->imapflags));
3189 vms->imapversion = vmu->imapversion;
3190 ast_debug(3,
"Before init_mailstream, user is %s\n", vmu->imapuser);
3192 if (init_mailstream(vms, box) || !vms->mailstream) {
3201 ast_debug(3,
"Mailbox name set to: %s, about to check quotas\n",
mbox(vmu, box));
3202 check_quota(vms, (
char *)
mbox(vmu, box));
3206 pgm = mail_newsearchpgm();
3209 hdr = mail_newsearchheader(
"X-Asterisk-VM-Extension", (!
ast_strlen_zero(vmu->imapvmshareid) ? vmu->imapvmshareid : vmu->
mailbox));
3210 hdr->next = mail_newsearchheader(
"X-Asterisk-VM-Context", vmu->
context);
3221 }
else if (box ==
NEW_FOLDER && urgent == 0) {
3231 ast_debug(3,
"Before mail_search_full, user is %s\n", vmu->imapuser);
3233 vms->vmArrayIndex = 0;
3234 mail_search_full (vms->mailstream,
NULL, pgm, NIL);
3235 vms->
lastmsg = vms->vmArrayIndex - 1;
3236 mail_free_searchpgm(&pgm);
3242 ast_log(
LOG_WARNING,
"The code expects the old messages to be checked first, fix the code.\n");
3253static void write_file(
char *filename,
char *buffer,
unsigned long len)
3257 if (!filename || !buffer) {
3261 if (!(output = fopen(filename,
"w"))) {
3266 if (fwrite(buffer,
len, 1, output) != 1) {
3267 if (ferror(output)) {
3274static void update_messages_by_imapuser(
const char *
user,
unsigned long number)
3276 struct vm_state *vms = get_vm_state_by_imapuser(
user, 1);
3278 if (!vms && !(vms = get_vm_state_by_imapuser(
user, 0))) {
3282 ast_debug(3,
"saving mailbox message number %lu as message %d. Interactive set to %d\n",
number, vms->vmArrayIndex, vms->interactive);
3285 if (vms->vmArrayIndex >= vms->msg_array_max) {
3286 long *new_mem =
ast_realloc(vms->msgArray, 2 * vms->msg_array_max *
sizeof(
long));
3290 vms->msgArray = new_mem;
3291 vms->msg_array_max *= 2;
3294 vms->msgArray[vms->vmArrayIndex++] =
number;
3297void mm_searched(MAILSTREAM *stream,
unsigned long number)
3307static struct ast_vm_user *find_user_realtime_imapuser(
const char *imapuser)
3332void mm_exists(MAILSTREAM * stream,
unsigned long number)
3341void mm_expunged(MAILSTREAM * stream,
unsigned long number)
3350void mm_flags(MAILSTREAM * stream,
unsigned long number)
3359void mm_notify(MAILSTREAM * stream,
char *
string,
long errflg)
3361 ast_debug(5,
"Entering NOTIFY callback, errflag is %ld, string is %s\n", errflg,
string);
3362 mm_log (
string, errflg);
3366void mm_list(MAILSTREAM * stream,
int delim,
char *
mailbox,
long attributes)
3368 if (delimiter ==
'\0') {
3373 if (attributes & LATT_NOINFERIORS)
3375 if (attributes & LATT_NOSELECT)
3377 if (attributes & LATT_MARKED)
3379 if (attributes & LATT_UNMARKED)
3384void mm_lsub(MAILSTREAM * stream,
int delim,
char *
mailbox,
long attributes)
3387 if (attributes & LATT_NOINFERIORS)
3389 if (attributes & LATT_NOSELECT)
3391 if (attributes & LATT_MARKED)
3393 if (attributes & LATT_UNMARKED)
3398void mm_status(MAILSTREAM * stream,
char *
mailbox, MAILSTATUS *
status)
3407 if (
status->flags & SA_MESSAGES) {
3410 if (
status->flags & SA_RECENT) {
3413 if (
status->flags & SA_UNSEEN) {
3416 if (
status->flags & SA_UIDVALIDITY) {
3419 if (
status->flags & SA_UIDNEXT) {
3428void mm_log(
char *
string,
long errflg)
3430 switch ((
short) errflg) {
3432 ast_debug(1,
"IMAP Info: %s\n",
string);
3445void mm_dlog(
char *
string)
3451void mm_login(NETMBX * mb,
char *
user,
char *pwd,
long trial)
3455 ast_debug(4,
"Entering callback mm_login\n");
3464 if (!strcasecmp(mb->user, vmu->imapuser)) {
3470 if ((vmu = find_user_realtime_imapuser(mb->user))) {
3479void mm_critical(MAILSTREAM * stream)
3484void mm_nocritical(MAILSTREAM * stream)
3489long mm_diskerror(MAILSTREAM * stream,
long errcode,
long serious)
3491 kill (getpid (), SIGSTOP);
3496void mm_fatal(
char *
string)
3502static void mm_parsequota(MAILSTREAM *stream,
unsigned char *msg, QUOTALIST *pquota)
3506 char buf[1024] =
"";
3507 unsigned long usage = 0, limit = 0;
3510 usage = pquota->usage;
3511 limit = pquota->limit;
3512 pquota = pquota->next;
3515 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)))) {
3522 vms->quota_usage =
usage;
3523 vms->quota_limit = limit;
3526static char *get_header_by_tag(
char *
header,
char *tag,
char *
buf,
size_t len)
3528 char *start, *eol_pnt;
3534 taglen = strlen(tag) + 1;
3545 if ((eol_pnt = strchr(
buf,
'\r')) || (eol_pnt = strchr(
buf,
'\n')))
3550static char *get_user_by_mailbox(
char *
mailbox,
char *
buf,
size_t len)
3552 char *start, *eol_pnt, *
quote;
3557 if (!(start = strstr(
mailbox,
"/user=")))
3563 if ((eol_pnt = strchr(
buf,
'/')) || (eol_pnt = strchr(
buf,
'}'))) {
3568 if ((eol_pnt = strchr(
quote + 1,
'"'))) {
3579 pthread_once(&ts_vmstate.once, ts_vmstate.key_init);
3580 if ((vms_p = pthread_getspecific(ts_vmstate.key)) && !strcmp(vms_p->imapuser, vmu->imapuser) && !strcmp(vms_p->
username, vmu->
mailbox)) {
3583 ast_debug(5,
"Adding new vmstate for %s\n", vmu->imapuser);
3585 if (!(vms_p =
ast_calloc(1,
sizeof(*vms_p))))
3587 ast_copy_string(vms_p->imapuser, vmu->imapuser,
sizeof(vms_p->imapuser));
3588 ast_copy_string(vms_p->imapfolder, vmu->imapfolder,
sizeof(vms_p->imapfolder));
3589 ast_copy_string(vms_p->imapserver, vmu->imapserver,
sizeof(vms_p->imapserver));
3590 ast_copy_string(vms_p->imapport, vmu->imapport,
sizeof(vms_p->imapport));
3591 ast_copy_string(vms_p->imapflags, vmu->imapflags,
sizeof(vms_p->imapflags));
3594 vms_p->mailstream = NIL;
3595 vms_p->imapversion = vmu->imapversion;
3596 ast_debug(5,
"Copied %s to %s\n", vmu->imapuser, vms_p->imapuser);
3600 init_vm_state(vms_p);
3601 vmstate_insert(vms_p);
3605static struct vm_state *get_vm_state_by_imapuser(
const char *
user,
int interactive)
3607 struct vmstate *vlist =
NULL;
3611 pthread_once(&ts_vmstate.once, ts_vmstate.key_init);
3612 if ((vms = pthread_getspecific(ts_vmstate.key)) && !strcmp(vms->imapuser,
user)) {
3623 if (vlist->vms->imapversion != imapversion) {
3627 if (!strcmp(vlist->vms->imapuser,
user) && (interactive == 2 || vlist->vms->interactive == interactive)) {
3639static struct vm_state *get_vm_state_by_mailbox(
const char *
mailbox,
const char *
context,
int interactive)
3642 struct vmstate *vlist =
NULL;
3643 const char *local_context =
S_OR(
context,
"default");
3647 pthread_once(&ts_vmstate.once, ts_vmstate.key_init);
3648 if ((vms = pthread_getspecific(ts_vmstate.key)) &&
3660 if (vlist->vms->imapversion != imapversion) {
3664 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);
3666 if (!strcmp(vlist->vms->username,
mailbox) && !strcmp(vlist->vms->context, local_context) && vlist->vms->interactive == interactive) {
3679static void vmstate_insert(
struct vm_state *vms)
3687 if (vms->interactive == 1) {
3693 vms->vmArrayIndex = altvms->vmArrayIndex;
3698 vms->persist_vms = altvms;
3700#ifdef REALLY_FAST_EVEN_IF_IT_MEANS_RESOURCE_LEAKS
3701 vms->mailstream = altvms->mailstream;
3703 vms->mailstream = NIL;
3714 ast_debug(3,
"Inserting vm_state for user:%s, mailbox %s\n", vms->imapuser, vms->
username);
3721static void vmstate_delete(
struct vm_state *vms)
3723 struct vmstate *vc =
NULL;
3728 if (vms->interactive == 1 && (altvms = vms->persist_vms)) {
3732 altvms->updated = 1;
3733 vms->mailstream = mail_close(vms->mailstream);
3739 ast_debug(3,
"Removing vm_state for user:%s, mailbox %s\n", vms->imapuser, vms->
username);
3743 if (vc->vms == vms) {
3754 vc->vms->msgArray =
NULL;
3755 vc->vms->msg_array_max = 0;
3763static void set_update(MAILSTREAM * stream)
3767 char buf[1024] =
"";
3769 if (!(
user = get_user_by_mailbox(
mailbox,
buf,
sizeof(
buf))) || !(vms = get_vm_state_by_imapuser(
user, 0))) {
3780static void init_vm_state(
struct vm_state *vms)
3783 vms->msgArray =
ast_calloc(vms->msg_array_max,
sizeof(
long));
3784 if (!vms->msgArray) {
3786 vms->msg_array_max = 0;
3788 vms->vmArrayIndex = 0;
3792static int save_body(BODY *body,
struct vm_state *vms,
char *section,
char *format,
int is_intro)
3796 char *
fn = is_intro ? vms->introfn : vms->
fn;
3797 unsigned long len = 0;
3798 unsigned long newlen = 0;
3801 if (!body || body == NIL)
3805 body_content = mail_fetchbody(vms->mailstream, vms->msgArray[vms->
curmsg], section, &
len);
3809 "Msgno %ld, section %s. The body's content size %ld is huge (max %ld). User:%s, mailbox %s\n",
3813 if (body_content != NIL &&
len) {
3814 snprintf(filename,
sizeof(filename),
"%s.%s",
fn, format);
3816 body_decoded = rfc822_base64((
unsigned char *) body_content,
len, &newlen);
3818 if (!newlen || !body_decoded) {
3821 write_file(filename, (
char *) body_decoded, newlen);
3823 ast_debug(5,
"Body of message is NULL.\n");
3837static void get_mailbox_delimiter(
struct vm_state *vms, MAILSTREAM *stream) {
3839 snprintf(
tmp,
sizeof(
tmp),
"{%s}",
S_OR(vms->imapserver, imapserver));
3840 mail_list(stream,
tmp,
"*");
3852 mail_parameters(
NULL, SET_QUOTA, (
void *) mm_parsequota);
3854 if (vms && vms->mailstream !=
NULL) {
3855 imap_getquotaroot(vms->mailstream,
mailbox);
3878#define MSG_ID_LEN 256
3890struct generic_prepare_struct {
3898 struct generic_prepare_struct *gps = data;
3902 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->
con, &stmt);
3903 if (!SQL_SUCCEEDED(res)) {
3908 if (!SQL_SUCCEEDED(res)) {
3910 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
3913 for (i = 0; i < gps->argc; i++)
3914 SQLBindParameter(stmt, i + 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(gps->argv[i]), 0, gps->argv[i], 0,
NULL);
3919static void odbc_update_msg_id(
char *dir,
int msg_num,
char *msg_id)
3924 char msg_num_str[20];
3925 char *argv[] = { msg_id, dir, msg_num_str };
3926 struct generic_prepare_struct gps = { .sql = sql, .argc = 3, .argv = argv };
3930 ast_log(
LOG_WARNING,
"Unable to update message ID for message %d in %s\n", msg_num, dir);
3934 snprintf(msg_num_str,
sizeof(msg_num_str),
"%d", msg_num);
3935 snprintf(sql,
sizeof(sql),
"UPDATE %s SET msg_id=? WHERE dir=? AND msgnum=?", odbc_table);
3940 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
3960static int retrieve_file(
char *dir,
int msgnum)
3966 void *fdm = MAP_FAILED;
3967 SQLSMALLINT colcount = 0;
3974 SQLSMALLINT datatype;
3975 SQLSMALLINT decimaldigits;
3976 SQLSMALLINT nullable;
3985 char *argv[] = { dir, msgnums };
3986 struct generic_prepare_struct gps = { .sql = sql, .argc = 2, .argv = argv };
3996 c = strchr(fmt,
'|');
3999 if (!strcasecmp(fmt,
"wav49"))
4002 snprintf(msgnums,
sizeof(msgnums),
"%d", msgnum);
4009 snprintf(full_fn,
sizeof(full_fn),
"%s.txt", fn);
4011 if (!(f = fopen(full_fn,
"w+"))) {
4016 snprintf(full_fn,
sizeof(full_fn),
"%s.%s", fn, fmt);
4017 snprintf(sql,
sizeof(sql),
"SELECT * FROM %s WHERE dir=? AND msgnum=?", odbc_table);
4025 res = SQLFetch(stmt);
4026 if (!SQL_SUCCEEDED(res)) {
4027 if (res != SQL_NO_DATA) {
4030 goto bail_with_handle;
4036 goto bail_with_handle;
4039 res = SQLNumResultCols(stmt, &colcount);
4040 if (!SQL_SUCCEEDED(res)) {
4042 goto bail_with_handle;
4045 fprintf(f,
"[message]\n");
4046 for (x = 0; x < colcount; x++) {
4049 collen =
sizeof(coltitle);
4050 res = SQLDescribeCol(stmt, x + 1, (
unsigned char *) coltitle,
sizeof(coltitle), &collen,
4051 &datatype, &colsize, &decimaldigits, &nullable);
4052 if (!SQL_SUCCEEDED(res)) {
4054 goto bail_with_handle;
4056 if (!strcasecmp(coltitle,
"recording")) {
4058 res = SQLGetData(stmt, x + 1, SQL_BINARY, rowdata, 0, &colsize2);
4062 lseek(fd, fdlen - 1, SEEK_SET);
4063 if (write(fd,
tmp, 1) != 1) {
4069 for (offset = 0; offset < colsize2; offset +=
CHUNKSIZE) {
4070 if ((fdm = mmap(
NULL,
CHUNKSIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset)) == MAP_FAILED) {
4072 goto bail_with_handle;
4074 res = SQLGetData(stmt, x + 1, SQL_BINARY, fdm,
CHUNKSIZE,
NULL);
4076 if (!SQL_SUCCEEDED(res)) {
4079 goto bail_with_handle;
4082 if (truncate(full_fn, fdlen) < 0) {
4087 res = SQLGetData(stmt, x + 1, SQL_CHAR, rowdata,
sizeof(rowdata),
NULL);
4088 if (res == SQL_NULL_DATA && !strcasecmp(coltitle,
"msg_id")) {
4092 snprintf(rowdata,
sizeof(rowdata),
"%s", msg_id);
4093 }
else if (res == SQL_NULL_DATA && !strcasecmp(coltitle,
"category")) {
4095 ast_debug(3,
"Ignoring null category column in ODBC voicemail retrieve_file.\n");
4097 }
else if (!SQL_SUCCEEDED(res)) {
4099 goto bail_with_handle;
4101 if (strcasecmp(coltitle,
"msgnum") && strcasecmp(coltitle,
"dir")) {
4102 fprintf(f,
"%s=%s\n", coltitle, rowdata);
4108 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
4122 odbc_update_msg_id(dir, msgnum, msg_id);
4144 char *argv[] = { dir };
4145 struct generic_prepare_struct gps = { .sql = sql, .argc = 1, .argv = argv };
4154 snprintf(sql,
sizeof(sql),
"SELECT msgnum FROM %s WHERE dir=? order by msgnum desc", odbc_table);
4162 res = SQLFetch(stmt);
4163 if (!SQL_SUCCEEDED(res)) {
4164 if (res == SQL_NO_DATA) {
4165 ast_log(
AST_LOG_DEBUG,
"Directory '%s' has no messages and therefore no index was retrieved.\n", dir);
4169 goto bail_with_handle;
4172 res = SQLGetData(stmt, 1, SQL_CHAR, rowdata,
sizeof(rowdata),
NULL);
4173 if (!SQL_SUCCEEDED(res)) {
4175 goto bail_with_handle;
4178 if (sscanf(rowdata,
"%30d", &x) != 1) {
4183 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
4200static int message_exists(
char *dir,
int msgnum)
4208 char *argv[] = { dir, msgnums };
4209 struct generic_prepare_struct gps = { .sql = sql, .argc = 2, .argv = argv };
4218 snprintf(msgnums,
sizeof(msgnums),
"%d", msgnum);
4219 snprintf(sql,
sizeof(sql),
"SELECT COUNT(*) FROM %s WHERE dir=? AND msgnum=?", odbc_table);
4226 res = SQLFetch(stmt);
4227 if (!SQL_SUCCEEDED(res)) {
4229 goto bail_with_handle;
4232 res = SQLGetData(stmt, 1, SQL_CHAR, rowdata,
sizeof(rowdata),
NULL);
4233 if (!SQL_SUCCEEDED(res)) {
4235 goto bail_with_handle;
4238 if (sscanf(rowdata,
"%30d", &x) != 1) {
4243 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
4266 char *argv[] = { dir };
4267 struct generic_prepare_struct gps = { .sql = sql, .argc = 1, .argv = argv };
4276 snprintf(sql,
sizeof(sql),
"SELECT COUNT(*) FROM %s WHERE dir=?", odbc_table);
4283 res = SQLFetch(stmt);
4284 if (!SQL_SUCCEEDED(res)) {
4286 goto bail_with_handle;
4289 res = SQLGetData(stmt, 1, SQL_CHAR, rowdata,
sizeof(rowdata),
NULL);
4290 if (!SQL_SUCCEEDED(res)) {
4292 goto bail_with_handle;
4295 if (sscanf(rowdata,
"%30d", &x) != 1) {
4300 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
4315static void delete_file(
const char *sdir,
int smsg)
4320 char *argv[] = {
NULL, msgnums };
4321 struct generic_prepare_struct gps = { .sql = sql, .argc = 2, .argv = argv };
4332 snprintf(msgnums,
sizeof(msgnums),
"%d", smsg);
4333 snprintf(sql,
sizeof(sql),
"DELETE FROM %s WHERE dir=? AND msgnum=?", odbc_table);
4338 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
4356static void copy_file(
char *sdir,
int smsg,
char *ddir,
int dmsg,
char *dmailboxuser,
char *dmailboxcontext)
4364 char *argv[] = { ddir, msgnumd, msg_id, dmailboxuser, dmailboxcontext, sdir, msgnums };
4365 struct generic_prepare_struct gps = { .sql = sql, .argc = 7, .argv = argv };
4375 snprintf(msgnums,
sizeof(msgnums),
"%d", smsg);
4376 snprintf(msgnumd,
sizeof(msgnumd),
"%d", dmsg);
4377 snprintf(sql,
sizeof(sql),
"INSERT INTO %s (dir, msgnum, msg_id, context, callerid, origtime, duration, recording, flag, mailboxuser, mailboxcontext) SELECT ?,?,?,context,callerid,origtime,duration,recording,flag,?,? FROM %s WHERE dir=? AND msgnum=?", odbc_table, odbc_table);
4380 ast_log(
AST_LOG_WARNING,
"SQL Execute error!\n[%s] (You probably don't have MySQL 4.1 or later installed)\n\n", sql);
4382 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
4391 const char *msgnums;
4396 const char *callerid;
4397 const char *origtime;
4398 const char *duration;
4399 const char *mailboxuser;
4400 const char *mailboxcontext;
4401 const char *category;
4406static SQLHSTMT insert_data_cb(
struct odbc_obj *obj,
void *vdata)
4408 struct insert_data *data = vdata;
4412 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->
con, &stmt);
4413 if (!SQL_SUCCEEDED(res)) {
4418 SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->dir), 0, (
void *) data->dir, 0,
NULL);
4419 SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->msgnums), 0, (
void *) data->msgnums, 0,
NULL);
4420 SQLBindParameter(stmt, 3, SQL_PARAM_INPUT, SQL_C_BINARY, SQL_LONGVARBINARY, data->datalen, 0, (
void *) data->data, data->datalen, &data->indlen);
4421 SQLBindParameter(stmt, 4, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->context), 0, (
void *) data->context, 0,
NULL);
4422 SQLBindParameter(stmt, 5, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->callerid), 0, (
void *) data->callerid, 0,
NULL);
4423 SQLBindParameter(stmt, 6, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->origtime), 0, (
void *) data->origtime, 0,
NULL);
4424 SQLBindParameter(stmt, 7, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->duration), 0, (
void *) data->duration, 0,
NULL);
4425 SQLBindParameter(stmt, 8, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->mailboxuser), 0, (
void *) data->mailboxuser, 0,
NULL);
4426 SQLBindParameter(stmt, 9, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->mailboxcontext), 0, (
void *) data->mailboxcontext, 0,
NULL);
4427 SQLBindParameter(stmt, 10, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->flag), 0, (
void *) data->flag, 0,
NULL);
4428 SQLBindParameter(stmt, 11, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->msg_id), 0, (
void *) data->msg_id, 0,
NULL);
4430 SQLBindParameter(stmt, 12, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->category), 0, (
void *) data->category, 0,
NULL);
4433 if (!SQL_SUCCEEDED(res)) {
4435 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
4455static int store_file(
const char *dir,
const char *mailboxuser,
const char *mailboxcontext,
int msgnum)
4459 void *fdm = MAP_FAILED;
4470 struct insert_data idata = { .sql = sql, .msgnums = msgnums, .dir = dir, .mailboxuser = mailboxuser, .mailboxcontext = mailboxcontext,
4471 .context =
"", .callerid =
"", .origtime =
"", .duration =
"", .category =
"", .flag =
"", .msg_id =
"" };
4484 c = strchr(fmt,
'|');
4487 if (!strcasecmp(fmt,
"wav49"))
4489 snprintf(msgnums,
sizeof(msgnums),
"%d", msgnum);
4494 snprintf(full_fn,
sizeof(full_fn),
"%s.txt", fn);
4496 snprintf(full_fn,
sizeof(full_fn),
"%s.%s", fn, fmt);
4497 fd = open(full_fn, O_RDWR);
4508 idata.callerid =
"";
4511 idata.origtime =
"";
4514 idata.duration =
"";
4517 idata.category =
"";
4526 fdlen = lseek(fd, 0, SEEK_END);
4527 if (fdlen < 0 || lseek(fd, 0, SEEK_SET) < 0) {
4532 fdm = mmap(
NULL, fdlen, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
4533 if (fdm == MAP_FAILED) {
4539 idata.datalen = idata.indlen = fdlen;
4542 snprintf(sql,
sizeof(sql),
"INSERT INTO %s (dir,msgnum,recording,context,callerid,origtime,duration,mailboxuser,mailboxcontext,flag,msg_id,category) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)", odbc_table);
4544 snprintf(sql,
sizeof(sql),
"INSERT INTO %s (dir,msgnum,recording,context,callerid,origtime,duration,mailboxuser,mailboxcontext,flag,msg_id) VALUES (?,?,?,?,?,?,?,?,?,?,?)", odbc_table);
4547 idata.origtime =
"0";
4551 idata.duration =
"0";
4555 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
4566 if (fdm != MAP_FAILED)
4586static void rename_file(
char *sdir,
int smsg,
char *mailboxuser,
char *mailboxcontext,
char *ddir,
int dmsg)
4593 char *argv[] = { ddir, msgnumd, mailboxuser, mailboxcontext, sdir, msgnums };
4594 struct generic_prepare_struct gps = { .sql = sql, .argc = 6, .argv = argv };
4604 snprintf(msgnums,
sizeof(msgnums),
"%d", smsg);
4605 snprintf(msgnumd,
sizeof(msgnumd),
"%d", dmsg);
4606 snprintf(sql,
sizeof(sql),
"UPDATE %s SET dir=?, msgnum=?, mailboxuser=?, mailboxcontext=? WHERE dir=? AND msgnum=?", odbc_table);
4611 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
4627static int remove_file(
char *dir,
int msgnum)
4634 snprintf(msgnums,
sizeof(msgnums),
"%d", msgnum);
4640 snprintf(full_fn,
sizeof(full_fn),
"%s.txt", fn);
4660 struct dirent *vment =
NULL;
4665 if ((vmdir = opendir(dir))) {
4666 while ((vment = readdir(vmdir))) {
4667 if (strlen(vment->d_name) > 7 && !strncmp(vment->d_name + 7,
".txt", 4)) {
4690 snprintf(stxt,
sizeof(stxt),
"%s.txt", sfn);
4691 snprintf(dtxt,
sizeof(dtxt),
"%s.txt", dfn);
4713 struct dirent *msgdirent;
4722 if (!(msgdir = opendir(dir))) {
4726 while ((msgdirent = readdir(msgdir))) {
4730 ast_debug(4,
"%s map[%d] = %d, count = %d\n", dir, msgdirint, map[msgdirint], stopcount);
4736 stopcount -= map[x];
4755static int copy(
char *infile,
char *outfile)
4763#ifdef HARDLINK_WHEN_POSSIBLE
4765 if (!link(infile, outfile)) {
4770 if ((ifd = open(infile, O_RDONLY)) < 0) {
4795 wrlen = write(ofd,
buf,
len);
4824 const char *origmailbox =
"", *
context =
"", *exten =
"";
4825 const char *
priority =
"", *callerchan =
"", *callerid =
"", *origdate =
"";
4826 const char *origtime =
"", *category =
"", *duration =
"";
4829 snprintf(frompath2,
sizeof(frompath2),
"%s.txt", frompath);
4830 snprintf(topath2,
sizeof(topath2),
"%s.txt", topath);
4836 if (!strcasecmp(
tmp->name,
"origmailbox")) {
4837 origmailbox =
tmp->value;
4838 }
else if (!strcasecmp(
tmp->name,
"context")) {
4840 }
else if (!strcasecmp(
tmp->name,
"exten")) {
4842 }
else if (!strcasecmp(
tmp->name,
"priority")) {
4844 }
else if (!strcasecmp(
tmp->name,
"callerchan")) {
4845 callerchan =
tmp->value;
4846 }
else if (!strcasecmp(
tmp->name,
"callerid")) {
4847 callerid =
tmp->value;
4848 }
else if (!strcasecmp(
tmp->name,
"origdate")) {
4849 origdate =
tmp->value;
4850 }
else if (!strcasecmp(
tmp->name,
"origtime")) {
4851 origtime =
tmp->value;
4852 }
else if (!strcasecmp(
tmp->name,
"category")) {
4853 category =
tmp->value;
4854 }
else if (!strcasecmp(
tmp->name,
"duration")) {
4855 duration =
tmp->value;
4858 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);
4860 copy(frompath2, topath2);
4878 txtsize = (strlen(
file) + 5)*
sizeof(
char);
4886 snprintf(txt, txtsize,
"%s.txt",
file);
4891static 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)
4895 char fromdir[256], fromfile[256];
4897 const char *origcallerid, *origtime;
4898 char origcidname[80], origcidnum[80], origdate[80];
4905 snprintf(num,
sizeof(num),
"%d", msgnum);
4919 make_file(fromfile,
sizeof(fromfile), fromdir, msgnum - 1);
4920 if (strlen(fromfile) <
sizeof(fromfile) - 5) {
4921 strcat(fromfile,
".txt");
4924 ast_debug(1,
"Config load for message text file '%s' failed\n", fromfile);
4930 ast_callerid_split(origcallerid, origcidname,
sizeof(origcidname), origcidnum,
sizeof(origcidnum));
4935 if ((origtime =
ast_variable_retrieve(msg_cfg,
"message",
"origtime")) && sscanf(origtime,
"%30d", &inttime) == 1) {
4936 struct timeval tv = { inttime, };
4959 for (ptr = from; *ptr; ptr++) {
4960 if (*ptr ==
'"' || *ptr ==
'\\') {
5001 if (*
str > 126 || *
str < 32 || strchr(
"()<>@,:;/\"[]?.=", *
str)) {
5028 int first_section = 1;
5032 for (; *start; start++) {
5033 int need_encoding = 0;
5034 if (*start < 33 || *start > 126 || strchr(
"()<>@,:;/\"[]?.=_", *start)) {
5046 if (need_encoding && *start ==
' ') {
5048 }
else if (need_encoding) {
5087 const char *fromfolder,
5094 int attach_user_voicemail,
5096 const char *category,
5107 char enc_cidnum[256] =
"", enc_cidname[256] =
"";
5109 char *greeting_attachment;
5115 if (!str1 || !str2) {
5127 gethostname(host,
sizeof(host) - 1);
5129 if (strchr(srcemail,
'@')) {
5132 snprintf(who,
sizeof(who),
"%s@%s", srcemail, host);
5135 greeting_attachment = strrchr(
ast_strdupa(attach),
'/');
5136 if (greeting_attachment) {
5137 *greeting_attachment++ =
'\0';
5140 snprintf(dur,
sizeof(dur),
"%d:%02d", duration / 60, duration % 60);
5142 fprintf(p,
"Date: %s" ENDL, date);
5152 prep_email_sub_vars(ast, vmu, msgnum + 1,
context,
mailbox, fromfolder, enc_cidnum, enc_cidname, dur, date, category,
flag);
5174 fprintf(p,
"From: Asterisk PBX <%s>" ENDL, who);
5181 char *next = emailsbuf;
5199 fprintf(p,
"Subject: New greeting '%s' on %s." ENDL, greeting_attachment, date);
5204 prep_email_sub_vars(ast, vmu, msgnum + 1,
context,
mailbox, fromfolder, cidnum, cidname, dur, date, category,
flag);
5227 fprintf(p,
"Subject: New message %d in mailbox %s" ENDL, msgnum + 1,
mailbox);
5229 fprintf(p,
"Subject: New %s message %d in mailbox %s" ENDL,
flag, msgnum + 1,
mailbox);
5233 fprintf(p,
"Subject: [PBX]: New message %d in mailbox %s" ENDL, msgnum + 1,
mailbox);
5235 fprintf(p,
"Subject: [PBX]: New %s message %d in mailbox %s" ENDL,
flag, msgnum + 1,
mailbox);
5239 fprintf(p,
"Message-ID: <Asterisk-%d-%u-%s-%d@%s>" ENDL, msgnum + 1,
5243 fprintf(p,
"X-Asterisk-VM-Message-Num: %d" ENDL, msgnum + 1);
5246 fprintf(p,
"X-Asterisk-VM-Context: %s" ENDL,
context);
5250 fprintf(p,
"X-Asterisk-VM-Extension: %s" ENDL,
mailbox);
5253 fprintf(p,
"X-Asterisk-VM-Flag: %s" ENDL,
S_OR(
flag,
""));
5255 fprintf(p,
"X-Asterisk-VM-Caller-ID-Num: %s" ENDL, enc_cidnum);
5256 fprintf(p,
"X-Asterisk-VM-Caller-ID-Name: %s" ENDL, enc_cidname);
5257 fprintf(p,
"X-Asterisk-VM-Duration: %d" ENDL, duration);
5259 fprintf(p,
"X-Asterisk-VM-Category: %s" ENDL, category);
5261 fprintf(p,
"X-Asterisk-VM-Category: " ENDL);
5263 fprintf(p,
"X-Asterisk-VM-Message-Type: %s" ENDL, msgnum > -1 ?
"Message" : greeting_attachment);
5264 fprintf(p,
"X-Asterisk-VM-Orig-date: %s" ENDL, date);
5265 fprintf(p,
"X-Asterisk-VM-Orig-time: %ld" ENDL, (
long) time(
NULL));
5266 fprintf(p,
"X-Asterisk-VM-Message-ID: %s" ENDL, msg_id);
5269 fprintf(p,
"X-Asterisk-CallerID: %s" ENDL, enc_cidnum);
5272 fprintf(p,
"X-Asterisk-CallerIDName: %s" ENDL, enc_cidname);
5274 fprintf(p,
"MIME-Version: 1.0" ENDL);
5275 if (attach_user_voicemail) {
5277 snprintf(bound,
sizeof(bound),
"----voicemail_%d%s%d%u", msgnum + 1,
mailbox,
5278 (
int) getpid(), (
unsigned int)
ast_random());
5280 fprintf(p,
"Content-Type: multipart/mixed; boundary=\"%s\"" ENDL, bound);
5281 fprintf(p,
ENDL ENDL "This is a multi-part message in MIME format." ENDL ENDL);
5282 fprintf(p,
"--%s" ENDL, bound);
5284 fprintf(p,
"Content-Type: text/plain; charset=%s" ENDL "Content-Transfer-Encoding: 8bit" ENDL ENDL,
charset);
5286 fprintf(p,
"This message is to let you know that your greeting '%s' was changed on %s." ENDL
5287 "Please do not delete this message, lest your greeting vanish with it." ENDL ENDL,
5288 greeting_attachment, date);
5293 prep_email_sub_vars(ast, vmu, msgnum + 1,
context,
mailbox, fromfolder, cidnum, cidname, dur, date, category,
flag);
5301 if ((next = strchr(line,
'\n'))) {
5304 fprintf(p,
"%s" ENDL, line);
5321 char fromdir[256], fromfile[256], origdate[80] =
"", origcallerid[80] =
"";
5325 make_file(fromfile,
sizeof(fromfile), fromdir, msgnum);
5326 if (strlen(fromfile) <
sizeof(fromfile) - 5) {
5327 strcat(fromfile,
".txt");
5336 if ((v =
ast_variable_retrieve(msg_cfg,
"message",
"origtime")) && sscanf(v,
"%30d", &inttime) == 1) {
5337 struct timeval tv = { inttime, };
5342 fprintf(p,
"Dear %s:" ENDL ENDL "\tJust wanted to let you know you were just forwarded"
5343 " a %s long message (number %d)" ENDL "in mailbox %s from %s, on %s" ENDL
5344 "(originally sent by %s on %s)" ENDL "so you might want to check it when you get a"
5346 msgnum + 1,
mailbox, (cidname ? cidname : (cidnum ? cidnum :
"an unknown caller")),
5347 date, origcallerid, origdate);
5354 fprintf(p,
"Dear %s:" ENDL ENDL "\tJust wanted to let you know you were just left a "
5355 "%s long message (number %d)" ENDL "in mailbox %s from %s, on %s so you might" ENDL
5356 "want to check it when you get a chance. Thanks!" ENDL ENDL "\t\t\t\t--Asterisk"
5358 (cidname ? cidname : (cidnum ? cidnum :
"an unknown caller")), date);
5362 if (imap || attach_user_voicemail) {
5364 snprintf(filename,
sizeof(filename),
"msg%04d.%s", msgnum, format);
5365 ast_debug(5,
"creating second attachment filename %s\n", filename);
5367 snprintf(filename,
sizeof(filename),
"msgintro%04d.%s", msgnum, format);
5368 ast_debug(5,
"creating attachment filename %s\n", filename);
5371 snprintf(filename,
sizeof(filename),
"msg%04d.%s", msgnum, format);
5372 ast_debug(5,
"creating attachment filename %s, no second attachment.\n", filename);
5384 char *file_to_delete =
NULL, *dir_to_delete =
NULL;
5388 char altformat[80] =
"";
5392 char *mime_type = (!strcasecmp(format,
"ogg")) ?
"application/" :
"audio/x-";
5395 snprintf(fname,
sizeof(fname),
"%s.%s", attach, format);
5398 c = strchr(altformat,
'|');
5403 snprintf(altfname,
sizeof(altfname),
"%s.%s", attach, altformat);
5417 res = snprintf(sox_gain_tmpdir,
sizeof(sox_gain_tmpdir),
"%s/vm-gain-XXXXXX", tmpdir);
5418 if (res >=
sizeof(sox_gain_tmpdir)) {
5419 ast_log(
LOG_ERROR,
"Failed to create temporary directory path %s: Out of buffer space\n", tmpdir);
5423 if (
mkdtemp(sox_gain_tmpdir)) {
5427 ast_debug(3,
"sox_gain_tmpdir: %s\n", sox_gain_tmpdir);
5430 dir_to_delete = sox_gain_tmpdir;
5432 res = snprintf(fname,
sizeof(fname),
"%s/output.%s", sox_gain_tmpdir, format);
5433 if (res >=
sizeof(fname)) {
5434 ast_log(
LOG_ERROR,
"Failed to create filename buffer for %s/output.%s: Too long\n", sox_gain_tmpdir, format);
5439 res = snprintf(sox_gain_cmd,
sizeof(sox_gain_cmd),
"sox -v %.4f %s.%s %s",
5440 vmu->
volgain, attach, format, fname);
5442 if (!strcasecmp(format,
"wav")) {
5444 res = snprintf(sox_gain_cmd,
sizeof(sox_gain_cmd),
"sox -v %.4f %s.%s -e signed-integer -b 16 %s",
5445 vmu->
volgain, attach, altformat, fname);
5447 res = snprintf(sox_gain_cmd,
sizeof(sox_gain_cmd),
"sox %s.%s -e signed-integer -b 16 %s",
5448 attach, altformat, fname);
5452 res = snprintf(sox_gain_cmd,
sizeof(sox_gain_cmd),
"sox -v %.4f %s.%s %s",
5453 vmu->
volgain, attach, altformat, fname);
5455 res = snprintf(sox_gain_cmd,
sizeof(sox_gain_cmd),
"sox %s.%s %s",
5456 attach, altformat, fname);
5461 if (res >=
sizeof(sox_gain_cmd)) {
5462 ast_log(
LOG_ERROR,
"Failed to generate sox command, out of buffer space\n");
5469 file_to_delete = fname;
5472 ast_log(
LOG_WARNING,
"Sox failed to re-encode %s: %s (have you installed support for all sox file formats?)\n",
5474 soxstatus == 1 ?
"Problem with command line options" :
"An error occurred during file processing");
5482 if (!file_to_delete) {
5483 res = snprintf(fname,
sizeof(fname),
"%s.%s", attach, format);
5484 if (res >=
sizeof(fname)) {
5485 ast_log(
LOG_ERROR,
"Failed to create filename buffer for %s.%s: Too long\n", attach, format);
5490 fprintf(p,
"--%s" ENDL, bound);
5492 fprintf(p,
"Content-Type: %s%s; name=\"%s\"" ENDL, mime_type, format, filename);
5494 fprintf(p,
"Content-Type: %s%s; name=\"%s.%s\"" ENDL, mime_type, format, greeting_attachment, format);
5495 fprintf(p,
"Content-Transfer-Encoding: base64" ENDL);
5496 fprintf(p,
"Content-Description: Voicemail sound attachment." ENDL);
5498 fprintf(p,
"Content-Disposition: attachment; filename=\"%s\"" ENDL ENDL, filename);
5500 fprintf(p,
"Content-Disposition: attachment; filename=\"%s.%s\"" ENDL ENDL, greeting_attachment, format);
5505 if (file_to_delete) {
5506 unlink(file_to_delete);
5509 if (dir_to_delete) {
5510 rmdir(dir_to_delete);
5521 const char *fromfolder,
5528 int attach_user_voicemail,
5530 const char *category,
5535 char tmp[80] =
"/tmp/astmail-XXXXXX";
5549 if (!strcmp(format,
"wav49"))
5558 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);
5560 snprintf(tmp2,
sizeof(tmp2),
"( %s < %s ; rm -f %s ) &",
mailcmd,
tmp,
tmp);
5567static 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)
5569 char enc_cidnum[256], enc_cidname[256];
5574 char tmp[80] =
"/tmp/astmail-XXXXXX";
5580 if (!str1 || !str2) {
5599 gethostname(host,
sizeof(host)-1);
5600 if (strchr(srcemail,
'@')) {
5603 snprintf(who,
sizeof(who),
"%s@%s", srcemail, host);
5605 snprintf(dur,
sizeof(dur),
"%d:%02d", duration / 60, duration % 60);
5607 fprintf(p,
"Date: %s\n", date);
5616 prep_email_sub_vars(ast, vmu, msgnum + 1,
context,
mailbox, fromfolder, enc_cidnum, enc_cidname, dur, date, category,
flag);
5638 fprintf(p,
"From: Asterisk PBX <%s>" ENDL, who);
5660 prep_email_sub_vars(ast, vmu, msgnum + 1,
context,
mailbox, fromfolder, cidnum, cidname, dur, date, category,
flag);
5683 fprintf(p,
"Subject: New VM\n\n");
5685 fprintf(p,
"Subject: New %s VM\n\n",
flag);
5692 prep_email_sub_vars(ast, vmu, msgnum + 1,
context,
mailbox, fromfolder, cidnum, cidname, dur, date, category,
flag);
5700 fprintf(p,
"New %s long %s msg in box %s\n"
5701 "from %s, on %s", dur,
flag,
mailbox, (cidname ? cidname : (cidnum ? cidnum :
"unknown")), date);
5705 snprintf(tmp2,
sizeof(tmp2),
"( %s < %s ; rm -f %s ) &",
mailcmd,
tmp,
tmp);
5773static int count_messages_in_folder(
struct odbc_obj *odbc,
const char *
context,
const char *
mailbox,
const char *folder,
int *messages)
5778 SQLHSTMT stmt =
NULL;
5779 struct generic_prepare_struct gps = { .sql = sql, .argc = 0 };
5785 snprintf(sql,
sizeof(sql),
"SELECT COUNT(*) FROM %s WHERE dir = '%s%s/%s/%s'", odbc_table,
VM_SPOOL_DIR,
context,
mailbox, folder);
5790 res = SQLFetch(stmt);
5791 if (!SQL_SUCCEEDED(res)) {
5793 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
5796 res = SQLGetData(stmt, 1, SQL_CHAR, rowdata,
sizeof(rowdata),
NULL);
5797 if (!SQL_SUCCEEDED(res)) {
5799 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
5803 *messages = atoi(rowdata);
5804 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
5809static int inboxcount2(
const char *
mailbox,
int *urgentmsgs,
int *newmsgs,
int *oldmsgs)
5861 if (count_messages_in_folder(obj,
context,
tmp,
"INBOX", newmsgs)
5862 || count_messages_in_folder(obj,
context,
tmp,
"Old", oldmsgs)
5863 || count_messages_in_folder(obj,
context,
tmp,
"Urgent", urgentmsgs)) {
5880static int messagecount(
const char *mailbox_id,
const char *folder)
5887 SQLHSTMT stmt =
NULL;
5890 struct generic_prepare_struct gps = { .sql = sql, .argc = 0 };
5908 if (!strcmp(folder,
"INBOX")) {
5911 snprintf(sql,
sizeof(sql),
"SELECT COUNT(*) FROM %s WHERE dir = '%s%s/%s/%s'", odbc_table,
VM_SPOOL_DIR,
context,
mailbox, folder);
5919 res = SQLFetch(stmt);
5920 if (!SQL_SUCCEEDED(res)) {
5922 goto bail_with_handle;
5924 res = SQLGetData(stmt, 1, SQL_CHAR, rowdata,
sizeof(rowdata),
NULL);
5925 if (!SQL_SUCCEEDED(res)) {
5927 goto bail_with_handle;
5929 nummsgs = atoi(rowdata);
5932 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
5981 const char *frombox =
mbox(vmu, imbox);
5982 const char *userfolder;
5989 userfolder =
"Urgent";
5991 userfolder = dest_folder;
5993 userfolder =
"INBOX";
6003 make_file(frompath,
sizeof(frompath), fromdir, msgnum);
6011 make_file(topath,
sizeof(topath), todir, recipmsgnum);
6014 COPY(fromdir, msgnum, todir, recipmsgnum, recip->
mailbox, recip->
context, frompath, topath);
6021 STORE(todir, recip->
mailbox, recip->
context, recipmsgnum, chan, recip, fmt, duration,
NULL,
NULL,
NULL);
6042#if !(defined(IMAP_STORAGE) || defined(ODBC_STORAGE))
6090 snprintf(fn,
sizeof(fn),
"%s%s/%s/%s",
VM_SPOOL_DIR,
c, m, folder);
6092 if (!(dir = opendir(fn)))
6095 while ((de = readdir(dir))) {
6096 if (!strncasecmp(de->d_name,
"msg", 3)) {
6100 }
else if (!strncasecmp(de->d_name + 8,
"txt", 3)) {
6127 while ((box =
strsep(&tmp2,
",&"))) {
6128 if ((
context = strchr(box,
'@')))
6171 int tmpnew, tmpold, tmpurgent;
6176 while ((cur =
strsep(&mb,
", "))) {
6188 *urgentmsgs += tmpurgent;
6225 *newmsgs += urgentmsgs;
6232 char arguments[255];
6233 char ext_context[256] =
"";
6234 int newvoicemails = 0, oldvoicemails = 0, urgentvoicemails = 0;
6250 if (!strncmp(mwi_msg->
cause,
"INV", 3))
6252 else if (!strncmp(mwi_msg->
cause,
"BLK", 3))
6262 if (
inboxcount2(ext_context, &urgentvoicemails, &newvoicemails, &oldvoicemails)) {
6265 snprintf(arguments,
sizeof(arguments),
"%s %s %s %d %d %d &",
6268 oldvoicemails, urgentvoicemails);
6269 ast_debug(1,
"Executing %s\n", arguments);
6294 snprintf(dst,
MSG_ID_LEN,
"%ld-%08x", (
long) time(
NULL), unique_counter);
6328 char ext_context[256] =
"";
6344 const char *category =
NULL;
6353 memset(&svm, 0,
sizeof(svm));
6365 duration = (int) (framelength / sample_rate);
6374 if (duration < recipient->minsecs) {
6375 ast_log(
LOG_NOTICE,
"Copying recording to voicemail %s@%s skipped because duration was shorter than "
6376 "minmessage of recipient\n", recdata->
mailbox, recdata->
context);
6386 snprintf(tmptxtfile,
sizeof(tmptxtfile),
"%s/XXXXXX", tmpdir);
6387 txtdes = mkstemp(tmptxtfile);
6397 txt = fdopen(txtdes,
"w+");
6403 "; Message Information file\n"
6426 date, (
long) time(
NULL),
6451 snprintf(ext_context,
sizeof(ext_context),
"%s@%s", recipient->
mailbox, recipient->
context);
6455 res =
inboxcount(ext_context, &newmsgs, &oldmsgs);
6462 if (!(vms = get_vm_state_by_mailbox(recipient->
mailbox, recipient->
context, 0))) {
6467 if (!(vms = create_vm_state_from_user(recipient))) {
6477 msgnum = newmsgs + oldmsgs;
6478 ast_debug(3,
"Messagecount set to %d\n", msgnum);
6479 snprintf(destination,
sizeof(destination),
"%simap/msg%s%04d",
VM_SPOOL_DIR, recipient->
mailbox, msgnum);
6483 if ((res = imap_check_limits(
NULL, vms, recipient, msgnum))) {
6510 ast_log(
LOG_ERROR,
"Couldn't lock directory %s. Voicemail will be lost.\n", dir);
6518 make_file(destination,
sizeof(destination), dir, msgnum);
6520 make_file(tmpaudiofile,
sizeof(tmpaudiofile), tmpdir, msgnum);
6523 ast_log(
LOG_ERROR,
"Audio file failed to copy to tmp dir. Probably low disk space.\n");
6534 ast_log(
LOG_ERROR,
"Audio file failed to move to destination directory. Permissions/Overlap?\n");
6542 snprintf(desttxtfile,
sizeof(desttxtfile),
"%s.txt", destination);
6543 rename(tmptxtfile, desttxtfile);
6560 char cidnum[80], cidname[80];
6566 "origmailbox", recdata->
mailbox,
6573 "origtime", time(
NULL),
6574 "category",
S_OR(category,
""),
6575 "filename", tmptxtfile,
6576 "duration", duration,
6580 STORE(dir, recipient->
mailbox, recipient->
context, msgnum,
NULL, recipient, fmt, 0, vms,
"", msg_id);
6622 int newmsgs, oldmsgs;
6634 int sound_duration = 0;
6636 int greeting_only = 0;
6645 char ext_context[256] =
"";
6648 char ecodes[17] =
"#";
6653 const char *category =
NULL;
6655 const char *alldtmf =
"0123456789ABCD*#";
6666 tmpptr = strchr(
context,
'&');
6668 tmpptr = strchr(
ext,
'&');
6689 memset(&svm, 0,
sizeof(svm));
6704 if (strcmp(vmu->
context,
"default"))
6705 snprintf(ext_context,
sizeof(ext_context),
"%s@%s",
ext, vmu->
context);
6750 strncat(ecodes,
"0",
sizeof(ecodes) - strlen(ecodes) - 1);
6755 strncat(ecodes,
"0",
sizeof(ecodes) - strlen(ecodes) - 1);
6763 strncat(ecodes,
"*",
sizeof(ecodes) - strlen(ecodes) - 1);
6767 strncat(ecodes,
"*",
sizeof(ecodes) - strlen(ecodes) - 1);
6771 for (code = alldtmf; *code; code++) {
6774 if (strchr(ecodes, e[0]) ==
NULL
6778 strncat(ecodes, e,
sizeof(ecodes) - strlen(ecodes) - 1);
6799 if (success == -1) {
6801 ast_debug(1,
"Greeting not retrieved from database, but found in file storage. Inserting into database\n");
6806 ast_debug(1,
"%s doesn't exist, doing what we can\n", prefile);
6811 ast_debug(1,
"Hang up during prefile playback\n");
6874 if (greeting_only) {
6875 ast_debug(3,
"Greetings only VM (maxmsg=0), Skipping voicemail recording\n");
6899 res =
inboxcount(ext_context, &newmsgs, &oldmsgs);
6906 if (!(vms = get_vm_state_by_mailbox(
ext,
context, 0))) {
6911 if (!(vms = create_vm_state_from_user(vmu))) {
6921 msgnum = newmsgs + oldmsgs;
6922 ast_debug(3,
"Messagecount set to %d\n", msgnum);
6927 if ((res = imap_check_limits(chan, vms, vmu, msgnum))) {
6942 snprintf(tmptxtfile,
sizeof(tmptxtfile),
"%s/XXXXXX", tmpdir);
6943 txtdes = mkstemp(tmptxtfile);
6967 snprintf(origtime,
sizeof(origtime),
"%ld", (
long) time(
NULL));
6979 "callerid", callerid,
6981 "origtime", origtime,
6982 "category",
S_OR(category,
""),
6983 "filename", tmptxtfile,
6988 txt = fdopen(txtdes,
"w+");
6998 "; Message Information file\n"
7020 date, (
long) time(
NULL),
7021 category ? category :
"",
7032 res =
play_record_review(chan,
NULL, tmptxtfile, vmu->
maxsecs, fmt, 1, vmu, &duration, &sound_duration,
NULL,
options->record_gain, vms,
flag, msg_id, 0);
7038 if (!strcmp(
flag,
"Urgent")) {
7043 fprintf(txt,
"flag=%s\n",
flag);
7044 if (sound_duration < vmu->
minsecs) {
7046 ast_verb(3,
"Recording was %d seconds long but needs to be at least %d - abandoning\n", sound_duration, vmu->
minsecs);
7054 fprintf(txt,
"duration=%d\n", duration);
7063 ast_debug(1,
"The recorded media file is gone, so we should remove the .txt file too!\n");
7083 snprintf(txtfile,
sizeof(txtfile),
"%s.txt", fn);
7085 rename(tmptxtfile, txtfile);
7095 snprintf(tmpdur,
sizeof(tmpdur),
"%d", duration);
7102 STORE(dir, vmu->
mailbox, vmu->
context, msgnum, chan, vmu, fmt, duration, vms,
flag, msg_id);
7110 exten =
strsep(&tmpptr,
"&");
7111 cntx = strchr(exten,
'@');
7116 memset(&recipu, 0,
sizeof(recipu));
7117 if ((recip =
find_user(&recipu, cntx, exten))) {
7149 }
else if (res > 0 && res !=
't')
7152 if (sound_duration < vmu->
minsecs)
7164 ast_debug(3,
"*** Checking if we can expunge, expungeonhangup set to %d\n", expungeonhangup);
7165 if (expungeonhangup == 1 && vms->mailstream !=
NULL) {
7167#ifdef HAVE_IMAP_TK2006
7168 if (LEVELUIDPLUS (vms->mailstream)) {
7169 mail_expunge_full(vms->mailstream, NIL, EX_UID);
7172 mail_expunge(vms->mailstream);
7181#if !defined(IMAP_STORAGE)
7194 for (x = 0, dest = 0; dest != stopcount && x <
MAXMSGLIMIT; x++) {
7230 snprintf(sequence,
sizeof(sequence),
"%ld", vms->msgArray[msg]);
7232 ast_debug(3,
"Copying sequence %s to mailbox %s\n", sequence,
mbox(vmu, box));
7236 mail_setflag(vms->mailstream, sequence,
"\\Seen");
7238 mail_clearflag(vms->mailstream, sequence,
"\\Seen");
7250 if (vms->mailstream && !mail_status(vms->mailstream,
mailbox, SA_UIDNEXT)) {
7251 if (mail_create(vms->mailstream,
mailbox) != NIL) {
7257 if (init_mailstream(vms, curr_mbox) || !vms->mailstream) {
7262 res = !mail_move(vms->mailstream, sequence, (
char *)
mbox(vmu, box));
7264 res = !mail_copy(vms->mailstream, sequence, (
char *)
mbox(vmu, box));
7276 const char *dbox =
mbox(vmu, box);
7287 for (i = 1; i <= x; i++) {
7290 make_file(dfn,
sizeof(dfn), ddir, i - 1);
7304 if (strcmp(sfn, dfn)) {
7305 COPY(dir, msg, ddir, x, username,
context, sfn, dfn);
7326 unsigned char buf[256];
7358 bytes += ast_adsi_logo(
buf);
7402 for (x = 0; x < 5; x++) {
7403 snprintf(num,
sizeof(num),
"%d", x);
7431 ast_debug(1,
"Done downloading scripts...\n");
7439 ast_debug(1,
"Restarting session...\n");
7475 unsigned char buf[256];
7477 unsigned char keys[8];
7482 for (x = 0; x < 8; x++)
7501 unsigned char buf[256];
7503 unsigned char keys[8];
7508 for (x = 0; x < 8; x++)
7523 unsigned char buf[256];
7525 unsigned char keys[8];
7531 for (x = 0; x < 5; x++) {
7553 unsigned char buf[256];
7560 char datetime[21] =
"";
7563 unsigned char keys[8];
7571 snprintf(fn2,
sizeof(fn2),
"%s.txt", vms->
fn);
7572 f = fopen(fn2,
"r");
7575 if (!fgets((
char *)
buf,
sizeof(
buf), f)) {
7579 char *stringp =
NULL;
7580 stringp = (
char *)
buf;
7584 if (!strcmp((
char *)
buf,
"callerid"))
7586 if (!strcmp((
char *)
buf,
"origdate"))
7594 for (x = 0; x < 5; x++)
7621 name =
"Unknown Caller";
7638 strcasecmp(vms->
curbox,
"INBOX") ?
" Messages" :
"");
7655 unsigned char buf[256];
7656 unsigned char keys[8];
7664 for (x = 0; x < 5; x++)
7706 unsigned char buf[256] =
"";
7707 char buf1[256] =
"",
buf2[256] =
"";
7709 unsigned char keys[8];
7712 char *newm = (vms->
newmessages == 1) ?
"message" :
"messages";
7713 char *oldm = (vms->
oldmessages == 1) ?
"message" :
"messages";
7719 strncat(
buf1,
" and",
sizeof(
buf1) - strlen(
buf1) - 1);
7722 snprintf(
buf2,
sizeof(
buf2),
"%s.", newm);
7726 snprintf(
buf2,
sizeof(
buf2),
"%s.", oldm);
7728 strcpy(
buf1,
"You have no messages.");
7736 for (x = 0; x < 6; x++)
7753 unsigned char buf[256] =
"";
7754 char buf1[256] =
"",
buf2[256] =
"";
7756 unsigned char keys[8];
7759 char *mess = (vms->
lastmsg == 0) ?
"message" :
"messages";
7765 for (x = 0; x < 6; x++)
7775 strcasecmp(vms->
curbox,
"INBOX") ?
" folder" :
"");
7780 strcpy(
buf2,
"no messages.");
7809 unsigned char buf[256];
7835 for (x = start; x < 5; x++) {
7841 snprintf(fn,
sizeof(fn),
"vm-%s",
mbox(
NULL, x));
7850 ast_verb(4,
"Failed to find file %s; falling back to INBOX\n", fn);
7878 for (x = start; x < 5; x++) {
7882 snprintf(fn,
sizeof(fn),
"vm-%s",
mbox(
NULL, x));
7918 while (((res <
'0') || (res >
'9')) &&
7919 (res !=
'#') && (res >= 0) &&
7934 isprint(res) ? res :
'?', isprint(res) ? res :
'?');
7960 int retries = 0, prepend_duration = 0, already_recorded = 0;
7966 signed char zero_gain = 0;
7968 const char *msg_id =
NULL;
7970 const char *duration_str;
7973 make_file(msgfile,
sizeof(msgfile), curdir, curmsg);
7974 strcpy(textfile, msgfile);
7975 strcpy(backup, msgfile);
7976 strcpy(backup_textfile, msgfile);
7977 strncat(textfile,
".txt",
sizeof(textfile) - strlen(textfile) - 1);
7978 strncat(backup,
"-bak",
sizeof(backup) - strlen(backup) - 1);
7979 strncat(backup_textfile,
"-bak.txt",
sizeof(backup_textfile) - strlen(backup_textfile) - 1);
7982 *duration = atoi(duration_str);
7987 while ((cmd >= 0) && (cmd !=
't') && (cmd !=
'*')) {
7998 make_file(vms->introfn,
sizeof(vms->introfn), curdir, curmsg);
7999 strncat(vms->introfn,
"intro",
sizeof(vms->introfn));
8002 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);
8011 make_file(msgfile,
sizeof(msgfile), curdir, curmsg);
8012 strcpy(textfile, msgfile);
8013 strncat(textfile,
".txt",
sizeof(textfile) - 1);
8024 if (already_recorded) {
8026 copy(backup_textfile, textfile);
8030 copy(textfile, backup_textfile);
8033 already_recorded = 1;
8051 *duration = atoi(duration_str);
8053 if (prepend_duration) {
8056 char duration_buf[12];
8058 *duration += prepend_duration;
8060 snprintf(duration_buf,
sizeof(duration_buf),
"%ld", *duration);
8071 *vms->introfn =
'\0';
8080 already_recorded = 0;
8098 isprint(cmd) ? cmd :
'?', isprint(cmd) ? cmd :
'?');
8104 if (prepend_duration)
8105 *duration = prepend_duration;
8107 if (already_recorded && cmd == -1) {
8110 rename(backup_textfile, textfile);
8113 if (cmd ==
't' || cmd ==
'S')
8118static void queue_mwi_event(
const char *channel_id,
const char *box,
int urgent,
int new,
int old)
8127 ast_debug(3,
"Queueing event for mailbox %s New: %d Old: %d\n", box,
new + urgent, old);
8140 ast_debug(3,
"Found alias mapping: %s -> %s\n", mapping->
alias, box);
8166 int newmsgs = 0, oldmsgs = 0, urgentmsgs = 0;
8167 const char *category;
8179 snprintf(todir,
sizeof(todir),
"%simap",
VM_SPOOL_DIR);
8181 make_file(fn,
sizeof(fn), todir, msgnum);
8182 snprintf(ext_context,
sizeof(ext_context),
"%s@%s", vmu->
mailbox, vmu->
context);
8201 char *msg_id =
NULL;
8207 snprintf(filename,
sizeof(filename),
"%s.txt", fn);
8215 if (attach_user_voicemail)
8219 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);
8221 if (attach_user_voicemail)
8226 sendpage(myserveremail, vmu->
pager, msgnum, vmu->
context, vmu->
mailbox,
mbox(vmu, 0), cidnum, cidname, duration, vmu, category,
flag);
8230 DELETE(todir, msgnum, fn, vmu);
8285 char ecodes[16] =
"#";
8286 int res = 0, cmd = 0;
8291 const char mailbox_context[256];
8292 int saved_messages = 0;
8293 int valid_extensions = 0;
8296 char urgent_str[7] =
"";
8297 int prompt_played = 0;
8302 ast_copy_string(urgent_str, urgent ?
"Urgent" :
"",
sizeof(urgent_str));
8305 if (vms ==
NULL)
return -1;
8310 while (!res && !valid_extensions) {
8311 int use_directory = 0;
8316 while ((cmd >= 0) && !
done ){
8346 isprint(cmd) ? cmd :
'?', isprint(cmd) ? cmd :
'?');
8349 if (cmd < 0 || cmd ==
't')
8353 if (use_directory) {
8356 struct ast_app* directory_app;
8359 if (directory_app) {
8360 char vmcontext[256];
8370 snprintf(vmcontext,
sizeof(vmcontext),
"%s,,v",
context ?
context :
"default");
8371 res =
pbx_exec(chan, directory_app, vmcontext);
8387 if (res || prompt_played > 4)
8389 if ((res =
ast_readstring(chan, username,
sizeof(username) - 1, 2000, 10000,
"#")) < 0)
8397 s =
strsep(&stringp,
"*");
8399 valid_extensions = 1;
8401 snprintf((
char*)mailbox_context,
sizeof(mailbox_context),
"%s@%s", s,
context ?
context :
"default");
8407 if (
inboxcount(mailbox_context, &newmsgs, &oldmsgs)) {
8408 ast_log(
LOG_ERROR,
"Problem in calculating number of voicemail messages available for extension %s\n", mailbox_context);
8411 valid_extensions = 0;
8415 if (!(dstvms = get_vm_state_by_mailbox(s,
context, 0))) {
8416 if (!(dstvms = create_vm_state_from_user(receiver))) {
8420 valid_extensions = 0;
8424 check_quota(dstvms, imapfolder);
8425 if (dstvms->quota_limit && dstvms->quota_usage >= dstvms->quota_limit) {
8426 ast_log(
LOG_NOTICE,
"Mailbox '%s' is exceeded quota %u >= %u\n", mailbox_context, dstvms->quota_usage, dstvms->quota_limit);
8428 valid_extensions = 0;
8437 if ((newmsgs + oldmsgs) >= capacity) {
8438 ast_log(
LOG_NOTICE,
"Mailbox '%s' is full with capacity of %d, prompting for another extension.\n", mailbox_context, capacity);
8440 valid_extensions = 0;
8461 valid_extensions = 0;
8479 s =
strsep(&stringp,
"*");
8482 if (valid_extensions)
8488 if (is_new_message == 1) {
8494 memset(&leave_options, 0,
sizeof(leave_options));
8502 int copy_msg_result = 0;
8506 const char *msg_id =
NULL;
8509 memcpy(&vmstmp, vms,
sizeof(vmstmp));
8513 make_file(filename,
sizeof(filename), dir, curmsg);
8514 strncat(filename,
".txt",
sizeof(filename) - strlen(filename) - 1);
8522 cmd =
vm_forwardoptions(chan, sender, vmstmp.
curdir, curmsg,
vmfmts,
S_OR(
context,
"default"), record_gain, &duration, &vmstmp, urgent_str);
8526 int attach_user_voicemail;
8530 dstvms = get_vm_state_by_mailbox(vmtmp->mailbox, vmtmp->context, 0);
8532 dstvms = create_vm_state_from_user(vmtmp);
8535 init_mailstream(dstvms, 0);
8536 if (!dstvms->mailstream) {
8539 copy_msg_result =
STORE(vmstmp.
curdir, vmtmp->mailbox, vmtmp->context, curmsg, chan, vmtmp, fmt, duration, dstvms, urgent_str, msg_id);
8546 myserveremail = vmtmp->serveremail;
8549 sendmail(myserveremail, vmtmp, todircount, vmtmp->context, vmtmp->mailbox,
8553 vmstmp.
fn, vmstmp.introfn, fmt, duration, attach_user_voicemail, chan,
8554 NULL, urgent_str, msg_id);
8556 copy_msg_result =
copy_message(chan, sender, 0, curmsg, duration, vmtmp, fmt, dir, urgent_str,
NULL);
8566 if (saved_messages > 0 && !copy_msg_result) {
8583 make_file(msgfile,
sizeof(msgfile), dir, curmsg);
8584 strcpy(textfile, msgfile);
8585 strcpy(backup, msgfile);
8586 strcpy(backup_textfile, msgfile);
8587 strncat(textfile,
".txt",
sizeof(textfile) - strlen(textfile) - 1);
8588 strncat(backup,
"-bak",
sizeof(backup) - strlen(backup) - 1);
8589 strncat(backup_textfile,
"-bak.txt",
sizeof(backup_textfile) - strlen(backup_textfile) - 1);
8592 rename(backup_textfile, textfile);
8599 make_file(msgfile,
sizeof(msgfile), dir, curmsg);
8600 strcpy(textfile, msgfile);
8601 strcpy(backup_textfile, msgfile);
8602 strncat(textfile,
".txt",
sizeof(textfile) - strlen(textfile) - 1);
8603 strncat(backup_textfile,
"-bak.txt",
sizeof(backup_textfile) - strlen(backup_textfile) - 1);
8604 rename(backup_textfile, textfile);
8614 return res ? res : cmd;
8679 if (time_now.tm_year == time_then.tm_year)
8680 snprintf(temp,
sizeof(temp),
"%d", time_now.tm_yday);
8682 snprintf(temp,
sizeof(temp),
"%d", (time_now.tm_year - time_then.tm_year) * 365 + (time_now.tm_yday - time_then.tm_yday));
8728 char *callerid, *
name;
8742 ast_debug(1,
"VM-CID: composite caller ID received: %s, context: %s\n", cid,
context);
8759 ast_verb(3,
"Playing envelope info: CID number '%s' matches mailbox number, playing recorded name\n", callerid);
8764 ast_verb(3,
"Playing envelope info: message from '%s'\n", callerid);
8767 res =
wait_file2(chan, vms,
"vm-from-extension");
8773 ast_debug(1,
"VM-CID: Numeric caller id: (%s)\n", callerid);
8779 ast_verb(3,
"Playing recorded name for CID number '%s' - '%s'\n", callerid,prefile);
8782 ast_verb(3,
"Played recorded name result '%d'\n", res);
8785 wait_file2(chan, vms,
"vm-from-phonenumber");
8794 ast_debug(1,
"VM-CID: From an unknown number\n");
8796 res =
wait_file2(chan, vms,
"vm-unknown-caller");
8807 if (duration ==
NULL)
8811 durations = atoi(duration);
8812 durationm = (durations / 60);
8814 ast_debug(1,
"VM-Duration: duration is: %d seconds converted to: %d minutes\n", durations, durationm);
8816 if ((!res) && (durationm >= minduration)) {
8821 div_t num = div(durationm, 10);
8823 if (durationm == 1) {
8826 }
else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
8855 const char *origtime, *
context, *category, *duration, *
flag;
8868 snprintf(filename,
sizeof(filename),
"%s.txt", vms->
fn);
8889 ten = (vms->
curmsg + 1) / 10;
8890 one = (vms->
curmsg + 1) % 10;
8893 snprintf(nextmsg,
sizeof(nextmsg),
"digits/n-%d", vms->
curmsg + 1);
8896 snprintf(nextmsg,
sizeof(nextmsg),
"digits/n-%d", ten * 10);
8900 snprintf(nextmsg,
sizeof(nextmsg),
"digits/n-%d", one);
8942 res =
wait_file2(chan, vms,
"vm-meddelandet");
9011 isprint(res) ? res :
'?', isprint(res) ? res :
'?');
9018static int imap_remove_file(
char *dir,
int msgnum)
9026 snprintf(
intro,
sizeof(
intro),
"%sintro", fn);
9030 if ((msgnum < 0 && imapgreetings) || msgnum > -1) {
9035 snprintf(full_fn,
sizeof(full_fn),
"%s.txt", fn);
9043static int imap_delete_old_greeting (
char *dir,
struct vm_state *vms)
9045 char *
file, *filename;
9055 ast_log(
AST_LOG_ERROR,
"Failed to procure file name from directory passed. You should never see this.\n");
9070 for (i = 0; i < vms->mailstream->nmsgs; i++) {
9071 mail_fetchstructure(vms->mailstream, i + 1, &body);
9073 if (body->nested.part->next && body->nested.part->next->body.parameter->value) {
9074 char *attachment = body->nested.part->next->body.parameter->value;
9075 char copy[strlen(attachment) + 1];
9077 strcpy(
copy, attachment);
9080 filename =
strsep(&attachment,
".");
9081 if (!strcmp(filename,
file)) {
9082 snprintf(arg,
sizeof(arg),
"%d", i + 1);
9083 mail_setflag(vms->mailstream, arg,
"\\DELETED");
9091 mail_expunge(vms->mailstream);
9093 if (curr_mbox != -1) {
9095 if (init_mailstream(vms, curr_mbox) || !vms->mailstream) {
9104#elif !defined(IMAP_STORAGE)
9107 int count_msg, last_msg;
9121 if (count_msg < 0) {
9147 if (last_msg < -1) {
9149 }
else if (vms->
lastmsg != last_msg) {
9150 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);
9161 int last_msg_idx = 0;
9164 int res = 0, nummsg;
9181 if (last_msg_idx != vms->
lastmsg) {
9186 for (x = 0; x < last_msg_idx + 1; x++) {
9195 if (strcmp(vms->
fn, fn2)) {
9229 for (x = vms->
curmsg + 1; x <= nummsg; x++) {
9242 for (x = last_msg_idx - 1; x >= 0; x--) {
9283 if (!strcasecmp(box,
"vm-INBOX") || !strcasecmp(box,
"vm-Old")){
9296 if (!strcasecmp(box,
"vm-INBOX") || !strcasecmp(box,
"vm-Old")) {
9309 if (!strcasecmp(box,
"vm-INBOX") || !strcasecmp(box,
"vm-Old")) {
9310 if (!strcasecmp(box,
"vm-INBOX"))
9325 if (!strcasecmp(box,
"vm-Family") || !strcasecmp(box,
"vm-Friends") || !strcasecmp(box,
"vm-Work")){
9684 snprintf(recname,
sizeof(recname),
"digits/1kvk");
9686 snprintf(recname,
sizeof(recname),
"digits/%dhk", vms->
urgentmessages);
9699 snprintf(recname,
sizeof(recname),
"digits/1kvk");
9701 snprintf(recname,
sizeof(recname),
"digits/%dhk", vms->
newmessages);
9716 snprintf(recname,
sizeof(recname),
"digits/1kvk");
9718 snprintf(recname,
sizeof(recname),
"digits/%dhk", vms->
oldmessages);
9794 }
else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
9821 }
else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
10432 static int deprecation_warning = 0;
10433 if (deprecation_warning++ % 10 == 0) {
10434 ast_log(
LOG_WARNING,
"cz is not a standard language code. Please switch to using cs instead.\n");
10502 if (skipadvanced) {
10517 if (!res && !skipadvanced)
10532 int curmsg_deleted;
10541 if (!curmsg_deleted) {
10591 if (skipadvanced) {
10612 if (!res && !skipadvanced)
10627 int curmsg_deleted;
10635 if (!curmsg_deleted) {
10706 char newpassword[80] =
"";
10707 char newpassword2[80] =
"";
10709 unsigned char buf[256];
10726 cmd =
play_record_review(chan,
"vm-rec-name", prefile,
maxgreet, fmtc, 0, vmu, &duration,
NULL,
NULL, record_gain, vms,
NULL,
NULL, 0);
10727 if (cmd < 0 || cmd ==
't' || cmd ==
'#')
10736 cmd =
play_record_review(chan,
"vm-rec-unv", prefile,
maxgreet, fmtc, 0, vmu, &duration,
NULL,
NULL, record_gain, vms,
NULL,
NULL, 0);
10737 if (cmd < 0 || cmd ==
't' || cmd ==
'#')
10743 cmd =
play_record_review(chan,
"vm-rec-busy", prefile,
maxgreet, fmtc, 0, vmu, &duration,
NULL,
NULL, record_gain, vms,
NULL,
NULL, 0);
10744 if (cmd < 0 || cmd ==
't' || cmd ==
'#')
10754 newpassword[1] =
'\0';
10757 newpassword[0] =
'\0';
10758 if (cmd < 0 || cmd ==
't' || cmd ==
'#')
10760 cmd =
ast_readstring(chan, newpassword + strlen(newpassword),
sizeof(newpassword) - 1, 2000, 10000,
"#");
10761 if (cmd < 0 || cmd ==
't' || cmd ==
'#')
10768 newpassword2[1] =
'\0';
10771 newpassword2[0] =
'\0';
10772 if (cmd < 0 || cmd ==
't' || cmd ==
'#')
10774 cmd =
ast_readstring(chan, newpassword2 + strlen(newpassword2),
sizeof(newpassword2) - 1, 2000, 10000,
"#");
10775 if (cmd < 0 || cmd ==
't' || cmd ==
'#')
10777 if (!strcmp(newpassword, newpassword2))
10793 ast_debug(1,
"User %s set password to %s of length %d\n", vms->
username, newpassword, (
int) strlen(newpassword));
10804 char newpassword[80] =
"";
10805 char newpassword2[80] =
"";
10807 unsigned char buf[256];
10819 while ((cmd >= 0) && (cmd !=
't')) {
10825 cmd =
play_record_review(chan,
"vm-rec-unv", prefile,
maxgreet, fmtc, 0, vmu, &duration,
NULL,
NULL, record_gain, vms,
NULL,
NULL, 0);
10829 cmd =
play_record_review(chan,
"vm-rec-busy", prefile,
maxgreet, fmtc, 0, vmu, &duration,
NULL,
NULL, record_gain, vms,
NULL,
NULL, 0);
10833 cmd =
play_record_review(chan,
"vm-rec-name", prefile,
maxgreet, fmtc, 0, vmu, &duration,
NULL,
NULL, record_gain, vms,
NULL,
NULL, 0);
10843 newpassword[1] =
'\0';
10846 newpassword[0] =
'\0';
10850 if ((cmd =
ast_readstring(chan, newpassword + strlen(newpassword),
sizeof(newpassword) - 1, 2000, 10000,
"#")) < 0) {
10863 newpassword2[1] =
'\0';
10866 newpassword2[0] =
'\0';
10871 if ((cmd =
ast_readstring(chan, newpassword2 + strlen(newpassword2),
sizeof(newpassword2) - 1, 2000, 10000,
"#")) < 0) {
10875 if (strcmp(newpassword, newpassword2)) {
10891 ast_debug(1,
"User %s set password to %s of length %d\n",
10892 vms->
username, newpassword, (
int) strlen(newpassword));
10919 isprint(cmd) ? cmd :
'?', isprint(cmd) ? cmd :
'?');
10949 unsigned char buf[256];
10963 while ((cmd >= 0) && (cmd !=
't')) {
10968 cmd =
play_record_review(chan,
"vm-rec-temp", prefile,
maxgreet, fmtc, 0, vmu, &duration,
NULL,
NULL, record_gain, vms,
NULL,
NULL, 0);
10976 cmd =
play_record_review(chan,
"vm-rec-temp", prefile,
maxgreet, fmtc, 0, vmu, &duration,
NULL,
NULL, record_gain, vms,
NULL,
NULL, 0);
10979 DELETE(prefile, -1, prefile, vmu);
10989 "vm-tempgreeting2" :
"vm-tempgreeting");
11000 isprint(cmd) ? cmd :
'?', isprint(cmd) ? cmd :
'?');
11026 if (!strcasecmp(vms->
vmbox,
"vm-INBOX") ||!strcasecmp(vms->
vmbox,
"vm-Old")){
11028 snprintf(vms->
fn,
sizeof(vms->
fn),
"vm-%ss", vms->
curbox);
11037 snprintf(vms->
fn,
sizeof(vms->
fn),
"vm-%s", vms->
curbox);
11053 if (!strcasecmp(vms->
fn,
"INBOX")) {
11081 snprintf(vms->
fn,
sizeof(vms->
fn),
"vm-%s", vms->
curbox);
11109 snprintf(vms->
fn,
sizeof(vms->
fn),
"vm-%s", vms->
curbox);
11131 snprintf(vms->
fn,
sizeof(vms->
fn),
"vm-%s", vms->
curbox);
11162 snprintf(vms->
fn,
sizeof(vms->
fn),
"vm-%s", vms->
curbox);
11186 snprintf(vms->
fn,
sizeof(vms->
fn),
"vm-%s", vms->
curbox);
11216 snprintf(vms->
fn,
sizeof(vms->
fn),
"vm-%s", vms->
curbox);
11240 snprintf(vms->
fn,
sizeof(vms->
fn),
"vm-%s", vms->
curbox);
11283 int skipuser,
int max_logins,
int silent)
11285 int useadsi = 0, valid = 0, logretries = 0;
11291 if (!skipuser && useadsi)
11300 while (!valid && (logretries < max_logins)) {
11310 ast_verb(3,
"Username not entered\n");
11313 }
else if (
mailbox[0] ==
'*') {
11315 ast_verb(4,
"Mailbox begins with '*', attempting jump to extension 'a'\n");
11320 ast_verb(4,
"Jump to extension 'a' failed; setting mailbox to NULL\n");
11328 char fullusername[80];
11331 strncat(fullusername,
mailbox,
sizeof(fullusername) - 1 - strlen(fullusername));
11336 memset(&vmus, 0,
sizeof(vmus));
11355 ast_verb(4,
"Password begins with '*', attempting jump to extension 'a'\n");
11362 ast_verb(4,
"Jump to extension 'a' failed; setting mailbox and user to NULL\n");
11372 if (passptr[0] ==
'-') passptr++;
11374 if (vmu && !strcmp(passptr,
password))
11383 if (skipuser || logretries >= max_logins) {
11404 if (!valid && (logretries >= max_logins)) {
11410 if (vmu && !skipuser) {
11419 const char *msg_id)
11468 memset(&vmus, 0,
sizeof(vmus));
11469 memset(&vms, 0,
sizeof(vms));
11472 goto play_msg_cleanup;
11484 goto play_msg_cleanup;
11496 goto play_msg_cleanup;
11512 vmstate_delete(&vms);
11562#define VMBOX_STRING_HEADER_FORMAT "%-32.32s %-32.32s %-16.16s %-16.16s %-16.16s %-16.16s\n"
11563#define VMBOX_STRING_DATA_FORMAT "%-32.32s %-32.32s %-16.16s %-16.16s %-16.16s %-16.16s\n"
11569 memset(&vmus, 0,
sizeof(vmus));
11570 memset(&vms, 0,
sizeof(vms));
11585#define VM_STRING_HEADER_FORMAT "%-8.8s %-32.32s %-32.32s %-9.9s %-6.6s %-30.30s\n"
11594 if (!mailbox_snapshot) {
11601 for (i = 0; i < mailbox_snapshot->
folders; i++) {
11604 msg->flag,
msg->msg_id);
11627 const char *from_context =
a->argv[3];
11628 const char *from_folder =
a->argv[4];
11629 const char *
id[] = {
a->argv[5] };
11630 const char *to_mailbox =
a->argv[6];
11631 const char *to_context =
a->argv[7];
11632 const char *to_folder =
a->argv[8];
11635 ast_cli(
a->fd,
"Error forwarding message %s from mailbox %s@%s %s to mailbox %s@%s %s\n",
11636 id[0],
from_mailbox, from_context, from_folder, to_mailbox, to_context, to_folder);
11638 ast_cli(
a->fd,
"Forwarded message %s from mailbox %s@%s %s to mailbox %s@%s %s\n",
11639 id[0],
from_mailbox, from_context, from_folder, to_mailbox, to_context, to_folder);
11648 const char *from_folder =
a->argv[4];
11649 const char *
id[] = {
a->argv[5] };
11650 const char *to_folder =
a->argv[6];
11653 ast_cli(
a->fd,
"Error moving message %s from mailbox %s@%s %s to %s\n",
11656 ast_cli(
a->fd,
"Moved message %s from mailbox %s@%s %s to %s\n",
11666 const char *folder =
a->argv[4];
11667 const char *
id[] = {
a->argv[5] };
11670 ast_cli(
a->fd,
"Error removing message %s from mailbox %s@%s %s\n",
11673 ast_cli(
a->fd,
"Removed message %s from mailbox %s@%s %s\n",
11681 const char *
word =
a->word;
11692 wordlen = strlen(
word);
11695 if (!strncasecmp(
word, vmu->
mailbox , wordlen)) {
11705 }
else if (pos == 4) {
11707 const char *box =
a->argv[3];
11708 wordlen = strlen(
word);
11730 e->
command =
"voicemail show mailbox";
11732 "Usage: voicemail show mailbox <mailbox> <context>\n"
11733 " Show contents of mailbox <mailbox>@<context>\n";
11741 if (
a->argc != 5) {
11771 const char *
word =
a->word;
11777 const char *
context =
"", *
mailbox =
"", *folder =
"", *
id =
"";
11780 if (pos > maxpos) {
11786 if (pos == 2 || (pos == 6 && maxpos == 8)) {
11788 wordlen = strlen(
word);
11791 if (!strncasecmp(
word, vmu->
mailbox , wordlen)) {
11801 }
else if (pos == 3 || pos == 7) {
11803 mailbox = (pos == 3) ?
a->argv[2] :
a->argv[6];
11804 wordlen = strlen(
word);
11817 }
else if (pos == 4 || pos == 8 || (pos == 6 && maxpos == 6) ) {
11820 wordlen = strlen(
word);
11827 }
else if (pos == 5) {
11833 folder =
a->argv[4];
11834 wordlen = strlen(
word);
11846 if (
id && !strncasecmp(
word,
msg->msg_id, wordlen) && ++which >
state) {
11864 e->
command =
"voicemail forward";
11866 "Usage: voicemail forward <from_mailbox> <from_context> <from_folder> <messageid> <to_mailbox> <to_context> <to_folder>\n"
11867 " Forward message <messageid> in mailbox <mailbox>@<context> <from_folder>\n"
11868 " to mailbox <mailbox>@<context> <to_folder>\n";
11876 if (
a->argc != 9) {
11891 e->
command =
"voicemail move";
11893 "Usage: voicemail move <mailbox> <context> <from_folder> <messageid> <to_folder>\n"
11894 " Move message <messageid> in mailbox <mailbox>&<context> from <from_folder> to <to_folder>\n";
11902 if (
a->argc != 7) {
11917 e->
command =
"voicemail remove";
11919 "Usage: voicemail remove <mailbox> <context> <from_folder> <messageid>\n"
11920 " Remove message <messageid> from <from_folder> in mailbox <mailbox>@<context>\n";
11928 if (
a->argc != 6) {
11947 char prefixstr[80] =
"";
11948 char ext_context[256]=
"";
11955 int silentexit = 0;
11957 signed char record_gain = 0;
11959 int play_folder = 0;
11987 if (
args.argc == 2) {
11997 record_gain = (
signed char) gain;
12017 if (play_folder > 9 || play_folder < 0) {
12019 "Invalid value '%s' provided for folder autoplay option. Defaulting to 'INBOX'\n",
12029 while (*(
args.argv0)) {
12030 if (*(
args.argv0) ==
's')
12032 else if (*(
args.argv0) ==
'p')
12066 ast_debug(1,
"After vm_authenticate\n");
12096 pthread_once(&ts_vmstate.once, ts_vmstate.key_init);
12097 pthread_setspecific(ts_vmstate.key, &vms);
12099 vms.interactive = 1;
12103 vmstate_insert(&vms);
12104 init_vm_state(&vms);
12110 ast_channel_language_set(chan, vmu->
language);
12182 if ((cmd ==
't') || (cmd ==
'#')) {
12187 }
else if (cmd < 0) {
12195 ast_debug(3,
"Checking quotas: comparing %u to %u\n", vms.quota_usage, vms.quota_limit);
12196 if (vms.quota_limit && vms.quota_usage >= vms.quota_limit) {
12197 ast_debug(1,
"*** QUOTA EXCEEDED!!\n");
12214 isprint(cmd) ? cmd :
'?', isprint(cmd) ? cmd :
'?');
12218 while ((cmd > -1) && (cmd !=
't') && (cmd !=
'#')) {
12235 isprint(cmd) ? cmd :
'?', isprint(cmd) ? cmd :
'?');
12238 }
else if (cmd > 0) {
12244 if (cmd != 11) in_urgent = 0;
12265 while ((cmd > -1) && (cmd !=
't') && (cmd !=
'#')) {
12281 ast_verb(3,
"Callback Requested\n");
12368 isprint(cmd) ? cmd :
'?', isprint(cmd) ? cmd :
'?');
12395 ast_debug(1,
"No more new messages, opened INBOX and got %d Urgent messages\n", vms.
lastmsg + 1);
12426 ast_debug(1,
"No more urgent messages, opened INBOX and got %d new messages\n", vms.
lastmsg + 1);
12445 if (play_folder == 0) {
12452 else if (play_folder == 1)
12456 if (play_folder == 0) {
12463 else if (play_folder == 1)
12479 if (in_urgent == 1) {
12488 ast_debug(1,
"No more urgent messages, opened INBOX and got %d new messages\n", vms.
lastmsg + 1);
12526 ast_debug(1,
"No more urgent messages, opened INBOX and got %d new messages\n", vms.
lastmsg + 1);
12547 isprint(cmd) ? cmd :
'?', isprint(cmd) ? cmd :
'?');
12552 }
else if (cmd > 0) {
12553 box = cmd = cmd -
'0';
12558#ifndef IMAP_STORAGE
12570 snprintf(vms.
fn,
sizeof(vms.
fn),
"vm-%s",
mbox(vmu, box));
12603 ast_debug(1,
"No more urgent messages, opened INBOX and got %d new messages\n", vms.
lastmsg + 1);
12662 if ((cmd ==
't') || (cmd ==
'#')) {
12689 int new = 0, old = 0, urgent = 0;
12690 snprintf(ext_context,
sizeof(ext_context),
"%s@%s", vms.
username, vmu->
context);
12698 ast_debug(3,
"*** Checking if we can expunge, deleted set to %d, expungeonhangup set to %d\n", deleted, expungeonhangup);
12699 if (vmu && deleted == 1 && expungeonhangup == 1 && vms.mailstream !=
NULL) {
12701#ifdef HAVE_IMAP_TK2006
12702 if (LEVELUIDPLUS (vms.mailstream)) {
12703 mail_expunge_full(vms.mailstream, NIL, EX_UID);
12706 mail_expunge(vms.mailstream);
12712 vmstate_delete(&vms);
12719 pthread_setspecific(ts_vmstate.key,
NULL);
12736 memset(&leave_options, 0,
sizeof(leave_options));
12741 if (
args.argc == 2) {
12767 res =
ast_app_getdata(chan,
"vm-whichbox", temp,
sizeof(temp) - 1, 0);
12815 ast_log(
LOG_ERROR,
"Voicemail data file %s/%d.txt has no [message] category?\n", dir, msg);
12836 ast_log(
LOG_WARNING,
"Mailbox %s in context %s begins with '*' character. The '*' character,"
12837 "\n\twhen it is the first character in a mailbox or password, is used to jump to a"
12838 "\n\tpredefined extension 'a'. A mailbox or password beginning with '*' is not valid"
12839 "\n\tand will be ignored.\n", box,
context);
12846 ast_log(
LOG_WARNING,
"\nIt has been detected that you have defined mailbox '%s' in separate\
12847 \n\tcontexts and that you have the 'searchcontexts' option on. This type of\
12848 \n\tconfiguration creates an ambiguity that you likely do not want. Please\
12849 \n\tamend your voicemail.conf file to avoid this situation.\n", box);
12879 int new = 0, old = 0, urgent = 0;
12890 if ((s =
strsep(&stringp,
","))) {
12893 "\n\tmust be reset in voicemail.conf.\n", box);
12898 if (stringp && (s =
strsep(&stringp,
","))) {
12901 if (stringp && (s =
strsep(&stringp,
","))) {
12904 if (stringp && (s =
strsep(&stringp,
","))) {
12924 imap_logout(mailbox_full);
12931#ifdef TEST_FRAMEWORK
12937 static const char options_string[] =
"attach=yes|attachfmt=wav49|"
12938 "serveremail=someguy@digium.com|fromstring=Voicemail System|tz=central|delete=yes|saycid=yes|"
12939 "sendvoicemail=yes|review=yes|tempgreetwarn=yes|messagewrap=yes|operator=yes|leaveurgent=yes|"
12940 "envelope=yes|moveheard=yes|sayduration=yes|saydurationm=5|forcename=yes|"
12941 "forcegreetings=yes|callback=somecontext|dialout=somecontext2|"
12942 "exitcontext=somecontext3|minsecs=10|maxsecs=100|nextaftercmd=yes|"
12943 "backupdeleted=50|volgain=1.3|passwordlocation=spooldir|emailbody="
12944 "Dear ${VM_NAME}:\n\n\tYou were just left a ${VM_DUR} long message|emailsubject="
12945 "[PBX]: New message \\\\${VM_MSGNUM}\\\\ in mailbox ${VM_MAILBOX}";
12947 static const char option_string2[] =
"imapuser=imapuser|imappassword=imappasswd|"
12948 "imapfolder=INBOX|imapvmshareid=6000|imapserver=imapserver|imapport=1234|imapflags=flagged";
12953 info->name =
"vmuser";
12954 info->category =
"/apps/app_voicemail/";
12955 info->summary =
"Vmuser unit test";
12956 info->description =
12957 "This tests passing all supported parameters to apply_options, the voicemail user config parser";
12975 if (strcasecmp(vmu->
attachfmt,
"wav49")) {
12979 if (strcasecmp(vmu->
fromstring,
"Voicemail System")) {
12983 if (strcasecmp(vmu->
serveremail,
"someguy@digium.com")) {
12987 if (!vmu->
emailsubject || strcasecmp(vmu->
emailsubject,
"[PBX]: New message \\${VM_MSGNUM}\\ in mailbox ${VM_MAILBOX}")) {
12991 if (!vmu->
emailbody || strcasecmp(vmu->
emailbody,
"Dear ${VM_NAME}:\n\n\tYou were just left a ${VM_DUR} long message")) {
12995 if (strcasecmp(vmu->
zonetag,
"central")) {
13055 if (strcasecmp(vmu->
callback,
"somecontext")) {
13059 if (strcasecmp(vmu->
dialout,
"somecontext2")) {
13063 if (strcasecmp(vmu->
exit,
"somecontext3")) {
13094 if (strcasecmp(vmu->imapuser,
"imapuser")) {
13098 if (strcasecmp(vmu->imappassword,
"imappasswd")) {
13102 if (strcasecmp(vmu->imapfolder,
"INBOX")) {
13106 if (strcasecmp(vmu->imapvmshareid,
"6000")) {
13110 if (strcasecmp(vmu->imapserver,
"imapserver")) {
13114 if (strcasecmp(vmu->imapport,
"1234")) {
13118 if (strcasecmp(vmu->imapflags,
"flagged")) {
13148 ast_log(
LOG_ERROR,
"VM_INFO requires an argument (<mailbox>[@<context>],attribute[,folder])\n");
13158 ast_log(
LOG_ERROR,
"VM_INFO requires an argument (<mailbox>[@<context>],attribute[,folder])\n");
13162 memset(&svm, 0,
sizeof(svm));
13165 if (!strncasecmp(arg.attribute,
"exists", 5)) {
13172 if (!strncasecmp(arg.attribute,
"password", 8)) {
13174 }
else if (!strncasecmp(arg.attribute,
"fullname", 8)) {
13176 }
else if (!strncasecmp(arg.attribute,
"email", 5)) {
13178 }
else if (!strncasecmp(arg.attribute,
"pager", 5)) {
13180 }
else if (!strncasecmp(arg.attribute,
"language", 8)) {
13182 }
else if (!strncasecmp(arg.attribute,
"locale", 6)) {
13184 }
else if (!strncasecmp(arg.attribute,
"tz", 2)) {
13186 }
else if (!strncasecmp(arg.attribute,
"count", 5)) {
13195 ast_log(
LOG_ERROR,
"Unable to retrieve message count for mailbox %s\n", arg.mailbox_context);
13199 snprintf(
buf,
len,
"%d", res);
13201 ast_log(
LOG_ERROR,
"Unknown attribute '%s' for VM_INFO\n", arg.attribute);
13221 int silent = 0, skipuser = 0;
13247 }
else if (
mailbox[0] ==
'*') {
13260 const char *cat =
NULL;
13269 "=============================================================\n"
13270 "=== Configured Voicemail Users ==============================\n"
13271 "=============================================================\n"
13277 "=== Mailbox ...\n"
13283 "=== ---------------------------------------------------------\n"
13288 "=============================================================\n"
13307 wordlen = strlen(
word);
13328#define HVSU_OUTPUT_FORMAT "%-10s %-5s %-25s %-10s %6s\n"
13330 int users_counter = 0;
13334 e->
command =
"voicemail show users [for]";
13336 "Usage: voicemail show users [for <context>]\n"
13337 " Lists all mailboxes currently set up\n";
13343 if ((
a->argc < 3) || (
a->argc > 5) || (
a->argc == 4))
13345 if (
a->argc == 5) {
13346 if (strcmp(
a->argv[3],
"for"))
13353 ast_cli(
a->fd,
"You must specify a specific context to show users from realtime!\n");
13361 ast_cli(
a->fd,
"There are no voicemail users currently defined\n");
13384 int newmsgs = 0, oldmsgs = 0;
13385 char count[12],
tmp[256] =
"";
13390 snprintf(count,
sizeof(count),
"%d", newmsgs);
13396 ast_cli(
a->fd,
"%d voicemail users configured.\n", users_counter);
13404#define HVSZ_OUTPUT_FORMAT "%-15s %-20s %-45s\n"
13409 e->
command =
"voicemail show zones";
13411 "Usage: voicemail show zones\n"
13412 " Lists zone message formats\n";
13428 ast_cli(
a->fd,
"There are no voicemail zones currently defined\n");
13441#define ALIASES_OUTPUT_FORMAT "%-32s %-32s\n"
13446 e->
command =
"voicemail show aliases";
13448 "Usage: voicemail show aliases\n"
13449 " Lists mailbox aliases\n";
13459 ast_cli(
a->fd,
"Aliases are not enabled\n");
13481 e->
command =
"voicemail reload";
13483 "Usage: voicemail reload\n"
13484 " Reload voicemail configuration\n";
13493 ast_cli(
a->fd,
"Reloading voicemail configuration...\n");
13512 int new = 0, old = 0, urgent = 0;
13522 if (imap_poll_logout) {
13538 struct timespec ts = { 0, };
13539 struct timeval wait;
13548 ts.tv_sec = wait.tv_sec;
13549 ts.tv_nsec = wait.tv_usec * 1000;
13560static void imap_logout(
const char *mailbox_id)
13573 memset(&vmus, 0,
sizeof(vmus));
13579 vms = get_vm_state_by_imapuser(vmu->imapuser, 0);
13588 vms->mailstream = mail_close(vms->mailstream);
13591 vmstate_delete(vms);
13594static int imap_close_subscribed_mailbox(
struct ast_mwi_state *mwi_state,
void *data)
13617 imap_close_subscribed_mailbox(mwi_state,
NULL);
13691 const char* event_name,
13692 const char* actionid
13700 if((s ==
NULL) || (vmu ==
NULL) || (event_name ==
NULL) || (actionid ==
NULL)) {
13720 ast_log(
LOG_ERROR,
"Could not get mailbox count. user[%s], context[%s]\n",
13728 "VMContext: %s\r\n"
13729 "VoiceMailbox: %s\r\n"
13733 "ServerEmail: %s\r\n"
13734 "FromString: %s\r\n"
13735 "MailCommand: %s\r\n"
13741 "ExitContext: %s\r\n"
13742 "SayDurationMinimum: %d\r\n"
13743 "SayEnvelope: %s\r\n"
13745 "AttachMessage: %s\r\n"
13746 "AttachmentFormat: %s\r\n"
13747 "DeleteMessage: %s\r\n"
13748 "VolumeGain: %.2f\r\n"
13749 "CanReview: %s\r\n"
13750 "CanMarkUrgent: %s\r\n"
13751 "CallOperator: %s\r\n"
13752 "MaxMessageCount: %d\r\n"
13753 "MaxMessageLength: %d\r\n"
13754 "NewMessageCount: %d\r\n"
13755 "OldMessageCount: %d\r\n"
13758 "IMAPServer: %s\r\n"
13760 "IMAPFlags: %s\r\n"
13816 const char* event_name,
13817 const char* actionid)
13821 int nummessages = 0;
13826 if (!mailbox_snapshot) {
13834 for (i = 0; i < mailbox_snapshot->
folders; i++) {
13879 (at = strchr(mwi_state->
uniqueid,
'@')) &&
13883 (at = strchr(mwi_state->
uniqueid,
'@')) &&
13884 strcmp(
context, at + 1) == 0) ||
13887 (at = strchr(mwi_state->
uniqueid,
'@')) &&
13889 strcmp(
context, at + 1) == 0)
13909 char actionid[128];
13921 actionid[0] =
'\0';
13923 snprintf(actionid,
sizeof(actionid),
"ActionID: %s\r\n",
id);
13927 memset(&svm, 0,
sizeof(svm));
13931 astman_send_ack(s, m,
"There is no voicemail user of the given info.");
13955 char actionid[128];
13959 actionid[0] =
'\0';
13961 snprintf(actionid,
sizeof(actionid),
"ActionID: %s\r\n",
id);
13967 astman_send_ack(s, m,
"There are no voicemail users currently defined.");
13996 char actionid[128];
14007 actionid[0] =
'\0';
14009 snprintf(actionid,
sizeof(actionid),
"ActionID: %s\r\n",
id);
14013 memset(&svm, 0,
sizeof(svm));
14017 astman_send_ack(s, m,
"There is no voicemail user matching the given user.");
14197 if (!
str->used ||
str->str[
str->used - 1] !=
'\r') {
14231 ast_log(
LOG_ERROR,
"Config file users.conf is in an invalid format. Avoiding.\n");
14246 ast_log(
LOG_ERROR,
"Config file users.conf is in an invalid format. Avoiding.\n");
14264#ifdef TEST_FRAMEWORK
14276 size_t from_len = strlen(
alias) + 1;
14277 size_t to_len = strlen(
mailbox) + 1;
14279 mapping =
ao2_alloc(
sizeof(*mapping) + from_len + to_len,
NULL);
14319 char storage[strlen(
var->value) + 1];
14326 strcpy(storage,
var->value);
14351 if (strcasecmp(cat,
"general") == 0
14353 || strcasecmp(cat,
"zonemessages") == 0) {
14370 char *q, *stringp, *
tmp;
14372 unsigned int tmpadsi[4];
14374 long tps_queue_low;
14375 long tps_queue_high;
14431 strcpy(odbc_database,
"asterisk");
14435 strcpy(odbc_table,
"voicemessages");
14468 if (sscanf(
val,
"%30d", &x) == 1)
14537 expungeonhangup = 0;
14539 expungeonhangup = 1;
14541 expungeonhangup = 1;
14568 imap_poll_logout = 0;
14576 mail_parameters(NIL, SET_READTIMEOUT, (
void *) (atol(
val)));
14578 mail_parameters(NIL, SET_READTIMEOUT, (
void *) 60L);
14582 mail_parameters(NIL, SET_WRITETIMEOUT, (
void *) (atol(
val)));
14584 mail_parameters(NIL, SET_WRITETIMEOUT, (
void *) 60L);
14588 mail_parameters(NIL, SET_OPENTIMEOUT, (
void *) (atol(
val)));
14590 mail_parameters(NIL, SET_OPENTIMEOUT, (
void *) 60L);
14594 mail_parameters(NIL, SET_CLOSETIMEOUT, (
void *) (atol(
val)));
14596 mail_parameters(NIL, SET_CLOSETIMEOUT, (
void *) 60L);
14612 ast_debug(1,
"Enabled SMDI voicemail notification\n");
14616 ast_debug(1,
"No SMDI interface set, trying default (/dev/ttyS0)\n");
14620 ast_log(
AST_LOG_ERROR,
"No valid SMDI interface specfied, disabling SMDI voicemail notification\n");
14635 if (sscanf(
val,
"%30d", &x) == 1) {
14641 static int maxmessage_deprecate = 0;
14642 if (maxmessage_deprecate == 0) {
14643 maxmessage_deprecate = 1;
14646 if (sscanf(
val,
"%30d", &x) == 1) {
14655 if (sscanf(
val,
"%30d", &x) == 1) {
14664 static int maxmessage_deprecate = 0;
14665 if (maxmessage_deprecate == 0) {
14666 maxmessage_deprecate = 1;
14669 if (sscanf(
val,
"%30d", &x) == 1) {
14686 ast_log(
LOG_ERROR,
"Error processing format string, defaulting to format 'wav'\n");
14694 if (sscanf(
val,
"%30d", &x) == 1) {
14702 if (sscanf(
val,
"%30d", &x) == 1) {
14711 if (sscanf(
val,
"%30d", &x) == 1) {
14720 if (sscanf(
val,
"%30d", &x) == 1) {
14738 ast_debug(1,
"VM_CID Internal context string: %s\n",
val);
14742 q =
strsep(&stringp,
",");
14743 while ((*q ==
' ')||(*q ==
'\t'))
14753 ast_debug(1,
"VM Review Option disabled globally\n");
14761 ast_debug(1,
"VM leave urgent messages disabled globally\n");
14768 ast_debug(1,
"VM Temporary Greeting Reminder Option disabled globally\n");
14771 ast_debug(1,
"VM Temporary Greeting Reminder Option enabled globally\n");
14775 ast_debug(1,
"VM next message wrap disabled globally\n");
14781 ast_debug(1,
"VM Operator break disabled globally\n");
14787 ast_debug(1,
"VM CID Info before msg disabled globally\n");
14793 ast_debug(1,
"Send Voicemail msg disabled globally\n");
14799 ast_debug(1,
"ENVELOPE before msg enabled globally\n");
14805 ast_debug(1,
"Move Heard enabled globally\n");
14811 ast_debug(1,
"Autoset of Urgent flag on forwarded Urgent messages disabled globally\n");
14817 ast_debug(1,
"Duration info before msg enabled globally\n");
14824 if (sscanf(
val,
"%30d", &x) == 1) {
14832 ast_debug(1,
"We are not going to skip to the next msg after save/delete\n");
14898 val =
"voicemail.conf";
14900 if (!(strcmp(
val,
"spooldir"))) {
14920 strcpy(
charset,
"ISO-8859-1");
14946 sscanf(
val,
"%2x%2x%2x%2x", &tmpadsi[0], &tmpadsi[1], &tmpadsi[2], &tmpadsi[3]);
14947 for (x = 0; x < 4; x++) {
14948 memcpy(&
adsifdn[x], &tmpadsi[x], 1);
14952 sscanf(
val,
"%2x%2x%2x%2x", &tmpadsi[0], &tmpadsi[1], &tmpadsi[2], &tmpadsi[3]);
14953 for (x = 0; x < 4; x++) {
14954 memcpy(&
adsisec[x], &tmpadsi[x], 1);
14983 if (sscanf(
val,
"%30ld", &tps_queue_high) != 1 || tps_queue_high <= 0) {
14988 tps_queue_low = -1;
14990 if (sscanf(
val,
"%30ld", &tps_queue_low) != 1 ||
14991 tps_queue_low < -1 || tps_queue_high < tps_queue_low) {
14993 tps_queue_low = -1;
15003 if (!strcasecmp(cat,
"general")) {
15016 switch (
current->passwordlocation) {
15057 ast_debug(2,
"About to try retrieving name file %s\n", dir);
15103 ast_log(
LOG_NOTICE,
"Failed reading voicemail password from %s, using secret from config file\n", secretfn);
15162#ifdef TEST_FRAMEWORK
15177 static const char TEST_CONTEXT[] =
"very_long_unique_context_so_that_nobody_will_ever_have_the_same_one_configured_3141592653";
15185 .
write = fake_write,
15191 info->name =
"vmsayname_exec";
15192 info->category =
"/apps/app_voicemail/";
15193 info->summary =
"Vmsayname unit test";
15194 info->description =
15195 "This tests passing various parameters to vmsayname";
15202 NULL,
NULL, 0, 0,
"TestChannel1"))) {
15203 goto exit_vmsayname_test;
15209 goto exit_vmsayname_test;
15229 goto exit_vmsayname_test;
15234 goto exit_vmsayname_test;
15239 if ((res = symlink(dir, dir2))) {
15241 goto exit_vmsayname_test;
15256exit_vmsayname_test:
15279 struct test_files *
tmp =
ast_alloca(
sizeof(
struct test_files) * 3);
15281 const char origweasels[] =
"tt-weasels";
15282 const char testcontext[] =
"test";
15283 const char testmailbox[] =
"00000000";
15284 const char testspec[] =
"00000000@test";
15286 int new, old, urgent;
15287 const char *folders[3] = {
"Old",
"Urgent",
"INBOX" };
15288 const int folder2mbox[3] = { 1, 11, 0 };
15289 const int expected_results[3][12] = {
15291 { 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0 },
15292 { 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1 },
15293 { 1, 1, 1, 1, 0, 2, 1, 1, 1, 1, 1, 2 },
15298 info->name =
"test_voicemail_msgcount";
15299 info->category =
"/apps/app_voicemail/";
15300 info->summary =
"Test Voicemail status checks";
15301 info->description =
15302 "Verify that message counts are correct when retrieved through the public API";
15309 snprintf(syscmd,
sizeof(syscmd),
"rm -rf \"%s%s/%s\"",
VM_SPOOL_DIR, testcontext, testmailbox);
15312 syserr > 0 ? strerror(syserr) :
"unable to fork()");
15323 memset(&svm, 0,
sizeof(svm));
15324 if (!(vmu =
find_user(&svm, testcontext, testmailbox)) &&
15335 memset(&vms, 0,
sizeof(vms));
15338 for (i = 0; i < 3; i++) {
15341 snprintf(
tmp[i].txtfile,
sizeof(
tmp[i].txtfile),
"%s.txt",
tmp[i].
file);
15344 snprintf(syscmd,
sizeof(syscmd),
"cp \"%s/sounds/en/%s.gsm\" \"%s/%s/%s/%s/msg0000.gsm\"",
ast_config_AST_DATA_DIR, origweasels,
15348 syserr > 0 ? strerror(syserr) :
"unable to fork()");
15358 if ((txt = fopen(
tmp[i].txtfile,
"w+"))) {
15359 fprintf(txt,
"; just a stub\n[message]\nflag=%s\n", strcmp(folders[i],
"Urgent") ?
"" :
"Urgent");
15367 STORE(
tmp[i].dir, testmailbox, testcontext, 0, chan, vmu,
"gsm", 600, &vms, strcmp(folders[i],
"Urgent") ?
"" :
"Urgent",
NULL);
15370 for (j = 0; j < 3; j++) {
15379 new = old = urgent = 0;
15383 }
else if (old != expected_results[i][3 + 0] ||
new != expected_results[i][3 + 2]) {
15385 testspec, old, expected_results[i][3 + 0],
new, expected_results[i][3 + 2]);
15389 new = old = urgent = 0;
15393 }
else if (old != expected_results[i][6 + 0] ||
15394 urgent != expected_results[i][6 + 1] ||
15395 new != expected_results[i][6 + 2] ) {
15396 ast_test_status_update(
test,
"inboxcount2(%s) returned old=%d (expected %d), urgent=%d (expected %d), and new=%d (expected %d)\n",
15397 testspec, old, expected_results[i][6 + 0], urgent, expected_results[i][6 + 1],
new, expected_results[i][6 + 2]);
15401 new = old = urgent = 0;
15402 for (j = 0; j < 3; j++) {
15405 testspec, folders[j],
ast_app_messagecount(testspec, folders[j]), expected_results[i][9 + j]);
15411 for (i = 0; i < 3; i++) {
15431 snprintf(syscmd,
sizeof(syscmd),
"rm -rf \"%s%s/%s\"",
VM_SPOOL_DIR, testcontext, testmailbox);
15434 syserr > 0 ? strerror(syserr) :
"unable to fork()");
15445 char testcontext[] =
"test";
15446 char testmailbox[] =
"00000000";
15447 char from[] =
"test@example.net", cidnum[] =
"1234", cidname[] =
"Mark Spencer", format[] =
"gsm";
15448 char attach[256], attach2[256];
15449 char buf[256] =
"";
15457 enum { INT, FLAGVAL, STATIC, STRPTR }
type;
15464 {
"plain jane config", STATIC, vmus.
password, .u.strval =
"1234" },
15465 {
"emailsubject", STRPTR, vmus.
emailsubject, .u.strval =
"Oogly boogly\xf8koogly with what appears to be UTF-8" },
15466 {
"emailbody", STRPTR, vmus.
emailbody, .u.strval =
"This is a test\n\twith multiple\nlines\nwithin\n" },
15467 {
"serveremail", STATIC, vmus.
serveremail, .u.strval =
"\"\xf8Something\xe8that\xd8seems to have UTF-8 chars\" <test@example.net>" },
15468 {
"attachment flag", FLAGVAL, &vmus.
flags, .u.intval =
VM_ATTACH },
15469 {
"attach2", STRPTR, attach2, .u.strval =
"" },
15470 {
"attach", STRPTR, attach, .u.strval =
"" },
15476 info->name =
"test_voicemail_notify_endl";
15477 info->category =
"/apps/app_voicemail/";
15478 info->summary =
"Test Voicemail notification end-of-line";
15479 info->description =
15480 "Verify that notification emails use a consistent end-of-line character";
15489 if (!(vmu =
find_user(&vmus, testcontext, testmailbox)) &&
15495 if (vmu != &vmus && !(vmu =
find_user(&vmus, testcontext, testmailbox))) {
15507 for (which = 0; which <
ARRAY_LEN(test_items); which++) {
15510 if (ftruncate(fileno(
file), 0)) {
15517 if (test_items[which].
type == INT) {
15518 *((
int *) test_items[which].location) = test_items[which].u.intval;
15519 }
else if (test_items[which].
type == FLAGVAL) {
15525 }
else if (test_items[which].
type == STATIC) {
15526 strcpy(test_items[which].location, test_items[which].u.strval);
15527 }
else if (test_items[which].
type == STRPTR) {
15528 test_items[which].location = test_items[which].u.strval;
15531 make_email_file(
file, from, vmu, 0, testcontext, testmailbox,
"INBOX", cidnum, cidname, attach, attach2, format, 999, 1, chan,
NULL, 0,
NULL,
NULL);
15535 (strlen(
buf) > 1 &&
15537 buf[strlen(
buf) - 2] !=
'\r'
15539 buf[strlen(
buf) - 2] ==
'\r'
15542 ||
buf[strlen(
buf) - 1] !=
'\n') {
15565 info->name =
"test_voicemail_load_config";
15566 info->category =
"/apps/app_voicemail/";
15567 info->summary =
"Test loading Voicemail config";
15568 info->description =
15569 "Verify that configuration is loaded consistently. "
15570 "This is to test regressions of ASTERISK-18838 where it was noticed that "
15571 "some options were loaded after the mailboxes were instantiated, causing "
15572 "those options not to be set correctly.";
15582 if (!(
file = fdopen(fd,
"w"))) {
15587 fputs(
"[general]\ncallback=somecontext\nlocale=de_DE.UTF-8\ntz=european\n[test]",
file);
15588 fputs(
"00000001 => 9999,Mr. Test,,,callback=othercontext|locale=nl_NL.UTF-8|tz=central\n",
file);
15589 fputs(
"00000002 => 9999,Mrs. Test\n",
file);
15597 load_config_from_memory(1, cfg,
NULL);
15600#define CHECK(u, attr, value) else if (strcmp(u->attr, value)) { \
15601 ast_test_status_update(test, "mailbox %s should have %s '%s', but has '%s'\n", \
15602 u->mailbox, #attr, value, u->attr); res = AST_TEST_FAIL; break; }
15606 if (!strcmp(vmu->
mailbox,
"00000001")) {
15608 CHECK(vmu, callback,
"othercontext")
15609 CHECK(vmu,
locale, "nl_NL.UTF-8")
15610 CHECK(vmu,
zonetag, "central")
15611 } else
if (!strcmp(vmu->
mailbox, "00000002")) {
15613 CHECK(vmu, callback,
"somecontext")
15614 CHECK(vmu,
locale, "de_DE.UTF-8")
15615 CHECK(vmu,
zonetag, "european")
15634 const char testcontext[] =
"test";
15635 const char testmailbox[] =
"00000000";
15636 const char vminfo_cmd[] =
"VM_INFO";
15637 char vminfo_buf[256], vminfo_args[256];
15640 int test_counter = 0;
15643 char *vminfo_test_args;
15644 char *vminfo_expected;
15648 {
"00000000@test,badparam",
"", -1 },
15649 {
"00000000@test",
"", -1 },
15650 {
"00000000@test,exists",
"1", 0 },
15651 {
"11111111@test,exists",
"0", 0 },
15652 {
"00000000@test,email",
"vm-info-test@example.net", 0 },
15653 {
"11111111@test,email",
"", 0 },
15654 {
"00000000@test,fullname",
"Test Framework Mailbox", 0 },
15655 {
"00000000@test,pager",
"vm-info-pager-test@example.net", 0 },
15656 {
"00000000@test,locale",
"en_US", 0 },
15657 {
"00000000@test,tz",
"central", 0 },
15658 {
"00000000@test,language",
"en", 0 },
15659 {
"00000000@test,password",
"9876", 0 },
15664 info->name =
"test_voicemail_vm_info";
15665 info->category =
"/apps/app_voicemail/";
15666 info->summary =
"VM_INFO unit test";
15667 info->description =
15668 "This tests passing various parameters to VM_INFO";
15701 for (test_counter = 0; test_counter <
ARRAY_LEN(test_items); test_counter++) {
15702 ast_copy_string(vminfo_args, test_items[test_counter].vminfo_test_args,
sizeof(vminfo_args));
15703 test_ret =
acf_vm_info(chan, vminfo_cmd, vminfo_args, vminfo_buf,
sizeof(vminfo_buf));
15704 if (strcmp(vminfo_buf, test_items[test_counter].vminfo_expected)) {
15705 ast_test_status_update(
test,
"VM_INFO respose was: '%s', but expected: '%s'\n", vminfo_buf, test_items[test_counter].vminfo_expected);
15708 if (!(test_ret == test_items[test_counter].vminfo_ret)) {
15709 ast_test_status_update(
test,
"VM_INFO return code was: '%i', but expected '%i'\n", test_ret, test_items[test_counter].vminfo_ret);
15767#ifdef TEST_FRAMEWORK
15778#ifdef TEST_FRAMEWORK
15779 ast_uninstall_vm_test_functions();
15810 prnt(where,
"Alias: %s Mailbox: %s", mapping->
alias, mapping->
mailbox);
15840 alias_mailbox_mapping_hash_fn,
NULL, alias_mailbox_mapping_cmp_fn);
15842 ast_log(
LOG_ERROR,
"Unable to create alias_mailbox_mappings container\n");
15848 ast_log(
LOG_ERROR,
"Unable to register alias_mailbox_mappings container\n");
15855 mailbox_alias_mapping_hash_fn,
NULL, mailbox_alias_mapping_cmp_fn);
15857 ast_log(
LOG_ERROR,
"Unable to create mailbox_alias_mappings container\n");
15865 ast_log(
LOG_ERROR,
"Unable to register mailbox_alias_mappings container\n");
15898#ifdef TEST_FRAMEWORK
15908 ast_log(
LOG_ERROR,
"Failure registering applications, functions or tests\n");
15931#ifdef TEST_FRAMEWORK
15932 ast_install_vm_test_functions(vm_test_create_user, vm_test_destroy_user);
15944 char destination[80] =
"";
15948 ast_verb(3,
"Destination number will be entered manually\n");
15949 while (retries < 3 && cmd !=
't') {
15950 destination[1] =
'\0';
15959 destination[0] = cmd;
15968 ast_verb(3,
"User hit '*' to cancel outgoing call\n");
15971 if ((cmd =
ast_readstring(chan, destination + strlen(destination),
sizeof(destination) - 1, 6000, 10000,
"#")) < 0)
15977 isprint(cmd) ? cmd :
'?', isprint(cmd) ? cmd :
'?');
15979 if (retries >= 3) {
15984 ast_verb(3,
"Destination number is CID number '%s'\n", num);
15989 if (destination[strlen(destination) -1 ] ==
'*')
15991 ast_verb(3,
"Placing outgoing call to extension '%s' in context '%s' from context '%s'\n", destination, outgoing_context,
ast_channel_context(chan));
16018 const char *origtime, *
context;
16029 snprintf(filename,
sizeof(filename),
"%s.txt", vms->
fn);
16064 while ((res > -1) && (res !=
't')) {
16088 ast_verb(3,
"Caller can not specify callback number - no dialout context available\n");
16110 ast_verb(3,
"Confirm CID number '%s' is number to use for callback\n", num);
16141 isprint(res) ? res :
'?', isprint(res) ? res :
'?');
16147 else if (res ==
'*')
16159 ast_verb(3,
"No CID number available, no reply sent\n");
16166 memset(&vmu2, 0,
sizeof(vmu2));
16173 ast_verb(3,
"Leaving voicemail for '%s' in context '%s'\n", num, vmu->
context);
16175 memset(&leave_options, 0,
sizeof(leave_options));
16186 ast_verb(3,
"No mailbox number '%s' in context '%s', no reply sent\n", num, vmu->
context);
16200#ifndef IMAP_STORAGE
16203 vms->
heard[msg] = 1;
16211 int outsidecaller,
struct ast_vm_user *vmu,
int *duration,
int *sound_duration,
const char *unlockdir,
16217 int max_attempts = 3;
16220 int msg_exists = 0;
16221 signed char zero_gain = 0;
16223 char *acceptdtmf =
"#";
16224 char *canceldtmf =
"";
16225 int canceleddtmf = 0;
16230 if (duration ==
NULL) {
16235 if (!outsidecaller)
16236 snprintf(tempfile,
sizeof(tempfile),
"%s.tmp", recordfile);
16242 while ((cmd >= 0) && (cmd !=
't')) {
16251 ast_verb(3,
"Saving message as is\n");
16252 if (!outsidecaller)
16254 if (!forwardintro) {
16257 if (!outsidecaller) {
16259 STORE(recordfile, vmu->
mailbox, vmu->
context, -1, chan, vmu, fmt, *duration, vms,
flag, msg_id);
16267 ast_verb(3,
"Reviewing the message\n");
16274 ast_verb(3,
"Re-recording the message\n");
16276 ast_verb(3,
"Recording the message\n");
16278 if (recorded && outsidecaller) {
16279 if (forwardintro) {
16288 ast_debug(1,
"User hung up before message could be rerecorded\n");
16298 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);
16299 if (strchr(canceldtmf, cmd)) {
16307 if (!outsidecaller) {
16315 }
else if (cmd ==
'*') {
16318 }
else if (vmu->review && sound_duration && (*sound_duration < 5)) {
16320 ast_verb(3,
"Message too short\n");
16324 }
else if (vmu->review && (cmd == 2 && sound_duration && *sound_duration < (
maxsilence + 3))) {
16326 ast_verb(3,
"Nothing recorded\n");
16343 ast_verb(3,
"marking message as Urgent\n");
16345 strcpy(
flag,
"Urgent");
16347 ast_verb(3,
"UNmarking message as Urgent\n");
16374 if (outsidecaller) {
16386 if (msg_exists || recorded) {
16394 }
else if (cmd ==
'4') {
16397 strcpy(
flag,
"Urgent");
16403 DELETE(tempfile, -1, tempfile, vmu);
16444 if (attempts > max_attempts) {
16449 if (!outsidecaller && (cmd == -1 || cmd ==
't')) {
16454 if (cmd !=
't' && outsidecaller)
16464 if (!(msg_snapshot =
ast_calloc(1,
sizeof(*msg_snapshot)))) {
16473 return msg_snapshot;
16484#ifdef TEST_FRAMEWORK
16486static int vm_test_destroy_user(
const char *
context,
const char *
mailbox)
16504static int vm_test_create_user(
const char *
context,
const char *
mailbox)
16531 int snapshot_index,
16547 snprintf(filename,
sizeof(filename),
"%s.txt", vms->
fn);
16571 filename,
id,
sizeof(
id), vmu, mailbox_index))) {
16602 switch (sort_val) {
16615 if (descending &&
val >= 0) {
16619 }
else if (!descending &&
val <= 0) {
16645 const char *folder,
16648 int combine_INBOX_and_OLD)
16655 int this_index_only = -1;
16662 ast_log(
LOG_WARNING,
"Cannot create a mailbox snapshot since no mailbox was specified\n");
16666 memset(&vmus, 0,
sizeof(vmus));
16672 this_index_only = i;
16676 if (this_index_only == -1) {
16687 if (!(mailbox_snapshot =
ast_calloc(1,
sizeof(*mailbox_snapshot)))) {
16701 for (i = 0; i < mailbox_snapshot->
folders; i++) {
16702 int msg_folder_index = i;
16709 if (!(this_index_only == -1 || this_index_only == i || (this_index_only == inbox_index && combine_INBOX_and_OLD && (i == old_index || i == urgent_index)))) {
16714 if (combine_INBOX_and_OLD && (i == old_index || i == urgent_index)) {
16715 msg_folder_index = inbox_index;
16718 memset(&vms, 0,
sizeof(vms));
16726 goto snapshot_cleanup;
16734 goto snapshot_cleanup;
16740 goto snapshot_cleanup;
16752 vmstate_delete(&vms);
16757 return mailbox_snapshot;
16765 for (i = 0; i < mailbox_snapshot->
folders; i++) {
16798 for (i = 0; i < num_msgs; ++i) {
16799 const char *
msg_id = msg_ids[i];
16802 const char *other_msg_id;
16808 snprintf(filename,
sizeof(filename),
"%s.txt", vms->
fn);
16819 if (!
ast_strlen_zero(other_msg_id) && !strcmp(other_msg_id, msg_id)) {
16824 msg_nums[i] = vms->
curmsg;
16845 int new = 0, old = 0, urgent = 0;
16846 char ext_context[1024];
16848 snprintf(ext_context,
sizeof(ext_context),
"%s@%s", vmu->
mailbox, vmu->
context);
16855 const char *from_context,
16856 const char *from_folder,
16857 const char *to_mailbox,
16858 const char *to_context,
16859 const char *to_folder,
16861 const char *msg_ids [],
16870 int from_folder_index;
16877 ast_log(
LOG_WARNING,
"Cannot forward message because either the from or to mailbox was not specified\n");
16882 ast_log(
LOG_WARNING,
"Invalid number of messages specified to forward: %zu\n", num_msgs);
16887 ast_log(
LOG_WARNING,
"Cannot forward message because the from_folder or to_folder was not specified\n");
16891 memset(&vmus, 0,
sizeof(vmus));
16892 memset(&to_vmus, 0,
sizeof(to_vmus));
16893 memset(&from_vms, 0,
sizeof(from_vms));
16896 if (from_folder_index == -1) {
16909 if (!(to_vmu =
find_user(&to_vmus, to_context, to_mailbox))) {
16910 ast_log(
LOG_WARNING,
"Can't find voicemail user to forward to (%s@%s)\n", to_mailbox, to_context);
16920 if ((res =
open_mailbox(&from_vms, vmu, from_folder_index)) < 0) {
16923 goto vm_forward_cleanup;
16928 if ((from_vms.
lastmsg + 1) < num_msgs) {
16929 ast_log(
LOG_WARNING,
"Folder %s has less than %zu messages\n", from_folder, num_msgs);
16931 goto vm_forward_cleanup;
16934 msg_nums =
ast_alloca(
sizeof(
int) * num_msgs);
16937 goto vm_forward_cleanup;
16941 for (i = 0; i < num_msgs; i++) {
16942 int cur_msg = msg_nums[i];
16947 snprintf(filename,
sizeof(filename),
"%s.txt", from_vms.
fn);
16959 duration = atoi(
value);
16965 from_vms.
deleted[cur_msg] = 1;
16974 goto vm_forward_cleanup;
16984 vmstate_delete(&from_vms);
17000 const char *oldfolder,
17001 const char *old_msg_ids [],
17002 const char *newfolder)
17006 int old_folder_index;
17007 int new_folder_index;
17019 ast_log(
LOG_WARNING,
"Invalid number of messages specified to move: %zu\n", num_msgs);
17024 ast_log(
LOG_WARNING,
"Cannot move message because either oldfolder or newfolder was not specified\n");
17031 memset(&vmus, 0,
sizeof(vmus));
17032 memset(&vms, 0,
sizeof(vms));
17034 if (old_folder_index == -1 || new_folder_index == -1) {
17047 if ((res =
open_mailbox(&vms, vmu, old_folder_index)) < 0) {
17050 goto vm_move_cleanup;
17055 if ((vms.
lastmsg + 1) < num_msgs) {
17056 ast_log(
LOG_WARNING,
"Folder %s has less than %zu messages\n", oldfolder, num_msgs);
17058 goto vm_move_cleanup;
17061 old_msg_nums =
ast_alloca(
sizeof(
int) * num_msgs);
17064 goto vm_move_cleanup;
17068 for (i = 0; i < num_msgs; ++i) {
17071 goto vm_move_cleanup;
17073 vms.
deleted[old_msg_nums[i]] = 1;
17079 goto vm_move_cleanup;
17089 vmstate_delete(&vms);
17104 const char *folder,
17105 const char *msgs[])
17121 ast_log(
LOG_WARNING,
"Invalid number of messages specified to remove: %zu\n", num_msgs);
17130 memset(&vmus, 0,
sizeof(vmus));
17131 memset(&vms, 0,
sizeof(vms));
17134 if (folder_index == -1) {
17149 if ((res =
open_mailbox(&vms, vmu, folder_index)) < 0) {
17152 goto vm_remove_cleanup;
17157 if ((vms.
lastmsg + 1) < num_msgs) {
17160 goto vm_remove_cleanup;
17163 msg_nums =
ast_alloca(
sizeof(
int) * num_msgs);
17166 goto vm_remove_cleanup;
17169 for (i = 0; i < num_msgs; i++) {
17170 vms.
deleted[msg_nums[i]] = 1;
17177 goto vm_remove_cleanup;
17187 vmstate_delete(&vms);
17202 const char *folder,
17203 const char *msg_id,
17228 ast_log(
LOG_WARNING,
"Cannot play message because no message number was specified\n");
17232 memset(&vmus, 0,
sizeof(vmus));
17233 memset(&vms, 0,
sizeof(vms));
17248 goto play2_msg_cleanup;
17254 goto play2_msg_cleanup;
17259 snprintf(filename,
sizeof(filename),
"%s.txt", vms.
fn);
17266 goto play2_msg_cleanup;
17269 duration = atoi(
value);
17282 cb(chan, vms.
fn, duration);
17283 }
else if ((
wait_file(chan, &vms, vms.
fn)) < 0) {
17301 vmstate_delete(&vms);
17322 .optional_modules =
"res_adsi,res_smdi",
ADSI Support (built upon Caller*ID)
int ast_adsi_display(unsigned char *buf, int page, int line, int just, int wrap, char *col1, char *col2)
Loads a line of info into the display.
int ast_adsi_load_soft_key(unsigned char *buf, int key, const char *llabel, const char *slabel, char *ret, int data)
Creates "load soft key" parameters.
#define ADSI_MSG_DOWNLOAD
int ast_adsi_data_mode(unsigned char *buf)
Puts CPE in data mode.
int ast_adsi_unload_session(struct ast_channel *chan)
int ast_adsi_begin_download(struct ast_channel *chan, char *service, unsigned char *fdn, unsigned char *sec, int version)
int ast_adsi_set_line(unsigned char *buf, int page, int line)
Sets the current line and page.
int ast_adsi_input_control(unsigned char *buf, int page, int line, int display, int format, int just)
Set input information.
int ast_adsi_input_format(unsigned char *buf, int num, int dir, int wrap, char *format1, char *format2)
Set input format.
int ast_adsi_load_session(struct ast_channel *chan, unsigned char *app, int ver, int data)
Check if scripts for a given app are already loaded. Version may be -1, if any version is okay,...
int ast_adsi_end_download(struct ast_channel *chan)
int ast_adsi_download_disconnect(unsigned char *buf)
Disconnects (and hopefully saves) a downloaded script.
int ast_adsi_available(struct ast_channel *chan)
Returns non-zero if Channel does or might support ADSI.
int ast_adsi_transmit_message(struct ast_channel *chan, unsigned char *msg, int msglen, int msgtype)
#define ADSI_DIR_FROM_LEFT
int ast_adsi_set_keys(unsigned char *buf, unsigned char *keys)
Set which soft keys should be displayed.
int ast_adsi_voice_mode(unsigned char *buf, int when)
Puts CPE in voice mode.
struct sla_ringing_trunk * last
#define VMBOX_STRING_DATA_FORMAT
static char * vm_check_password_shell(char *command, char *buf, size_t len)
static int vm_browse_messages_vi(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
Vietnamese syntax for 'You have N messages' greeting.
static int save_to_folder(struct ast_vm_user *vmu, struct vm_state *vms, int msg, int box, int *newmsg, int move)
static char pagerfromstring[100]
static char vm_password[80]
static char vm_invalid_password[80]
static char * handle_voicemail_show_users(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Show a list of voicemail users in the CLI.
static int vm_browse_messages_en(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
Default English syntax for 'You have N messages' greeting.
static char listen_control_reverse_key[12]
#define MAX_VM_CONTEXT_LEN
#define EXISTS(a, b, c, d)
static int vm_intro_pl(struct ast_channel *chan, struct vm_state *vms)
static void adsi_password(struct ast_channel *chan)
static char serveremail[80]
static int get_folder(struct ast_channel *chan, int start)
get_folder: Folder menu Plays "press 1 for INBOX messages" etc. Should possibly be internationalized
#define VMSTATE_MAX_MSG_ARRAY
static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_options *options)
Prompts the user and records a voicemail to a mailbox.
static void adsi_folders(struct ast_channel *chan, int start, char *label)
static int close_mailbox(struct vm_state *vms, struct ast_vm_user *vmu)
static int mwi_handle_unsubscribe2(void *data)
#define VOICEMAIL_DIR_MODE
static int make_file(char *dest, const int len, const char *dir, const int num)
Creates a file system path expression for a folder within the voicemail data folder and the appropria...
static int manager_voicemail_refresh(struct mansession *s, const struct message *m)
static int inprocess_hash_fn(const void *obj, const int flags)
static struct ast_custom_function vm_info_acf
static const char * ast_str_encode_mime(struct ast_str **end, ssize_t maxlen, const char *start, size_t preamble, size_t postamble)
Encode a string according to the MIME rules for encoding strings that are not 7-bit clean or contain ...
static int show_messages_for_mailbox(struct ast_cli_args *a)
static int vm_msg_play(struct ast_channel *chan, const char *mailbox, const char *context, const char *folder, const char *msg_num, ast_vm_msg_play_cb cb)
static void make_email_file(FILE *p, char *srcemail, struct ast_vm_user *vmu, int msgnum, char *context, char *mailbox, const char *fromfolder, char *cidnum, char *cidname, char *attach, char *attach2, char *format, int duration, int attach_user_voicemail, struct ast_channel *chan, const char *category, int imap, const char *flag, const char *msg_id)
Creates the email file to be sent to indicate a new voicemail exists for a user.
static int manager_list_voicemail_users(struct mansession *s, const struct message *m)
Manager list voicemail users command.
#define DEFAULT_LISTEN_CONTROL_FORWARD_KEY
static int vm_delete(char *file)
Removes the voicemail sound and information file.
static int wait_file2(struct ast_channel *chan, struct vm_state *vms, char *file)
static int msg_id_incrementor
static const struct ast_vm_functions vm_table
static void free_zone(struct vm_zone *z)
static void adsi_begin(struct ast_channel *chan, int *useadsi)
static char * handle_voicemail_show_mailbox(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static void read_password_from_file(const char *secretfn, char *password, int passwordlen)
static int say_and_wait(struct ast_channel *chan, int num, const char *language)
static void apply_options_full(struct ast_vm_user *retval, struct ast_variable *var)
Loads the options specific to a voicemail user.
static void populate_defaults(struct ast_vm_user *vmu)
Sets default voicemail system options to a voicemail user.
static struct ast_taskprocessor * mwi_subscription_tps
static int vm_browse_messages_zh(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
Chinese (Taiwan)syntax for 'You have N messages' greeting.
static char vm_newpassword[80]
static int vm_intro_he(struct ast_channel *chan, struct vm_state *vms)
static int vm_execmain(struct ast_channel *chan, const char *data)
static void free_user(struct ast_vm_user *vmu)
AO2_STRING_FIELD_CMP_FN(alias_mailbox_mapping, alias)
static int vm_play_folder_name_gr(struct ast_channel *chan, char *box)
static int vm_instructions_zh(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int skipadvanced, int in_urgent, int nodelete)
static int invent_message(struct ast_channel *chan, char *context, char *ext, int busy, char *ecodes)
static int vm_instructions(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int skipadvanced, int in_urgent, int nodelete)
#define UPDATE_MSG_ID(a, b, c, d, e, f)
static int vm_instructions_en(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int skipadvanced, int in_urgent, int nodelete)
#define VM_STRING_HEADER_FORMAT
static void generate_msg_id(char *dst)
Sets the destination string to a uniquely identifying msg_id string.
static struct ast_flags globalflags
static char listen_control_forward_key[12]
static int play_record_review(struct ast_channel *chan, char *playfile, char *recordfile, int maxtime, char *fmt, int outsidecaller, struct ast_vm_user *vmu, int *duration, int *sound_duration, const char *unlockdir, signed char record_gain, struct vm_state *vms, char *flag, const char *msg_id, int forwardintro)
static int vmauthenticate(struct ast_channel *chan, const char *data)
static int play_message_duration(struct ast_channel *chan, struct vm_state *vms, const char *duration, int minduration)
static int vm_browse_messages_pt(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
Portuguese syntax for 'You have N messages' greeting.
static char vm_newuser[80]
#define VMBOX_STRING_HEADER_FORMAT
static int sendmail(char *srcemail, struct ast_vm_user *vmu, int msgnum, char *context, char *mailbox, const char *fromfolder, char *cidnum, char *cidname, char *attach, char *attach2, char *format, int duration, int attach_user_voicemail, struct ast_channel *chan, const char *category, const char *flag, const char *msg_id)
static const char * ast_str_quote(struct ast_str **buf, ssize_t maxlen, const char *from)
Wraps a character sequence in double quotes, escaping occurences of quotes within the string.
static ast_mutex_t poll_lock
static int check_mime(const char *str)
Check if the string would need encoding within the MIME standard, to avoid confusing certain mail sof...
static const char * vm_index_to_foldername(int id)
static unsigned char adsisec[4]
static int play_message_category(struct ast_channel *chan, const char *category)
static struct ast_vm_user * find_user_realtime(struct ast_vm_user *ivm, const char *context, const char *mailbox)
Finds a voicemail user from the realtime engine.
static const char * substitute_escapes(const char *value)
static int change_password_realtime(struct ast_vm_user *vmu, const char *password)
Performs a change of the voicemail passowrd in the realtime engine.
static int reset_user_pw(const char *context, const char *mailbox, const char *newpass)
Resets a user password to a specified password.
static int count_messages(struct ast_vm_user *vmu, char *dir)
Find all .txt files - even if they are not in sequence from 0000.
static pthread_t poll_thread
static int vm_intro_multilang(struct ast_channel *chan, struct vm_state *vms, const char message_gender[])
static int vm_exec(struct ast_channel *chan, const char *data)
static struct ast_vm_msg_snapshot * vm_msg_snapshot_alloc(void)
static char * pagersubject
static int manager_voicemail_forward(struct mansession *s, const struct message *m)
static int manager_voicemail_move(struct mansession *s, const struct message *m)
#define COPY(a, b, c, d, e, f, g, h)
static void load_zonemessages(struct ast_config *cfg)
static int vm_browse_messages(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
Top level method to invoke the language variant vm_browse_messages_XX function.
static int vm_intro(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms)
static int vm_playmsgexec(struct ast_channel *chan, const char *data)
static int vm_intro_de(struct ast_channel *chan, struct vm_state *vms)
static int passwordlocation
static int get_folder_ja(struct ast_channel *chan, int start)
static char vm_mismatch[80]
static void adsi_delete(struct ast_channel *chan, struct vm_state *vms)
static const struct ast_app_option vm_app_options[128]
static char * voicemail_app
static char * playmsg_app
static int vm_browse_messages_es(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
Spanish syntax for 'You have N messages' greeting.
static void notify_new_state(struct ast_vm_user *vmu)
static void adsi_message(struct ast_channel *chan, struct vm_state *vms)
#define ASTERISK_USERNAME
static int vm_newuser_setup(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain)
static int valid_config(const struct ast_config *cfg)
Check if configuration file is valid.
static char vm_pls_try_again[80]
static int play_message_callerid(struct ast_channel *chan, struct vm_state *vms, char *cid, const char *context, int callback, int saycidnumber)
static int write_password_to_file(const char *secretfn, const char *password)
static int wait_file(struct ast_channel *chan, struct vm_state *vms, char *file)
static int append_vmbox_info_astman(struct mansession *s, const struct message *m, struct ast_vm_user *vmu, const char *event_name, const char *actionid)
Append vmbox info string into given astman with event_name.
static int msg_create_from_file(struct ast_vm_recording_data *recdata)
static char * complete_voicemail_show_mailbox(struct ast_cli_args *a)
static const struct ast_vm_greeter_functions vm_greeter_table
static void rename_file(char *sfn, char *dfn)
Renames a message in a mailbox folder.
static int move_message_from_mailbox(struct ast_cli_args *a)
static struct alias_mailbox_mapping * alias_mailbox_mapping_create(const char *alias, const char *mailbox)
static struct ast_vm_mailbox_snapshot * vm_mailbox_snapshot_destroy(struct ast_vm_mailbox_snapshot *mailbox_snapshot)
struct ast_mwi_observer mwi_observer
static char ext_pass_check_cmd[128]
static int vm_intro_pt_BR(struct ast_channel *chan, struct vm_state *vms)
static int append_vmu_info_astman(struct mansession *s, struct ast_vm_user *vmu, const char *event_name, const char *actionid)
Append vmu info string into given astman with event_name.
static int separate_mailbox(char *mailbox_id, char **mailbox, char **context)
static int vm_msg_snapshot_create(struct ast_vm_user *vmu, struct vm_state *vms, struct ast_vm_mailbox_snapshot *mailbox_snapshot, int snapshot_index, int mailbox_index, int descending, enum ast_vm_snapshot_sort_val sort_val)
Create and store off all the msgs in an open mailbox.
static char dialcontext[AST_MAX_CONTEXT]
static int vmsayname_exec(struct ast_channel *chan, const char *data)
#define DEFAULT_POLL_FREQ
static int vm_intro_vi(struct ast_channel *chan, struct vm_state *vms)
static int messagecount(const char *mailbox_id, const char *folder)
static int manager_voicemail_remove(struct mansession *s, const struct message *m)
static void stop_poll_thread(void)
AO2_STRING_FIELD_HASH_FN(alias_mailbox_mapping, alias)
static char aliasescontext[MAX_VM_CONTEXT_LEN]
static int vm_sayname(struct ast_channel *chan, const char *mailbox_id)
#define DELETE(a, b, c, d)
static void print_mappings(void *v_obj, void *where, ao2_prnt_fn *prnt)
static struct ast_cli_entry cli_voicemail[]
#define DEFAULT_LISTEN_CONTROL_RESTART_KEY
static char listen_control_stop_key[12]
static char fromstring[100]
static int vm_browse_messages_ja(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
Japanese syntax for 'You have N messages' greeting.
#define PWDCHANGE_INTERNAL
static char * handle_voicemail_forward_message(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int vm_intro_cs(struct ast_channel *chan, struct vm_state *vms)
static void mwi_handle_unsubscribe(const char *id, struct ast_mwi_subscriber *sub)
static int adsi_load_vmail(struct ast_channel *chan, int *useadsi)
static void vm_change_password(struct ast_vm_user *vmu, const char *newpassword)
The handler for the change password option.
static void * mb_poll_thread(void *data)
static char cidinternalcontexts[MAX_NUM_CID_CONTEXTS][64]
static void run_externnotify(const char *context, const char *extension, const char *flag)
static int append_mailbox(const char *context, const char *box, const char *data)
static int vm_lock_path(const char *path)
Lock file path only return failure if ast_lock_path returns 'timeout', not if the path does not exist...
static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms)
static int vm_intro_nl(struct ast_channel *chan, struct vm_state *vms)
static void adsi_status(struct ast_channel *chan, struct vm_state *vms)
#define DEFAULT_LISTEN_CONTROL_STOP_KEY
static int acf_vm_info(struct ast_channel *chan, const char *cmd, char *args, char *buf, size_t len)
static int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu, int box)
static int vm_intro_zh(struct ast_channel *chan, struct vm_state *vms)
static char emaildateformat[32]
static char vm_reenterpassword[80]
static void adsi_login(struct ast_channel *chan)
static int manager_get_mailbox_summary(struct mansession *s, const struct message *m)
static int advanced_options(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int msg, int option, signed char record_gain)
The advanced options within a message.
#define MAX_VM_MAILBOX_LEN
static int __has_voicemail(const char *context, const char *mailbox, const char *folder, int shortcircuit)
static int vm_intro_pt(struct ast_channel *chan, struct vm_state *vms)
static int check_password(struct ast_vm_user *vmu, char *password)
Check that password meets minimum required length.
static int play_message_by_id_helper(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, const char *msg_id)
static int load_config_force(int reload, int force)
Reload voicemail.conf.
static int saydurationminfo
struct ao2_container * inprocess_container
static int vm_allocate_dh(struct vm_state *vms, struct ast_vm_user *vmu, int count_msg)
static void prep_email_sub_vars(struct ast_channel *ast, struct ast_vm_user *vmu, int msgnum, char *context, char *mailbox, const char *fromfolder, char *cidnum, char *cidname, char *dur, char *date, const char *category, const char *flag)
static char * sayname_app
static void free_user_final(struct ast_vm_user *vmu)
static int vm_instructions_ja(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int skipadvanced, int in_urgent, int nodelete)
static void load_users(struct ast_config *cfg)
static int message_range_and_existence_check(struct vm_state *vms, const char *msg_ids[], size_t num_msgs, int *msg_nums, struct ast_vm_user *vmu)
common bounds checking and existence check for Voicemail API functions.
static int get_folder2(struct ast_channel *chan, char *fn, int start)
plays a prompt and waits for a keypress.
static int vm_msg_forward(const char *from_mailbox, const char *from_context, const char *from_folder, const char *to_mailbox, const char *to_context, const char *to_folder, size_t num_msgs, const char *msg_ids[], int delete_old)
static void adsi_goodbye(struct ast_channel *chan)
#define HVSU_OUTPUT_FORMAT
static char ext_pass_cmd[128]
static int is_valid_dtmf(const char *key)
Determines if a DTMF key entered is valid.
static char pagerdateformat[32]
static int vm_tempgreeting(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain)
The handler for 'record a temporary greeting'.
static int actual_load_config(int reload, struct ast_config *cfg, struct ast_config *ucfg)
static int get_folder_by_name(const char *name)
#define HVSZ_OUTPUT_FORMAT
static char * emailsubject
static int inprocess_count(const char *context, const char *mailbox, int delta)
static struct ast_vm_user * find_user(struct ast_vm_user *ivm, const char *context, const char *mailbox)
Finds a voicemail user from the users file or the realtime engine.
static struct ao2_container * mailbox_alias_mappings
static int make_dir(char *dest, int len, const char *context, const char *ext, const char *folder)
Creates a file system path expression for a folder within the voicemail data folder and the appropria...
static void apply_options(struct ast_vm_user *vmu, const char *options)
Destructively Parse options and apply.
static int add_email_attachment(FILE *p, struct ast_vm_user *vmu, char *format, char *attach, char *greeting_attachment, char *mailbox, char *bound, char *filename, int last, int msgnum)
static char externnotify[160]
static int adsi_logo(unsigned char *buf)
static int play_message_datetime(struct ast_channel *chan, struct ast_vm_user *vmu, const char *origtime, const char *filename)
static unsigned char poll_thread_run
static char listen_control_restart_key[12]
static int add_message_id(struct ast_config *msg_cfg, char *dir, int msg, char *filename, char *id, size_t id_size, struct ast_vm_user *vmu, int folder)
static int play_message_by_id(struct ast_channel *chan, const char *mailbox, const char *context, const char *msg_id)
Finds a message in a specific mailbox by msg_id and plays it to the channel.
static int create_dirpath(char *dest, int len, const char *context, const char *ext, const char *folder)
basically mkdir -p $dest/$context/$ext/$folder
#define MAX_VM_MBOX_ID_LEN
static char * handle_voicemail_show_aliases(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Show a list of voicemail zones in the CLI.
static char * handle_voicemail_show_zones(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Show a list of voicemail zones in the CLI.
static void copy_plain_file(char *frompath, char *topath)
Copies a voicemail information (envelope) file.
static int vm_forwardoptions(struct ast_channel *chan, struct ast_vm_user *vmu, char *curdir, int curmsg, char *vm_fmts, char *context, signed char record_gain, long *duration, struct vm_state *vms, char *flag)
presents the option to prepend to an existing message when forwarding it.
#define DEFAULT_LISTEN_CONTROL_PAUSE_KEY
#define MAX_NUM_CID_CONTEXTS
static int vm_play_folder_name_pl(struct ast_channel *chan, char *box)
static char * complete_voicemail_show_users(const char *line, const char *word, int pos, int state)
static int inboxcount(const char *mailbox, int *newmsgs, int *oldmsgs)
@ OPT_PWLOC_VOICEMAILCONF
static char vm_prepend_timeout[80]
static char userscontext[AST_MAX_EXTENSION]
static int vm_authenticate(struct ast_channel *chan, char *mailbox, int mailbox_size, struct ast_vm_user *res_vmu, const char *context, const char *prefix, int skipuser, int max_logins, int silent)
#define RETRIEVE(a, b, c, d)
static int inprocess_cmp_fn(void *obj, void *arg, int flags)
static int vm_intro_en(struct ast_channel *chan, struct vm_state *vms)
static char VM_SPOOL_DIR[PATH_MAX]
static int vm_options(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain)
#define SMDI_MWI_WAIT_TIMEOUT
static char callcontext[AST_MAX_CONTEXT]
static void mwi_handle_subscribe(const char *id, struct ast_mwi_subscriber *sub)
static int vm_intro_da(struct ast_channel *chan, struct vm_state *vms)
static void vm_change_password_shell(struct ast_vm_user *vmu, char *newpassword)
static int vm_intro_fr(struct ast_channel *chan, struct vm_state *vms)
static int show_mailbox_snapshot(struct ast_cli_args *a)
static int vm_browse_messages_it(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
Italian syntax for 'You have N messages' greeting.
static int vm_msg_remove(const char *mailbox, const char *context, size_t num_msgs, const char *folder, const char *msgs[])
static char listen_control_pause_key[12]
static int copy(char *infile, char *outfile)
Utility function to copy a file.
static int silencethreshold
static void start_poll_thread(void)
#define MAX_MAIL_BODY_CONTENT_SIZE
static char * strip_control_and_high(const char *input, char *buf, size_t buflen)
Strips control and non 7-bit clean characters from input string.
#define RENAME(a, b, c, d, e, f, g, h)
static int load_module(void)
Load the module.
static char * handle_voicemail_move_message(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int vm_browse_messages_he(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
static unsigned int poll_mailboxes
static int poll_subscribed_mailbox(struct ast_mwi_state *mwi_state, void *data)
static int sendpage(char *srcemail, char *pager, int msgnum, char *context, char *mailbox, const char *fromfolder, char *cidnum, char *cidname, int duration, struct ast_vm_user *vmu, const char *category, const char *flag)
static int forward_message_from_mailbox(struct ast_cli_args *a)
#define STORE(a, b, c, d, e, f, g, h, i, j, k)
static int vm_intro_is(struct ast_channel *chan, struct vm_state *vms)
static char * complete_voicemail_move_message(struct ast_cli_args *a, int maxpos)
static char * handle_voicemail_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Reload voicemail configuration from the CLI.
static unsigned int poll_freq
static int resequence_mailbox(struct ast_vm_user *vmu, char *dir, int stopcount)
static int last_message_index(char *dir)
Determines the highest message number in use for a given user and mailbox folder.
static ast_cond_t poll_cond
static void adsi_status2(struct ast_channel *chan, struct vm_state *vms)
static int unload_module(void)
static int load_config(int reload)
static void free_vm_zones(void)
Free the zones structure.
static int mwi_handle_subscribe2(void *data)
static int forward_message(struct ast_channel *chan, char *context, struct vm_state *vms, struct ast_vm_user *sender, char *fmt, int is_new_message, signed char record_gain, int urgent)
Sends a voicemail message to a mailbox recipient.
static int vm_intro_es(struct ast_channel *chan, struct vm_state *vms)
#define PWDCHANGE_EXTERNAL
static struct ast_vm_user * find_or_create(const char *context, const char *box)
static unsigned char adsifdn[4]
static void queue_mwi_event(const char *channel_id, const char *box, int urgent, int new, int old)
static int manager_status_voicemail_user(struct mansession *s, const struct message *m)
#define VOICEMAIL_FILE_MODE
static char * handle_voicemail_remove_message(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static void load_aliases(struct ast_config *cfg)
static struct ao2_container * alias_mailbox_mappings
static int vm_play_folder_name(struct ast_channel *chan, char *mbox)
static const struct ast_tm * vmu_tm(const struct ast_vm_user *vmu, struct ast_tm *tm)
fill in *tm for current time according to the proper timezone, if any.
static int vm_play_folder_name_ua(struct ast_channel *chan, char *box)
#define DEFAULT_LISTEN_CONTROL_REVERSE_KEY
static char * show_users_realtime(int fd, const char *context)
static int remove_message_from_mailbox(struct ast_cli_args *a)
static int has_voicemail(const char *mailbox, const char *folder)
Determines if the given folder has messages.
static int notify_new_message(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int msgnum, long duration, char *fmt, char *cidnum, char *cidname, const char *flag)
Sends email notification that a user has a new voicemail waiting for them.
#define VM_EMAIL_EXT_RECS
static struct ast_vm_mailbox_snapshot * vm_mailbox_snapshot_create(const char *mailbox, const char *context, const char *folder, int descending, enum ast_vm_snapshot_sort_val sort_val, int combine_INBOX_and_OLD)
static int manager_match_mailbox(struct ast_mwi_state *mwi_state, void *data)
static int vm_intro_ja(struct ast_channel *chan, struct vm_state *vms)
static int inboxcount2(const char *mailbox, int *urgentmsgs, int *newmsgs, int *oldmsgs)
Check the given mailbox's message count.
static char exitcontext[AST_MAX_CONTEXT]
static int dialout(struct ast_channel *chan, struct ast_vm_user *vmu, char *num, char *outgoing_context)
static int vm_msg_move(const char *mailbox, const char *context, size_t num_msgs, const char *oldfolder, const char *old_msg_ids[], const char *newfolder)
static int sayname(struct ast_channel *chan, const char *mailbox, const char *context)
static int get_date(char *s, int len)
Gets the current date and time, as formatted string.
static const char *const mailbox_folders[]
static int show_mailbox_details(struct ast_cli_args *a)
static const char * mbox(struct ast_vm_user *vmu, int id)
static int copy_message(struct ast_channel *chan, struct ast_vm_user *vmu, int imbox, int msgnum, long duration, struct ast_vm_user *recip, char *fmt, char *dir, const char *flag, const char *dest_folder)
Copies a message from one mailbox to another.
static char * vmauthenticate_app
static int vm_play_folder_name_ja(struct ast_channel *chan, char *box)
#define force_reload_config()
Forcibly reload voicemail.conf, even if it has not changed. This is necessary after running unit test...
static int vm_intro_se(struct ast_channel *chan, struct vm_state *vms)
static void apply_option(struct ast_vm_user *vmu, const char *var, const char *value)
Sets a specific property value.
static char vm_passchanged[80]
static struct ast_vm_msg_snapshot * vm_msg_snapshot_destroy(struct ast_vm_msg_snapshot *msg_snapshot)
static char * voicemailmain_app
#define ALIASES_OUTPUT_FORMAT
static int vm_intro_it(struct ast_channel *chan, struct vm_state *vms)
static int vm_browse_messages_gr(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
Greek syntax for 'You have N messages' greeting.
static struct ast_smdi_interface * smdi_iface
static int vm_intro_gr(struct ast_channel *chan, struct vm_state *vms)
static void free_vm_users(void)
Free the users structure.
static int vm_intro_no(struct ast_channel *chan, struct vm_state *vms)
static int input(yyscan_t yyscanner)
Asterisk main include file. File version handling, generic pbx functions.
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
#define ast_realloc(p, len)
A wrapper for realloc()
#define ast_strdup(str)
A wrapper for strdup()
#define ast_strdupa(s)
duplicate a string in memory from the stack
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
#define ast_calloc(num, len)
A wrapper for calloc()
#define ast_malloc(len)
A wrapper for malloc()
#define ao2_iterator_next(iter)
#define ao2_link(container, obj)
Add an object to a container.
@ AO2_ALLOC_OPT_LOCK_MUTEX
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container,...
void ao2_container_unregister(const char *name)
Unregister a container for CLI stats and integrity check.
#define ao2_find(container, arg, flags)
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
int ao2_container_register(const char *name, struct ao2_container *self, ao2_prnt_obj_fn *prnt_obj)
Register a container for CLI stats and integrity check.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
@ OBJ_SEARCH_KEY
The arg parameter is a search key, but is not an object.
#define ao2_alloc(data_size, destructor_fn)
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Allocate and initialize a hash container with the desired number of buckets.
void() ao2_prnt_fn(void *where, const char *fmt,...)
Print output.
char * ast_callerid_merge(char *buf, int bufsiz, const char *name, const char *num, const char *unknown)
int ast_callerid_parse(char *instr, char **name, char **location)
Destructively parse inbuf into name and location (or number)
int ast_callerid_split(const char *src, char *name, int namelen, char *num, int numlen)
static SQLHSTMT generic_prepare(struct odbc_obj *obj, void *data)
static char language[MAX_LANGUAGE]
static int transfer(void *data)
General Asterisk PBX channel definitions.
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
const char * ast_channel_name(const struct ast_channel *chan)
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
#define ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag,...)
Create a channel structure.
void ast_channel_nativeformats_set(struct ast_channel *chan, struct ast_format_cap *value)
#define ast_channel_lock(chan)
struct ast_party_redirecting * ast_channel_redirecting(struct ast_channel *chan)
int ast_channel_priority(const struct ast_channel *chan)
const char * ast_channel_uniqueid(const struct ast_channel *chan)
const char * ast_channel_context(const struct ast_channel *chan)
void ast_channel_set_rawreadformat(struct ast_channel *chan, struct ast_format *format)
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
void ast_channel_set_rawwriteformat(struct ast_channel *chan, struct ast_format *format)
void ast_channel_set_readformat(struct ast_channel *chan, struct ast_format *format)
#define ast_channel_unref(c)
Decrease channel reference count.
const char * ast_channel_language(const struct ast_channel *chan)
void ast_channel_context_set(struct ast_channel *chan, const char *value)
#define ast_dummy_channel_alloc()
Create a fake channel structure.
int ast_channel_setoption(struct ast_channel *channel, int option, void *data, int datalen, int block)
Sets an option on a channel.
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
void ast_channel_priority_set(struct ast_channel *chan, int value)
int ast_readstring(struct ast_channel *c, char *s, int len, int timeout, int rtimeout, char *enders)
Reads multiple digits.
int ast_answer(struct ast_channel *chan)
Answer a channel.
void ast_channel_adsicpe_set(struct ast_channel *chan, enum ast_channel_adsicpe value)
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
void ast_channel_tech_set(struct ast_channel *chan, const struct ast_channel_tech *value)
const char * ast_channel_exten(const struct ast_channel *chan)
#define ast_channel_unlock(chan)
#define AST_MAX_EXTENSION
void ast_channel_set_writeformat(struct ast_channel *chan, struct ast_format *format)
void ast_party_caller_init(struct ast_party_caller *init)
Initialize the given caller structure.
ast_channel_state
ast_channel states
Standard Command Line Interface.
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
#define AST_CLI_DEFINE(fn, txt,...)
void ast_cli(int fd, const char *fmt,...)
#define ast_cli_register_multiple(e, len)
Register multiple commands.
static struct progalias aliases[]
Convenient Signal Processing routines.
int ast_dsp_get_threshold_from_settings(enum threshold which)
Get silence threshold from dsp.conf.
static char * config_filename
Generic File Format Support. Should be included by clients of the file handling routines....
off_t ast_tellstream(struct ast_filestream *fs)
Tell where we are in a stream.
int ast_stopstream(struct ast_channel *c)
Stops a stream.
int ast_seekstream(struct ast_filestream *fs, off_t sample_offset, int whence)
Seeks into stream.
int ast_filerename(const char *oldname, const char *newname, const char *fmt)
Renames a file.
struct ast_filestream * ast_readfile(const char *filename, const char *type, const char *comment, int flags, int check, mode_t mode)
Starts reading from a file.
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
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.
FILE * ast_file_mkftemp(char *template, mode_t mode)
same as mkstemp, but return a 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 struct ast_threadstorage buf2
static struct ast_threadstorage buf1
static int quote(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag)
Send ack in manager transaction to begin a list.
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
void ast_manager_publish_event(const char *type, int class_type, struct ast_json *obj)
Publish an event to AMI.
void astman_send_list_complete_start(struct mansession *s, const struct message *m, const char *event_name, int count)
Start the list complete event.
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
void astman_append(struct mansession *s, const char *fmt,...)
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
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.
void ast_unreplace_sigchld(void)
Restore the SIGCHLD handler.
#define ast_vm_greeter_register(vm_table)
See __ast_vm_greeter_register()
struct ast_vm_mailbox_snapshot * ast_vm_mailbox_snapshot_create(const char *mailbox, const char *context, const char *folder, int descending, enum ast_vm_snapshot_sort_val sort_val, int combine_INBOX_and_OLD)
Create a snapshot of a mailbox which contains information about every msg.
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
int ast_unlock_path(const char *path)
Unlock a path.
void ast_close_fds_above_n(int n)
Common routine for child processes, to close all fds prior to exec(2)
char * strsep(char **str, const char *delims)
char * mkdtemp(char *template_s)
char * strcasestr(const char *, const char *)
Configuration File Parser.
#define ast_config_load(filename, flags)
Load a config file.
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
int ast_update2_realtime(const char *family,...) attribute_sentinel
Update realtime configuration.
struct ast_config * ast_config_new(void)
Create a new base configuration structure.
int ast_realtime_require_field(const char *family,...) attribute_sentinel
Inform realtime what fields that may be stored.
struct ast_config * ast_load_realtime_multientry(const char *family,...) attribute_sentinel
Retrieve realtime configuration.
int ast_config_text_file_save(const char *filename, const struct ast_config *cfg, const char *generator)
Save a config text file preserving the pre 13.2 behavior.
void ast_category_append(struct ast_config *config, struct ast_category *category)
Appends a category to a config.
void ast_variable_append(struct ast_category *category, struct ast_variable *variable)
int ast_variable_update(struct ast_category *category, const char *variable, const char *value, const char *match, unsigned int object)
Update variable value within a config.
struct ast_category * ast_category_new(const char *name, const char *in_file, int lineno)
Create a category.
#define ast_variable_new(name, value, filename)
int ast_unload_realtime(const char *family)
Release any resources cached for a realtime family.
#define CONFIG_STATUS_FILEUNCHANGED
#define CONFIG_STATUS_FILEINVALID
int ast_check_realtime(const char *family)
Check if realtime engine is configured for family.
int ast_destroy_realtime(const char *family, const char *keyfield, const char *lookup,...) attribute_sentinel
Destroy realtime configuration.
void ast_category_destroy(struct ast_category *cat)
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
int ast_update_realtime(const char *family, const char *keyfield, const char *lookup,...) attribute_sentinel
Update realtime configuration.
int ast_store_realtime(const char *family,...) attribute_sentinel
Create realtime configuration.
const char * ast_config_option(struct ast_config *cfg, const char *cat, const char *var)
Retrieve a configuration variable within the configuration set.
struct ast_variable * ast_load_realtime(const char *family,...) attribute_sentinel
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
struct ast_category * ast_category_get(const struct ast_config *config, const char *category_name, const char *filter)
Retrieve a category if it exists.
@ CONFIG_FLAG_WITHCOMMENTS
@ CONFIG_FLAG_FILEUNCHANGED
#define AST_OPTION_RXGAIN
struct ast_frame ast_null_frame
Support for logging to various files, console and syslog Configuration in file logger....
#define DEBUG_ATLEAST(level)
#define ast_debug(level,...)
Log a DEBUG message.
#define ast_verb(level,...)
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
#define AST_LIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a list of specified type, statically initialized.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
#define AST_LIST_HEAD_NOLOCK_STATIC(name, type)
Defines a structure to be used to hold a list of specified type, statically initialized.
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
#define AST_LIST_INSERT_BEFORE_CURRENT(elm, field)
Inserts a list entry before the current entry during a traversal.
#define AST_LIST_LOCK(head)
Locks a list.
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Custom localtime functions for multiple timezones.
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
int ast_strftime(char *buf, size_t len, const char *format, const struct ast_tm *tm)
Special version of strftime(3) that handles fractions of a second. Takes the same arguments as strfti...
int ast_strftime_locale(char *buf, size_t len, const char *format, const struct ast_tm *tm, const char *locale)
Asterisk locking-related definitions:
#define AST_PTHREADT_NULL
#define ast_cond_timedwait(cond, mutex, time)
#define ast_mutex_init(pmutex)
#define ast_mutex_unlock(a)
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
pthread_cond_t ast_cond_t
#define ast_mutex_destroy(a)
#define ast_mutex_lock(a)
#define AST_MUTEX_DEFINE_STATIC(mutex)
#define ast_cond_signal(cond)
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
#define EVENT_FLAG_REPORTING
#define EVENT_FLAG_SYSTEM
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Asterisk module definitions.
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
@ AST_MODULE_SUPPORT_CORE
#define ASTERISK_GPL_KEY
The text the key() function should return.
int ast_unregister_application(const char *app)
Unregister an application.
@ AST_MODULE_LOAD_SUCCESS
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
#define ast_publish_mwi_state_channel(mailbox, context, new_msgs, old_msgs, channel_id)
Publish a MWI state update associated with some channel.
void ast_mwi_state_callback_all(on_mwi_state handler, void *data)
For each managed mailbox call the given handler.
void ast_mwi_state_callback_subscribed(on_mwi_state handler, void *data)
For each managed mailbox that has a subscriber call the given handler.
int ast_mwi_add_observer(struct ast_mwi_observer *observer)
Add an observer to receive MWI state related events.
int ast_delete_mwi_state_full(const char *mailbox, const char *context, struct ast_eid *eid)
Delete MWI state cached by stasis with all parameters.
void ast_mwi_remove_observer(struct ast_mwi_observer *observer)
Remove an MWI state observer.
struct ast_mwi_state * ast_mwi_subscriber_data(struct ast_mwi_subscriber *sub)
Retrieves the state data object associated with the MWI subscriber.
def from_mailbox(key, val, section, pjsip, nmapped)
Asterisk file paths, configured in asterisk.conf.
const char * ast_config_AST_DATA_DIR
const char * ast_config_AST_SPOOL_DIR
Core PBX routines and definitions.
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
void ast_str_substitute_variables(struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ)
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
int pbx_exec(struct ast_channel *c, struct ast_app *app, const char *data)
Execute an application.
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name.
#define ast_custom_function_register(acf)
Register a custom function.
int ast_goto_if_exists(struct ast_channel *chan, const char *context, const char *exten, int priority)
int ast_canmatch_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Looks for a valid matching extension.
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
struct ast_app * pbx_findapp(const char *app)
Look up an application.
static void * cleanup(void *unused)
static char intro[ADSI_MAX_INTRO][20]
static struct stasis_rest_handlers mailboxes
REST handler for /api-docs/mailboxes.json.
struct stasis_forward * sub
int ast_odbc_prepare(struct odbc_obj *obj, SQLHSTMT *stmt, const char *sql)
Prepares a SQL query on a statement.
void ast_odbc_release_obj(struct odbc_obj *obj)
Releases an ODBC object previously allocated by ast_odbc_request_obj()
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 void delete_file(struct phoneprov_file *file)
static int debug
Global debug status.
Say numbers and dates (maybe words one day too)
int ast_say_character_str(struct ast_channel *chan, const char *num, const char *ints, const char *lang, enum ast_say_case_sensitivity sensitivity)
function to pronounce character and phonetic strings
int ast_say_number(struct ast_channel *chan, int num, const char *ints, const char *lang, const char *options)
says a number
SAY_EXTERN int(* ast_say_date_with_format)(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *timezone) SAY_INIT(ast_say_date_with_format)
int ast_say_counted_noun(struct ast_channel *chan, int num, const char *noun)
int ast_say_counted_adjective(struct ast_channel *chan, int num, const char *adjective, const char *gender)
int ast_say_digit_str(struct ast_channel *chan, const char *num, const char *ints, const char *lang)
says digits of a string
SMDI support for Asterisk.
struct ast_smdi_interface * ast_smdi_interface_find(const char *iface_name)
Find an SMDI interface with the specified name.
int ast_smdi_mwi_set(struct ast_smdi_interface *iface, const char *mailbox)
Set the MWI indicator for a mailbox.
struct ast_smdi_mwi_message * ast_smdi_mwi_message_wait_station(struct ast_smdi_interface *iface, int timeout, const char *station)
int ast_smdi_mwi_unset(struct ast_smdi_interface *iface, const char *mailbox)
Unset the MWI indicator for a mailbox.
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
String manipulation functions.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
int ast_get_time_t(const char *src, time_t *dst, time_t _default, int *consumed)
Parse a time (integer) string.
static force_inline int attribute_pure ast_strlen_zero(const char *s)
int ast_build_string(char **buffer, size_t *space, const char *fmt,...)
Build a string in a buffer, designed to be called repeatedly.
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is "false"....
#define ast_str_alloca(init_len)
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
ast_app: A registered application
Structure to describe a channel "technology", ie a channel driver See for examples:
int(*const write)(struct ast_channel *chan, struct ast_frame *frame)
Write a frame, in standard format (see frame.h)
struct ast_format_cap * capabilities
Main Channel structure associated with a channel.
descriptor for a cli entry.
Data structure associated with a custom dialplan function.
This structure is allocated by file.c in one chunk, together with buf_size and desc_size bytes of mem...
Structure used to handle boolean flags.
Data structure associated with a single frame of data.
Abstract JSON element (object, array, string, int, ...).
Structure for mutex and tracking information.
MWI state event interface.
void(* on_subscribe)(const char *mailbox, struct ast_mwi_subscriber *sub)
Raised when MWI is being subscribed.
The structure that contains MWI state.
const ast_string_field uniqueid
Caller Party information.
struct ast_party_id id
Caller party ID.
struct ast_party_name name
Subscriber name.
struct ast_party_number number
Subscriber phone number.
unsigned char valid
TRUE if the name information is valid/present.
char * str
Subscriber name (Malloced)
unsigned char valid
TRUE if the number information is valid/present.
char * str
Subscriber phone number (Malloced)
An SMDI message waiting indicator message.
char cause[SMDI_MWI_FAIL_CAUSE_LEN+1]
char fwd_st[SMDI_MAX_STATION_NUM_LEN+1]
Support for dynamic strings.
A ast_taskprocessor structure is a singleton by name.
Structure for variables, used for configurations and for channel variables.
Voicemail function table definition.
unsigned int module_version
The version of this function table.
const char * module_name
The name of the module that provides the voicemail functionality.
Voicemail greeter function table definition.
unsigned int module_version
The version of this function table.
const char * module_name
The name of the module that provides the voicemail greeter functionality.
struct ast_vm_mailbox_snapshot::@185 * snapshots
const ast_string_field origtime
struct ast_vm_msg_snapshot::@184 msg
const ast_string_field msg_id
Structure used for ast_copy_recording_to_vm in order to cleanly supply data needed for making the rec...
const ast_string_field recording_file
const ast_string_field call_callerchan
const ast_string_field context
const ast_string_field folder
const ast_string_field call_callerid
const ast_string_field call_context
const ast_string_field recording_ext
const ast_string_field call_extension
const ast_string_field mailbox
char mailbox[MAX_VM_MBOX_ID_LEN]
struct ast_vm_user::@82 list
char context[MAX_VM_CONTEXT_LEN]
char language[MAX_LANGUAGE]
All configuration options for http media cache.
structure to hold extensions
Options for leaving voicemail with the voicemail() application.
In case you didn't read that giant block of text above the mansession_session struct,...
structure to hold users read from users.conf
list of users found in the config file
An API for managing task processing threads that can be shared across modules.
struct ast_taskprocessor * ast_taskprocessor_get(const char *name, enum ast_tps_options create)
Get a reference to a taskprocessor with the specified name and create the taskprocessor if necessary.
void * ast_taskprocessor_unreference(struct ast_taskprocessor *tps)
Unreference the specified taskprocessor and its reference count will decrement.
int ast_taskprocessor_push(struct ast_taskprocessor *tps, int(*task_exe)(void *datap), void *datap) attribute_warn_unused_result
Push a task into the specified taskprocessor queue and signal the taskprocessor thread.
#define AST_TASKPROCESSOR_HIGH_WATER_LEVEL
int ast_taskprocessor_alert_set_levels(struct ast_taskprocessor *tps, long low_water, long high_water)
Set the high and low alert water marks of the given taskprocessor queue.
#define AST_TEST_REGISTER(cb)
#define ast_test_status_update(a, b, c...)
#define AST_TEST_UNREGISTER(cb)
#define ast_test_suite_event_notify(s, f,...)
#define AST_TEST_DEFINE(hdr)
Definitions to aid in the use of thread local storage.
#define AST_THREADSTORAGE(name)
Define a thread storage variable.
Time-related functions and macros.
struct timeval ast_samp2tv(unsigned int _nsamp, unsigned int _rate)
Returns a timeval corresponding to the duration of n samples at rate r. Useful to convert samples to ...
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
#define ast_test_flag(p, flag)
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
int ast_file_is_readable(const char *filename)
Test that a file exists and is readable by the effective user.
#define ast_pthread_create(a, b, c, d)
#define ast_set2_flag(p, value, flag)
#define ast_clear_flag(p, flag)
long int ast_random(void)
int ast_mkdir(const char *path, int mode)
Recursively create directory path.
#define ast_set_flag(p, flag)
#define ast_copy_flags(dest, src, flagz)
int ast_base64_encode_file_path(const char *filename, FILE *outputfile, const char *endl)
Performs a base 64 encode algorithm on the contents of a File.