558#define MVM_REVIEW (1 << 0)
559#define MVM_OPERATOR (1 << 1)
560#define MVM_REALTIME (1 << 2)
561#define MVM_SVMAIL (1 << 3)
562#define MVM_ENVELOPE (1 << 4)
563#define MVM_PBXSKIP (1 << 9)
564#define MVM_ALLOCED (1 << 13)
568#define SENDMAIL "/usr/sbin/sendmail -t"
570#define SOUND_INTRO "vm-intro"
573#define MAX_DATETIME_FORMAT 512
574#define MAX_NUM_CID_CONTEXTS 10
576#define ERROR_LOCK_PATH -100
577#define VOICEMAIL_DIR_MODE 0700
579#define VOICEMAIL_CONFIG "minivm.conf"
580#define ASTERISK_USERNAME "asterisk"
733#define DEFAULT_DATEFORMAT "%A, %B %d, %Y at %r"
734#define DEFAULT_CHARSET "ISO-8859-1"
757 ast_copy_string(template->subject,
"New message in mailbox ${MVM_USERNAME}@${MVM_DOMAIN}",
sizeof(template->subject));
758 template->attachment =
TRUE;
787 ast_debug(3,
"Configuring template option %s = \"%s\" for template %s\n",
var->name,
var->value,
name);
788 if (!strcasecmp(
var->name,
"fromaddress")) {
790 }
else if (!strcasecmp(
var->name,
"fromemail")) {
792 }
else if (!strcasecmp(
var->name,
"subject")) {
794 }
else if (!strcasecmp(
var->name,
"locale")) {
796 }
else if (!strcasecmp(
var->name,
"attachmedia")) {
798 }
else if (!strcasecmp(
var->name,
"dateformat")) {
800 }
else if (!strcasecmp(
var->name,
"charset")) {
802 }
else if (!strcasecmp(
var->name,
"templatefile")) {
806 if (!template->body) {
810 }
else if (!strcasecmp(
var->name,
"messagebody")) {
814 if (!template->body) {
847 if (!strcasecmp(this->name,
name)) {
970 ast_debug(3,
"Looking for voicemail user %s in domain %s\n", username, domain);
975 if (!strcasecmp(domain, cur->domain) && !strcasecmp(username, cur->username))
981 ast_debug(3,
"Found account for %s@%s\n", username, domain);
987 if (createtemp && !vmu) {
994 ast_debug(1,
"Created temporary account\n");
1026 snprintf(
name,
sizeof(
name),
"%s@%s", username, domain);
1041 if (*
str > 126 || *
str < 32 || strchr(
"()<>@,:;/\"[]?.=", *
str)) {
1070 int first_section = 1;
1074 for (; *start; start++) {
1075 int need_encoding = 0;
1076 if (*start < 33 || *start > 126 || strchr(
"()<>@,:;/\"[]?.=_", *start)) {
1079 if ((first_section && need_encoding && preamble +
ast_str_strlen(tmp) > 70) ||
1080 (first_section && !need_encoding && preamble +
ast_str_strlen(tmp) > 72) ||
1082 (!first_section && !need_encoding &&
ast_str_strlen(tmp) > 72)) {
1088 if (need_encoding && *start ==
' ') {
1090 }
else if (need_encoding) {
1114 for (ptr = from; *ptr; ptr++) {
1115 if (*ptr ==
'"' || *ptr ==
'\\') {
1134 char email[256] =
"";
1140 char tmp[80] =
"/tmp/astmail-XXXXXX";
1142 char sox_gain_tmpdir[
PATH_MAX] =
"";
1143 char *file_to_delete =
NULL, *dir_to_delete =
NULL;
1152 if (!str1 || !str2) {
1172 if (!strcmp(format,
"wav49"))
1179 ast_copy_string(sox_gain_tmpdir,
"/tmp/minivm-gain-XXXXXX",
sizeof(sox_gain_tmpdir));
1180 ast_debug(3,
"sox_gain_tmpdir: %s\n", sox_gain_tmpdir);
1181 if (!
mkdtemp(sox_gain_tmpdir)) {
1185 snprintf(fname,
sizeof(fname),
"%s/output.%s", sox_gain_tmpdir, format);
1186 snprintf(sox_gain_cmd,
sizeof(sox_gain_cmd),
"sox -v %.4f %s.%s %s", vmu->
volgain, filename, format, fname);
1188 ast_debug(3,
"VOLGAIN: Stored at: %s.%s - Level: %.4f - Mailbox: %s\n", filename, format, vmu->
volgain, vmu->
username);
1191 file_to_delete = fname;
1192 dir_to_delete = sox_gain_tmpdir;
1194 snprintf(fname,
sizeof(fname),
"%s.%s", filename, format);
1197 if (template->attachment)
1198 ast_debug(1,
"Attaching file '%s', format '%s', uservm is '%d'\n", fname, format, attach_user_voicemail);
1204 p = fdopen(pfd,
"w");
1209 ast_debug(1,
"Opening temp file for e-mail: %s\n", tmp);
1221 snprintf(dur,
sizeof(dur),
"%d:%02d", duration / 60, duration % 60);
1238 ast_strftime(date,
sizeof(date),
"%a, %d %b %Y %H:%M:%S %z", &tm);
1241 fprintf(p,
"Date: %s\n", date);
1244 ast_strftime(date,
sizeof(date), template->dateformat, &tm);
1258 fromemail =
"asterisk";
1260 if (strchr(fromemail,
'@'))
1264 gethostname(host,
sizeof(host)-1);
1265 snprintf(who,
sizeof(who),
"%s@%s", fromemail, host);
1269 fprintf(p,
"From: Asterisk PBX <%s>\n", who);
1279 fprintf(p,
"%s %s\n", first_line ?
"From:" :
"",
ast_str_buffer(str2));
1284 fprintf(p,
"%s %s <%s>\n", first_line ?
"From:" :
"",
ast_str_buffer(str2), who);
1290 fprintf(p,
"Message-ID: <Asterisk-%u-%s-%d-%s>\n", (
unsigned int)
ast_random(), vmu->
username, (
int)getpid(), who);
1304 fprintf(p,
"%s %s\n", first_line ?
"To:" :
"",
ast_str_buffer(str2));
1322 fprintf(p,
"%s %s\n", first_line ?
"Subject:" :
"",
ast_str_buffer(str2));
1327 fprintf(p,
"%s %s\n", first_line ?
"Subject:" :
"",
ast_str_buffer(str2));
1332 fprintf(p,
"Subject: New message in mailbox %s@%s\n", vmu->
username, vmu->
domain);
1333 ast_debug(1,
"Using default subject for this email \n");
1337 fprintf(p,
"X-Asterisk-debug: template %s user account %s@%s\n", template->name, vmu->
username, vmu->
domain);
1338 fprintf(p,
"MIME-Version: 1.0\n");
1341 snprintf(bound,
sizeof(bound),
"voicemail_%s%d%u", vmu->
username, (
int)getpid(), (
unsigned int)
ast_random());
1343 fprintf(p,
"Content-Type: multipart/mixed; boundary=\"%s\"\n\n\n", bound);
1345 fprintf(p,
"--%s\n", bound);
1346 fprintf(p,
"Content-Type: text/plain; charset=%s\nContent-Transfer-Encoding: 8bit\n\n", template->charset);
1352 fprintf(p,
"Dear %s:\n\n\tJust wanted to let you know you were just left a %s long message \n"
1353 "in mailbox %s from %s, on %s so you might\n"
1354 "want to check it when you get a chance. Thanks!\n\n\t\t\t\t--Asterisk\n\n", vmu->
fullname,
1355 dur, vmu->
username, (cidname ? cidname : (cidnum ? cidnum :
"an unknown caller")), date);
1356 ast_debug(3,
"Using default message body (no template)\n-----\n");
1359 if (template->attachment) {
1360 char *ctype =
"audio/x-";
1361 ast_debug(3,
"Attaching file to message: %s\n", fname);
1362 if (!strcasecmp(format,
"ogg"))
1363 ctype =
"application/";
1365 fprintf(p,
"--%s\n", bound);
1366 fprintf(p,
"Content-Type: %s%s; name=\"voicemailmsg.%s\"\n", ctype, format, format);
1367 fprintf(p,
"Content-Transfer-Encoding: base64\n");
1368 fprintf(p,
"Content-Description: Voicemail sound attachment.\n");
1369 fprintf(p,
"Content-Disposition: attachment; filename=\"voicemail%s.%s\"\n\n", counter ? counter :
"", format);
1372 fprintf(p,
"\n\n--%s--\n.\n", bound);
1378 if (file_to_delete && dir_to_delete) {
1381 res = snprintf(mail_cmd_buffer,
sizeof(mail_cmd_buffer),
1382 "( %s < %s ; rm -f %s %s ; rmdir %s ) &",
1385 res = snprintf(mail_cmd_buffer,
sizeof(mail_cmd_buffer),
1386 "( %s < %s ; rm -f %s ) &",
1390 if (res <
sizeof(mail_cmd_buffer)) {
1391 file_to_delete = dir_to_delete =
NULL;
1399 ast_debug(1,
"Sent message to %s with command '%s'%s\n", vmu->
email,
global_mailcmd, template->attachment ?
" - (media attachment)" :
"");
1400 ast_debug(3,
"Actual command used: %s\n", mail_cmd_buffer);
1405 if (file_to_delete) {
1406 unlink(file_to_delete);
1409 if (dir_to_delete) {
1410 rmdir(dir_to_delete);
1418static int make_dir(
char *dest,
int len,
const char *domain,
const char *username,
const char *folder)
1434 struct stat filestat;
1435 make_dir(dest,
len, domain, username, folder ? folder :
"");
1436 if (stat(dest, &filestat)== -1)
1459 ast_debug(2,
"Creating directory for %s@%s folder %s : %s\n", username, domain, folder, dest);
1472 ast_debug(2,
"Still preparing to play message ...\n");
1474 snprintf(fn,
sizeof(fn),
"%s%s/%s/greet",
MVM_SPOOL_DIR, domain, username);
1484 int numericusername = 1;
1487 ast_debug(2,
"No personal prompts. Using default prompt set for language\n");
1490 ast_debug(2,
"Numeric? Checking %c\n", *i);
1492 numericusername =
FALSE;
1498 if (numericusername) {
1539 int outsidecaller,
struct minivm_account *vmu,
int *duration,
int *sound_duration,
const char *unlockdir,
1540 signed char record_gain)
1543 int max_attempts = 3;
1546 int message_exists = 0;
1547 signed char zero_gain = 0;
1548 char *acceptdtmf =
"#";
1549 char *canceldtmf =
"";
1554 if (duration ==
NULL) {
1561 while ((cmd >= 0) && (cmd !=
't')) {
1564 ast_verb(3,
"Saving message as is\n");
1570 ast_verb(3,
"Reviewing the message\n");
1578 ast_verb(3,
"Re-recording the message\n");
1580 ast_verb(3,
"Recording the message\n");
1581 if (recorded && outsidecaller)
1589 cmd =
ast_play_and_record_full(chan, playfile, recordfile, maxtime, fmt, duration, sound_duration, 0,
global_silencethreshold,
global_maxsilence, unlockdir, acceptdtmf, canceldtmf, 0,
AST_RECORD_IF_EXISTS_OVERWRITE);
1596 else if (cmd ==
'*')
1619 if (message_exists || recorded) {
1639 if (message_exists) {
1657 if (attempts > max_attempts) {
1673 char *argv[5] = {
NULL };
1682 snprintf(fquser,
sizeof(fquser),
"%s@%s", vmu->
username, vmu->
domain);
1687 argv[idx++] = fquser;
1698 ast_debug(1,
"Executing: %s %s %s %s\n",
1699 argv[0], argv[1], argv[2] ?:
"", argv[3] ?:
"");
1712 char *messageformat;
1714 char oldlocale[100];
1715 const char *counter;
1738 ast_debug(2,
"Changing locale from %s to %s\n", oldlocale, etemplate->
locale);
1739 new_locale = setlocale(LC_TIME, etemplate->
locale);
1740 if (new_locale ==
NULL) {
1755 ast_debug(2,
"MVM_COUNTER not found\n");
1757 ast_debug(2,
"MVM_COUNTER found - will use it with value %s\n", counter);
1769 ast_copy_string(oldlocale, setlocale(LC_TIME,
""),
sizeof(oldlocale));
1770 setlocale(LC_TIME, etemplate->
locale);
1778 goto notify_cleanup;
1783 "Event",
"MiniVoiceMail",
1784 "Action",
"SentNotification",
1785 "Counter", counter ?:
"");
1787 goto notify_cleanup;
1791 goto notify_cleanup;
1798 setlocale(LC_TIME, oldlocale);
1811 int res = 0, txtdes;
1813 int sound_duration = 0;
1816 char ext_context[256] =
"";
1825 domain = strchr(tmp,
'@');
1833 ast_log(
LOG_ERROR,
"Can't allocate temporary account for '%s@%s'\n", username, domain);
1839 if (strcmp(vmu->
domain,
"localhost"))
1840 snprintf(ext_context,
sizeof(ext_context),
"%s@%s", username, vmu->
domain);
1860 create_dirpath(tmpdir,
sizeof(tmpdir),
"0000_minivm_temp",
"mediafiles",
"");
1861 ast_debug(3,
"Creating temporary directory %s\n", tmpdir);
1865 snprintf(tmptxtfile,
sizeof(tmptxtfile),
"%s/XXXXXX", tmpdir);
1868 txtdes = mkstemp(tmptxtfile);
1887 ast_debug(2,
"Open file for metadata: %s\n", tmptxtfile);
1889 res =
play_record_review(chan,
NULL, tmptxtfile,
global_vmmaxmessage, fmt, 1, vmu, &duration, &sound_duration,
NULL,
options->record_gain);
1891 txt = fdopen(txtdes,
"w+");
1898 char logbuf[BUFSIZ];
1901 ast_strftime(timebuf,
sizeof(timebuf),
"%H:%M:%S", &tm);
1907 snprintf(logbuf,
sizeof(logbuf),
1909 "%s:%s:%s:%d:%s:%s:%s:%s:%d:%s:%s\n",
1922 fprintf(txt,
"%s", logbuf);
1939 ast_debug(1,
"The recorded media file is gone, so we should remove the .txt file too!\n");
1949 snprintf(timebuf,
sizeof(timebuf),
"%d", duration);
1961 ast_debug(2,
"-_-_- Deleted audio file after notification :: %s \n", tmptxtfile);
1977static void queue_mwi_event(
const char *channel_id,
const char *mbx,
const char *ctx,
int urgent,
int new,
int old)
2013 domain = strchr(tmp,
'@');
2019 ast_log(
LOG_ERROR,
"Need mailbox@context as argument. Sorry. Argument 0 %s\n", argv[0]);
2040 const char *
template =
"";
2041 const char *filename;
2043 const char *duration_string;
2056 domain = strchr(tmp,
'@');
2062 ast_log(
LOG_ERROR,
"Need username@domain as argument. Sorry. Argument 0 %s\n", argv[0]);
2068 ast_log(
LOG_WARNING,
"Could not allocate temporary memory for '%s@%s'\n", username, domain);
2118 memset(&leave_options, 0,
sizeof(leave_options));
2150 ast_log(
LOG_ERROR,
"Could not leave voicemail. The path is already locked.\n");
2174 char ext_context[256] =
"";
2176 char ecodes[16] =
"#";
2196 domain = strchr(tmp,
'@');
2202 ast_log(
LOG_ERROR,
"Need username@domain as argument. Sorry. Argument: %s\n", argv[0]);
2205 ast_debug(1,
"Trying to find configuration for user %s in domain %s\n", username, domain);
2217 if (strcmp(vmu->
domain,
"localhost"))
2218 snprintf(ext_context,
sizeof(ext_context),
"%s@%s", username, vmu->
domain);
2229 snprintf(prefile,
sizeof(prefile),
"%s%s/%s/unavail",
MVM_SPOOL_DIR, vmu->
domain, username);
2232 snprintf(tempfile,
sizeof(tempfile),
"%s%s/%s/temp",
MVM_SPOOL_DIR, vmu->
domain, username);
2234 ast_debug(2,
"Temporary message directory does not exist, using default (%s)\n", tempfile);
2237 ast_debug(2,
"Preparing to play message ...\n");
2244 strncat(ecodes,
"0",
sizeof(ecodes) - strlen(ecodes) - 1);
2249 strncat(ecodes,
"0",
sizeof(ecodes) - strlen(ecodes) - 1);
2257 strncat(ecodes,
"*",
sizeof(ecodes) - strlen(ecodes) - 1);
2261 strncat(ecodes,
"*",
sizeof(ecodes) - strlen(ecodes) - 1);
2270 ast_debug(2,
"%s doesn't exist, doing what we can\n", prefile);
2274 ast_debug(2,
"Hang up during prefile playback\n");
2306 }
else if (res ==
'0') {
2317 }
else if (res < 0) {
2337 char filename[BUFSIZ];
2348 ast_log(
LOG_ERROR,
"No filename given in application arguments or channel variable MVM_FILENAME\n");
2357 ast_debug(2,
"Can't delete file: %s\n", filename);
2360 ast_debug(2,
"Deleted voicemail file :: %s \n", filename);
2364 ast_debug(2,
"Filename does not exist: %s\n", filename);
2379 char *tmpptr =
NULL;
2390 ast_log(
LOG_ERROR,
"MinivmAccmess needs at least two arguments: account and option\n");
2398 ast_log(
LOG_ERROR,
"MinivmAccmess needs at least two arguments: account and option\n");
2401 if (!
error && strlen(argv[1]) > 1) {
2402 ast_log(
LOG_ERROR,
"MinivmAccmess can only handle one option at a time. Bad option string: %s\n", argv[1]);
2418 domain = strchr(tmp,
'@');
2424 ast_log(
LOG_ERROR,
"Need username@domain as argument. Sorry. Argument 0 %s\n", argv[0]);
2431 ast_log(
LOG_WARNING,
"Could not allocate temporary memory for '%s@%s'\n", username, domain);
2456 play_record_review(chan,
prompt, filename,
global_maxgreet,
default_vmformat, 0, vmu, &duration,
NULL,
NULL,
FALSE);
2458 ast_debug(1,
"Recorded new %s message in %s (duration %d)\n",
message, filename, duration);
2475 char accbuf[BUFSIZ];
2477 ast_debug(3,
"Creating %s account for [%s]\n", realtime ?
"realtime" :
"static",
name);
2481 domain = strchr(accbuf,
'@');
2491 ast_debug(3,
"Creating static account for user %s domain %s\n", username, domain);
2507 if (!strcasecmp(
var->name,
"serveremail")) {
2509 }
else if (!strcasecmp(
var->name,
"email")) {
2511 }
else if (!strcasecmp(
var->name,
"accountcode")) {
2513 }
else if (!strcasecmp(
var->name,
"pincode")) {
2515 }
else if (!strcasecmp(
var->name,
"domain")) {
2517 }
else if (!strcasecmp(
var->name,
"language")) {
2519 }
else if (!strcasecmp(
var->name,
"timezone")) {
2521 }
else if (!strcasecmp(
var->name,
"externnotify")) {
2523 }
else if (!strcasecmp(
var->name,
"etemplate")) {
2525 }
else if (!strcasecmp(
var->name,
"ptemplate")) {
2527 }
else if (!strcasecmp(
var->name,
"fullname")) {
2529 }
else if (!strcasecmp(
var->name,
"setvar")) {
2531 char varname[strlen(
var->value) + 1];
2534 strcpy(varname,
var->value);
2535 if ((varval = strchr(varname,
'='))) {
2543 }
else if (!strcasecmp(
var->name,
"pager")) {
2545 }
else if (!strcasecmp(
var->name,
"volgain")) {
2586 char *msg_format, *timezone_str;
2589 if (newzone ==
NULL)
2594 timezone_str =
strsep(&msg_format,
"|");
2616 char buf[BUFSIZ * 6];
2617 char readbuf[BUFSIZ];
2618 char filenamebuf[BUFSIZ];
2626 if (*filename ==
'/')
2631 if (!(fi = fopen(filenamebuf,
"r"))) {
2632 ast_log(
LOG_ERROR,
"Can't read message template from file: %s\n", filenamebuf);
2636 while (fgets(readbuf,
sizeof(readbuf), fi)) {
2638 if (writepos !=
buf) {
2643 writepos += strlen(readbuf) - 1;
2648 ast_debug(4,
"---> Size of allocation %d\n", (
int) strlen(
buf + 1) );
2649 ast_debug(4,
"---> Done reading message template : \n%s\n---- END message template--- \n", messagebody);
2657 char *tmpread, *tmpwrite;
2662 while ((tmpwrite = strchr(tmpread,
'\\'))) {
2663 int len = strlen(
"\n");
2664 switch (tmpwrite[1]) {
2666 memmove(tmpwrite +
len, tmpwrite + 2, strlen(tmpwrite + 2) + 1);
2670 memmove(tmpwrite +
len, tmpwrite + 2, strlen(tmpwrite + 2) + 1);
2674 ast_log(
LOG_NOTICE,
"Substitution routine does not support this character: %c\n", tmpwrite[1]);
2676 tmpread = tmpwrite +
len;
2688 if (!strcmp(
var->name,
"mailcmd")) {
2690 }
else if (!strcmp(
var->name,
"maxgreet")) {
2692 }
else if (!strcmp(
var->name,
"maxsilence")) {
2696 }
else if (!strcmp(
var->name,
"logfile")) {
2698 if(*(
var->value) ==
'/')
2703 }
else if (!strcmp(
var->name,
"externnotify")) {
2706 }
else if (!strcmp(
var->name,
"silencethreshold") || !strcmp(
var->name,
"silencetreshold")) {
2709 }
else if (!strcmp(
var->name,
"maxmessage")) {
2711 if (sscanf(
var->value,
"%30d", &x) == 1) {
2717 }
else if (!strcmp(
var->name,
"minmessage")) {
2719 if (sscanf(
var->value,
"%30d", &x) == 1) {
2722 ast_log(
LOG_WARNING,
"maxsilence should be less than minmessage or you may get empty messages\n");
2727 }
else if (!strcmp(
var->name,
"format")) {
2729 }
else if (!strcmp(
var->name,
"review")) {
2731 }
else if (!strcmp(
var->name,
"operator")) {
2764 ast_debug(2,
"Destroyed memory objects...\n");
2786 ast_log(
LOG_WARNING,
"Failed to load configuration file. Module activated with default settings.\n");
2791 ast_debug(2,
"Loaded configuration file, now parsing\n");
2797 ast_debug(3,
"Found configuration section [%s]\n", cat);
2798 if (!strcasecmp(cat,
"general")) {
2801 }
else if (!strncasecmp(cat,
"template-", 9)) {
2803 char *
name = cat + 9;
2809 if (!strcasecmp(cat,
"zonemessages")) {
2843 template->attachment =
TRUE;
2857 template->attachment =
FALSE;
2885#define HVLT_OUTPUT_FORMAT "%-15s %-10s %-10s %-15.15s %-50s\n"
2890 e->
command =
"minivm list templates";
2892 "Usage: minivm list templates\n"
2893 " Lists message templates for e-mail, paging and IM\n";
2904 ast_cli(
a->fd,
"There are no message templates defined\n");
2919 ast_cli(
a->fd,
"\n * Total: %d minivoicemail message templates\n", count);
2928 const char *domain =
"";
2933 wordlen = strlen(
word);
2935 if (!strncasecmp(
word, vmu->
domain, wordlen)) {
2936 if (domain && strcmp(domain, vmu->
domain) && ++which >
state)
2949#define HMSU_OUTPUT_FORMAT "%-23s %-15s %-15s %-10s %-10s %-50s\n"
2954 e->
command =
"minivm list accounts [for]";
2956 "Usage: minivm list accounts [for <domain>]\n"
2957 " Lists all mailboxes currently set up\n";
2963 if ((
a->argc < 3) || (
a->argc > 5) || (
a->argc == 4))
2965 if ((
a->argc == 5) && strcmp(
a->argv[3],
"for"))
2970 ast_cli(
a->fd,
"There are no voicemail users currently defined\n");
2978 if ((
a->argc == 3) || ((
a->argc == 5) && !strcmp(
a->argv[4], vmu->
domain))) {
2989 ast_cli(
a->fd,
"\n * Total: %d minivoicemail accounts\n", count);
2997#define HMSZ_OUTPUT_FORMAT "%-15s %-20s %-45s\n"
3002 e->
command =
"minivm list zones";
3004 "Usage: minivm list zones\n"
3005 " Lists zone message formats\n";
3011 if (
a->argc != e->
args)
3022 ast_cli(
a->fd,
"There are no voicemail zones currently defined\n");
3035 e->
command =
"minivm show settings";
3037 "Usage: minivm show settings\n"
3038 " Display Mini-Voicemail general settings\n";
3044 ast_cli(
a->fd,
"* Mini-Voicemail general settings\n");
3045 ast_cli(
a->fd,
" -------------------------------\n");
3071 e->
command =
"minivm show stats";
3073 "Usage: minivm show stats\n"
3074 " Display Mini-Voicemail counters\n";
3080 ast_cli(
a->fd,
"* Mini-Voicemail statistics\n");
3081 ast_cli(
a->fd,
" -------------------------\n");
3087 ast_cli(
a->fd,
" Received messages since last reset: <none>\n");
3092 ast_cli(
a->fd,
" Last received voicemail: %s\n",
buf);
3106 char *username, *domain, *colname;
3110 if ((colname = strchr(username,
':'))) {
3116 if ((domain = strchr(username,
'@'))) {
3121 ast_log(
LOG_ERROR,
"This function needs a username and a domain: username@domain\n");
3128 if (!strcasecmp(colname,
"hasaccount")) {
3130 }
else if (!strcasecmp(colname,
"fullname")) {
3132 }
else if (!strcasecmp(colname,
"email")) {
3137 }
else if (!strcasecmp(colname,
"pager")) {
3139 }
else if (!strcasecmp(colname,
"etemplate")) {
3144 }
else if (!strcasecmp(colname,
"language")) {
3146 }
else if (!strcasecmp(colname,
"timezone")) {
3148 }
else if (!strcasecmp(colname,
"ptemplate")) {
3153 }
else if (!strcasecmp(colname,
"accountcode")) {
3155 }
else if (!strcasecmp(colname,
"pincode")) {
3157 }
else if (!strcasecmp(colname,
"path")) {
3163 if (!strcmp(
var->name, colname)) {
3199 char filename[BUFSIZ];
3200 char readbuf[BUFSIZ];
3202 int old = 0, counter = 0;
3208 snprintf(filename,
sizeof(filename),
"%s/%s.counter", directory, countername);
3210 counterfile = fopen(filename,
"r");
3212 if(fgets(readbuf,
sizeof(readbuf), counterfile)) {
3213 ast_debug(3,
"Read this string from counter file: %s\n", readbuf);
3214 old = counter = atoi(readbuf);
3216 fclose(counterfile);
3222 ast_debug(2,
"MINIVM Counter %s/%s: Value %d\n", directory, countername, counter);
3236 counterfile = fopen(filename,
"w");
3238 ast_log(
LOG_ERROR,
"Could not open counter file for writing : %s - %s\n", filename, strerror(
errno));
3242 fprintf(counterfile,
"%d\n\n", counter);
3243 fclose(counterfile);
3245 ast_debug(2,
"MINIVM Counter %s/%s: Old value %d New value %d\n", directory, countername, old, counter);
3252 char *username, *domain, *countername;
3253 char userpath[BUFSIZ];
3260 if ((countername = strchr(username,
':'))) {
3261 *countername =
'\0';
3265 if ((domain = strchr(username,
'@'))) {
3277 ast_log(
LOG_ERROR,
"This function needs two arguments: Account:countername\n");
3289 ast_log(
LOG_ERROR,
"Minivm account does not exist: %s@%s\n", username, domain);
3298 snprintf(
buf,
len,
"%d", res);
3305 char *username, *domain, *countername, *operand;
3306 char userpath[BUFSIZ];
3312 change = atoi(
value);
3316 if ((countername = strchr(username,
':'))) {
3317 *countername =
'\0';
3320 if ((operand = strchr(countername,
':'))) {
3325 if ((domain = strchr(username,
'@'))) {
3343 ast_log(
LOG_ERROR,
"Writing to this function requires three arguments: Account:countername:operand\n");
3349 ast_log(
LOG_ERROR,
"Minivm account does not exist: %s@%s\n", username, domain);
3355 if (*operand ==
'i')
3357 else if (*operand ==
'd') {
3358 change = change * -1;
3360 }
else if (*operand ==
's')
3384 .
name =
"MINIVMCOUNTER",
3390 .
name =
"MINIVMACCOUNT",
3436 "Usage: minivm reload\n"
3437 " Reload mini-voicemail configuration and reset statistics\n";
3444 ast_cli(
a->fd,
"\n-- Mini voicemail re-configured \n");
static char * handle_minivm_show_zones(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Show a list of voicemail zones in the CLI.
static int global_maxsilence
#define DEFAULT_DATEFORMAT
static FILE * minivmlogfile
static int create_vmaccount(char *name, struct ast_variable *var, int realtime)
Append new mailbox to mailbox list from configuration file.
static void prep_email_sub_vars(struct ast_channel *channel, const struct minivm_account *vmu, const char *cidnum, const char *cidname, const char *dur, const char *date, const char *counter)
static void message_destroy_list(void)
static char * handle_minivm_show_users(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
CLI command to list voicemail accounts.
static int make_dir(char *dest, int len, const char *domain, const char *username, const char *folder)
static void free_user(struct minivm_account *vmu)
static int vm_delete(char *file)
#define HMSU_OUTPUT_FORMAT
static char default_vmformat[80]
static void queue_mwi_event(const char *channel_id, const char *mbx, const char *ctx, int urgent, int new, int old)
static int minivm_record_exec(struct ast_channel *chan, const char *data)
static int minivm_notify_exec(struct ast_channel *chan, const char *data)
static void populate_defaults(struct minivm_account *vmu)
static char * app_minivm_delete
static char * app_minivm_greet
static char * message_template_parse_filebody(const char *filename)
Read message template from file.
static int apply_general_options(struct ast_variable *var)
Apply general configuration options.
static struct ast_flags globalflags
static const char * ast_str_quote(struct ast_str **buf, ssize_t maxlen, const char *from)
static int minivm_account_func_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
${MINIVMACCOUNT()} Dialplan function - reads account data
static int check_mime(const char *str)
static struct ast_custom_function minivm_account_function
static void timezone_destroy_list(void)
Clear list of timezones.
static ast_mutex_t minivmloglock
static struct minivm_template * message_template_create(const char *name)
static int minivm_counter_func_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
${MINIVMCOUNTER()} Dialplan function - read counters
static int timezone_add(const char *zonename, const char *config)
Add time zone to memory list.
static int minivm_delete_exec(struct ast_channel *chan, const char *data)
static char * handle_minivm_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
CLI Show settings.
static int minivm_mwi_exec(struct ast_channel *chan, const char *data)
static char * message_template_parse_emailbody(const char *body)
Parse emailbody template from configuration file.
static int global_maxgreet
static int global_vmmaxmessage
static char * handle_minivm_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Reload configuration.
static void message_template_free(struct minivm_template *template)
static int vm_lock_path(const char *path)
lock directory
static char * handle_minivm_list_templates(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
CLI routine for listing templates.
static int minivm_accmess_exec(struct ast_channel *chan, const char *data)
Record specific messages for voicemail account.
#define HVLT_OUTPUT_FORMAT
static struct minivm_account * mvm_user_alloc(void)
static int message_template_build(const char *name, struct ast_variable *var)
static char global_mailcmd[160]
static void free_zone(struct minivm_zone *z)
Free Mini Voicemail timezone.
static const struct ast_app_option minivm_accmess_options[128]
static int notify_new_message(struct ast_channel *chan, const char *templatename, struct minivm_account *vmu, const char *filename, long duration, const char *format, char *cidnum, char *cidname)
#define SENDMAIL
Default mail command to mail voicemail. Change it with the mailcmd= command in voicemail....
static void vmaccounts_destroy_list(void)
static int play_record_review(struct ast_channel *chan, char *playfile, char *recordfile, int maxtime, char *fmt, int outsidecaller, struct minivm_account *vmu, int *duration, int *sound_duration, const char *unlockdir, signed char record_gain)
static int check_dirpath(char *dest, int len, char *domain, char *username, char *folder)
static int global_silencethreshold
static char * app_minivm_notify
static int global_saydurationminfo
#define HMSZ_OUTPUT_FORMAT
static struct minivm_template * message_template_find(const char *name)
static int invent_message(struct ast_channel *chan, char *domain, char *username, int busy, char *ecodes)
static double global_volgain
static int leave_voicemail(struct ast_channel *chan, char *username, struct leave_vm_options *options)
static char MVM_SPOOL_DIR[PATH_MAX]
static struct ast_cli_entry cli_minivm[]
CLI commands for Mini-voicemail.
static char * app_minivm_record
mvm_messagetype
Message types for notification.
static char * app_minivm_accmess
static int load_module(void)
Load mini voicemail module.
static ast_mutex_t minivmlock
static int create_dirpath(char *dest, int len, char *domain, char *username, char *folder)
static int sendmail(struct minivm_template *template, struct minivm_account *vmu, char *cidnum, char *cidname, const char *filename, char *format, int duration, int attach_user_voicemail, enum mvm_messagetype type, const char *counter)
static char global_externnotify[160]
static const struct ast_app_option minivm_app_options[128]
static char * handle_minivm_show_stats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Show stats.
static void run_externnotify(struct ast_channel *chan, struct minivm_account *vmu)
Run external notification for voicemail message.
static int minivm_greet_exec(struct ast_channel *chan, const char *data)
static int unload_module(void)
Unload mini voicemail module.
static int load_config(int reload)
Load minivoicemail configuration.
static int reload(void)
Reload mini voicemail module.
static const char * ast_str_encode_mime(struct ast_str **end, ssize_t maxlen, const char *charset, const char *start, size_t preamble, size_t postamble)
static int global_vmminmessage
static struct ast_custom_function minivm_counter_function
static struct minivm_account * find_account(const char *domain, const char *username, int createtemp)
static char global_logfile[PATH_MAX]
static int minivm_counter_func_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
${MINIVMCOUNTER()} Dialplan function - changes counter data
static int get_date(char *s, int len)
static int access_counter_file(char *directory, char *countername, int value, int operand)
Access counter file, lock directory, read and possibly write it again changed.
static struct minivm_account * find_user_realtime(const char *domain, const char *username)
static char * app_minivm_mwi
static char * complete_minivm_show_users(const char *line, const char *word, int pos, int state)
static struct minivm_stats global_stats
Statistics for voicemail.
char * strsep(char **str, const char *delims)
char * mkdtemp(char *template_s)
static struct ast_str * prompt
Asterisk main include file. File version handling, generic pbx functions.
#define ast_strdup(str)
A wrapper for strdup()
#define ast_strdupa(s)
duplicate a string in memory from the stack
#define ast_calloc(num, len)
A wrapper for calloc()
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
char * ast_callerid_merge(char *buf, int bufsiz, const char *name, const char *num, const char *unknown)
static const char config[]
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)
#define ast_channel_lock(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)
#define AST_MAX_ACCOUNT_CODE
#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_answer(struct ast_channel *chan)
Answer a channel.
const char * ast_channel_exten(const struct ast_channel *chan)
#define ast_channel_unlock(chan)
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.
Convenient Signal Processing routines.
int ast_dsp_get_threshold_from_settings(enum threshold which)
Get silence threshold from dsp.conf.
Generic File Format Support. Should be included by clients of the file handling routines....
int ast_stopstream(struct ast_channel *c)
Stops a stream.
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.
int ast_fileexists(const char *filename, const char *fmt, const char *preflang)
Checks for the existence of a given file.
int ast_filedelete(const char *filename, const char *fmt)
Deletes a file.
int ast_waitstream(struct ast_channel *c, const char *breakon)
Waits for a stream to stop or digit to be pressed.
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
struct ast_channel_snapshot * ast_channel_snapshot_get_latest(const char *uniqueid)
Obtain the latest ast_channel_snapshot from the Stasis Message Bus API cache. This is an ao2 object,...
Application convenience functions, designed to give consistent look and feel to Asterisk apps.
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_safe_execvp(int dualfork, const char *file, char *const argv[])
Safely spawn an external program while closing file descriptors.
#define AST_APP_OPTIONS(holder, options...)
Declares an array of options for an application.
#define ast_app_separate_args(a, b, c, d)
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_safe_system(const char *s)
Safely spawn an OS shell command while closing file descriptors.
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.
@ AST_RECORD_IF_EXISTS_OVERWRITE
#define AST_APP_OPTION(option, flagno)
Declares an application option that does not accept an argument.
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.
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.
@ CONFIG_FLAG_FILEUNCHANGED
#define ast_variable_new(name, value, filename)
#define CONFIG_STATUS_FILEUNCHANGED
#define CONFIG_STATUS_FILEINVALID
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)
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)
#define AST_OPTION_RXGAIN
#define DEBUG_ATLEAST(level)
#define ast_debug(level,...)
Log a DEBUG message.
#define ast_verb(level,...)
Asterisk JSON abstraction layer.
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.
A set of macros to manage forward-linked lists.
#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_ENTRY(type)
Declare a forward link structure inside a list entry.
#define AST_LIST_LOCK(head)
Locks a list.
#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.
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...
Asterisk locking-related definitions:
#define ast_mutex_unlock(a)
#define ast_mutex_lock(a)
#define AST_MUTEX_DEFINE_STATIC(mutex)
Asterisk module definitions.
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
@ AST_MODULE_SUPPORT_EXTENDED
#define ASTERISK_GPL_KEY
The text the key() function should return.
int ast_unregister_application(const char *app)
Unregister an application.
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
struct stasis_message_type * ast_mwi_vm_app_type(void)
Get the Stasis Message Bus API message type for voicemail application specific messages.
#define ast_publish_mwi_state_channel(mailbox, context, new_msgs, old_msgs, channel_id)
Publish a MWI state update associated with some channel.
struct stasis_message * ast_mwi_blob_create(struct ast_mwi_state *mwi_state, struct stasis_message_type *message_type, struct ast_json *blob)
Creates a ast_mwi_blob message.
struct stasis_topic * ast_mwi_topic(const char *uniqueid)
Get the Stasis Message Bus API topic for MWI messages on a unique ID.
struct ast_mwi_state * ast_mwi_create(const char *mailbox, const char *context)
Create a ast_mwi_state object.
Asterisk file paths, configured in asterisk.conf.
const char * ast_config_AST_CONFIG_DIR
const char * ast_config_AST_SPOOL_DIR
const char * ast_config_AST_LOG_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_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_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
Say numbers and dates (maybe words one day too)
int ast_say_digit_str(struct ast_channel *chan, const char *num, const char *ints, const char *lang)
says digits of a string
Stasis Message Bus API. See Stasis Message Bus API for detailed documentation.
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic's subscribers.
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...
static force_inline int attribute_pure ast_strlen_zero(const char *s)
#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.
Main Channel structure associated with a channel.
descriptor for a cli entry.
int args
This gets set in ast_cli_register()
Data structure associated with a custom dialplan function.
Structure used to handle boolean flags.
Abstract JSON element (object, array, string, int, ...).
The structure that contains MWI state.
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)
Support for dynamic strings.
Structure for variables, used for configurations and for channel variables.
struct ast_variable * next
structure for queuing ARI channel variable setting
Options for leaving voicemail with the voicemail() application.
The list of e-mail templates.
struct ast_variable * chanvars
char username[AST_MAX_CONTEXT]
struct minivm_account::@38 list
char language[MAX_LANGUAGE]
char accountcode[AST_MAX_ACCOUNT_CODE]
char domain[AST_MAX_CONTEXT]
Structure for gathering statistics.
struct timeval lastreceived
struct minivm_template::@39 list
struct minivm_zone::@40 list
The list of e-mail time zones.
Time-related functions and macros.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
int error(const char *format,...)
#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.
#define ast_set2_flag(p, value, 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.