531#define MVM_REVIEW (1 << 0)
532#define MVM_OPERATOR (1 << 1)
533#define MVM_REALTIME (1 << 2)
534#define MVM_SVMAIL (1 << 3)
535#define MVM_ENVELOPE (1 << 4)
536#define MVM_PBXSKIP (1 << 9)
537#define MVM_ALLOCED (1 << 13)
541#define SENDMAIL "/usr/sbin/sendmail -t"
543#define SOUND_INTRO "vm-intro"
546#define MAX_DATETIME_FORMAT 512
547#define MAX_NUM_CID_CONTEXTS 10
549#define ERROR_LOCK_PATH -100
550#define VOICEMAIL_DIR_MODE 0700
552#define VOICEMAIL_CONFIG "minivm.conf"
553#define ASTERISK_USERNAME "asterisk"
706#define DEFAULT_DATEFORMAT "%A, %B %d, %Y at %r"
707#define DEFAULT_CHARSET "ISO-8859-1"
730 ast_copy_string(template->subject,
"New message in mailbox ${MVM_USERNAME}@${MVM_DOMAIN}",
sizeof(template->subject));
731 template->attachment =
TRUE;
760 ast_debug(3,
"Configuring template option %s = \"%s\" for template %s\n",
var->name,
var->value,
name);
761 if (!strcasecmp(
var->name,
"fromaddress")) {
763 }
else if (!strcasecmp(
var->name,
"fromemail")) {
765 }
else if (!strcasecmp(
var->name,
"subject")) {
767 }
else if (!strcasecmp(
var->name,
"locale")) {
769 }
else if (!strcasecmp(
var->name,
"attachmedia")) {
771 }
else if (!strcasecmp(
var->name,
"dateformat")) {
773 }
else if (!strcasecmp(
var->name,
"charset")) {
775 }
else if (!strcasecmp(
var->name,
"templatefile")) {
779 if (!template->body) {
783 }
else if (!strcasecmp(
var->name,
"messagebody")) {
787 if (!template->body) {
820 if (!strcasecmp(this->name,
name)) {
943 ast_debug(3,
"Looking for voicemail user %s in domain %s\n", username, domain);
948 if (!strcasecmp(domain, cur->domain) && !strcasecmp(username, cur->username))
954 ast_debug(3,
"Found account for %s@%s\n", username, domain);
960 if (createtemp && !vmu) {
967 ast_debug(1,
"Created temporary account\n");
999 snprintf(
name,
sizeof(
name),
"%s@%s", username, domain);
1014 if (*
str > 126 || *
str < 32 || strchr(
"()<>@,:;/\"[]?.=", *
str)) {
1043 int first_section = 1;
1047 for (; *start; start++) {
1048 int need_encoding = 0;
1049 if (*start < 33 || *start > 126 || strchr(
"()<>@,:;/\"[]?.=_", *start)) {
1061 if (need_encoding && *start ==
' ') {
1063 }
else if (need_encoding) {
1087 for (ptr = from; *ptr; ptr++) {
1088 if (*ptr ==
'"' || *ptr ==
'\\') {
1107 char email[256] =
"";
1113 char tmp[80] =
"/tmp/astmail-XXXXXX";
1115 char sox_gain_tmpdir[
PATH_MAX] =
"";
1116 char *file_to_delete =
NULL, *dir_to_delete =
NULL;
1125 if (!str1 || !str2) {
1145 if (!strcmp(format,
"wav49"))
1152 ast_copy_string(sox_gain_tmpdir,
"/tmp/minivm-gain-XXXXXX",
sizeof(sox_gain_tmpdir));
1153 ast_debug(3,
"sox_gain_tmpdir: %s\n", sox_gain_tmpdir);
1154 if (!
mkdtemp(sox_gain_tmpdir)) {
1158 snprintf(fname,
sizeof(fname),
"%s/output.%s", sox_gain_tmpdir, format);
1159 snprintf(sox_gain_cmd,
sizeof(sox_gain_cmd),
"sox -v %.4f %s.%s %s", vmu->
volgain, filename, format, fname);
1161 ast_debug(3,
"VOLGAIN: Stored at: %s.%s - Level: %.4f - Mailbox: %s\n", filename, format, vmu->
volgain, vmu->
username);
1164 file_to_delete = fname;
1165 dir_to_delete = sox_gain_tmpdir;
1167 snprintf(fname,
sizeof(fname),
"%s.%s", filename, format);
1170 if (template->attachment)
1171 ast_debug(1,
"Attaching file '%s', format '%s', uservm is '%d'\n", fname, format, attach_user_voicemail);
1177 p = fdopen(pfd,
"w");
1182 ast_debug(1,
"Opening temp file for e-mail: %s\n",
tmp);
1194 snprintf(dur,
sizeof(dur),
"%d:%02d", duration / 60, duration % 60);
1211 ast_strftime(date,
sizeof(date),
"%a, %d %b %Y %H:%M:%S %z", &tm);
1214 fprintf(p,
"Date: %s\n", date);
1217 ast_strftime(date,
sizeof(date), template->dateformat, &tm);
1231 fromemail =
"asterisk";
1233 if (strchr(fromemail,
'@'))
1237 gethostname(host,
sizeof(host)-1);
1238 snprintf(who,
sizeof(who),
"%s@%s", fromemail, host);
1242 fprintf(p,
"From: Asterisk PBX <%s>\n", who);
1252 fprintf(p,
"%s %s\n", first_line ?
"From:" :
"",
ast_str_buffer(str2));
1257 fprintf(p,
"%s %s <%s>\n", first_line ?
"From:" :
"",
ast_str_buffer(str2), who);
1263 fprintf(p,
"Message-ID: <Asterisk-%u-%s-%d-%s>\n", (
unsigned int)
ast_random(), vmu->
username, (
int)getpid(), who);
1277 fprintf(p,
"%s %s\n", first_line ?
"To:" :
"",
ast_str_buffer(str2));
1295 fprintf(p,
"%s %s\n", first_line ?
"Subject:" :
"",
ast_str_buffer(str2));
1300 fprintf(p,
"%s %s\n", first_line ?
"Subject:" :
"",
ast_str_buffer(str2));
1305 fprintf(p,
"Subject: New message in mailbox %s@%s\n", vmu->
username, vmu->
domain);
1306 ast_debug(1,
"Using default subject for this email \n");
1310 fprintf(p,
"X-Asterisk-debug: template %s user account %s@%s\n", template->name, vmu->
username, vmu->
domain);
1311 fprintf(p,
"MIME-Version: 1.0\n");
1314 snprintf(bound,
sizeof(bound),
"voicemail_%s%d%u", vmu->
username, (
int)getpid(), (
unsigned int)
ast_random());
1316 fprintf(p,
"Content-Type: multipart/mixed; boundary=\"%s\"\n\n\n", bound);
1318 fprintf(p,
"--%s\n", bound);
1319 fprintf(p,
"Content-Type: text/plain; charset=%s\nContent-Transfer-Encoding: 8bit\n\n", template->charset);
1325 fprintf(p,
"Dear %s:\n\n\tJust wanted to let you know you were just left a %s long message \n"
1326 "in mailbox %s from %s, on %s so you might\n"
1327 "want to check it when you get a chance. Thanks!\n\n\t\t\t\t--Asterisk\n\n", vmu->
fullname,
1328 dur, vmu->
username, (cidname ? cidname : (cidnum ? cidnum :
"an unknown caller")), date);
1329 ast_debug(3,
"Using default message body (no template)\n-----\n");
1332 if (template->attachment) {
1333 char *ctype =
"audio/x-";
1334 ast_debug(3,
"Attaching file to message: %s\n", fname);
1335 if (!strcasecmp(format,
"ogg"))
1336 ctype =
"application/";
1338 fprintf(p,
"--%s\n", bound);
1339 fprintf(p,
"Content-Type: %s%s; name=\"voicemailmsg.%s\"\n", ctype, format, format);
1340 fprintf(p,
"Content-Transfer-Encoding: base64\n");
1341 fprintf(p,
"Content-Description: Voicemail sound attachment.\n");
1342 fprintf(p,
"Content-Disposition: attachment; filename=\"voicemail%s.%s\"\n\n", counter ? counter :
"", format);
1345 fprintf(p,
"\n\n--%s--\n.\n", bound);
1351 if (file_to_delete && dir_to_delete) {
1354 res = snprintf(mail_cmd_buffer,
sizeof(mail_cmd_buffer),
1355 "( %s < %s ; rm -f %s %s ; rmdir %s ) &",
1358 res = snprintf(mail_cmd_buffer,
sizeof(mail_cmd_buffer),
1359 "( %s < %s ; rm -f %s ) &",
1363 if (res <
sizeof(mail_cmd_buffer)) {
1364 file_to_delete = dir_to_delete =
NULL;
1372 ast_debug(1,
"Sent message to %s with command '%s'%s\n", vmu->
email,
global_mailcmd, template->attachment ?
" - (media attachment)" :
"");
1373 ast_debug(3,
"Actual command used: %s\n", mail_cmd_buffer);
1378 if (file_to_delete) {
1379 unlink(file_to_delete);
1382 if (dir_to_delete) {
1383 rmdir(dir_to_delete);
1391static int make_dir(
char *dest,
int len,
const char *domain,
const char *username,
const char *folder)
1407 struct stat filestat;
1408 make_dir(dest,
len, domain, username, folder ? folder :
"");
1409 if (stat(dest, &filestat)== -1)
1432 ast_debug(2,
"Creating directory for %s@%s folder %s : %s\n", username, domain, folder, dest);
1445 ast_debug(2,
"Still preparing to play message ...\n");
1447 snprintf(fn,
sizeof(fn),
"%s%s/%s/greet",
MVM_SPOOL_DIR, domain, username);
1457 int numericusername = 1;
1460 ast_debug(2,
"No personal prompts. Using default prompt set for language\n");
1463 ast_debug(2,
"Numeric? Checking %c\n", *i);
1465 numericusername =
FALSE;
1471 if (numericusername) {
1512 int outsidecaller,
struct minivm_account *vmu,
int *duration,
int *sound_duration,
const char *unlockdir,
1513 signed char record_gain)
1516 int max_attempts = 3;
1519 int message_exists = 0;
1520 signed char zero_gain = 0;
1521 char *acceptdtmf =
"#";
1522 char *canceldtmf =
"";
1527 if (duration ==
NULL) {
1534 while ((cmd >= 0) && (cmd !=
't')) {
1537 ast_verb(3,
"Saving message as is\n");
1543 ast_verb(3,
"Reviewing the message\n");
1551 ast_verb(3,
"Re-recording the message\n");
1553 ast_verb(3,
"Recording the message\n");
1554 if (recorded && outsidecaller)
1562 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);
1569 else if (cmd ==
'*')
1592 if (message_exists || recorded) {
1612 if (message_exists) {
1630 if (attempts > max_attempts) {
1646 char *argv[5] = {
NULL };
1655 snprintf(fquser,
sizeof(fquser),
"%s@%s", vmu->
username, vmu->
domain);
1660 argv[idx++] = fquser;
1671 ast_debug(1,
"Executing: %s %s %s %s\n",
1672 argv[0], argv[1], argv[2] ?:
"", argv[3] ?:
"");
1685 char *messageformat;
1687 char oldlocale[100];
1688 const char *counter;
1711 ast_debug(2,
"Changing locale from %s to %s\n", oldlocale, etemplate->
locale);
1712 new_locale = setlocale(LC_TIME, etemplate->
locale);
1713 if (new_locale ==
NULL) {
1728 ast_debug(2,
"MVM_COUNTER not found\n");
1730 ast_debug(2,
"MVM_COUNTER found - will use it with value %s\n", counter);
1742 ast_copy_string(oldlocale, setlocale(LC_TIME,
""),
sizeof(oldlocale));
1743 setlocale(LC_TIME, etemplate->
locale);
1751 goto notify_cleanup;
1756 "Event",
"MiniVoiceMail",
1757 "Action",
"SentNotification",
1758 "Counter", counter ?:
"");
1760 goto notify_cleanup;
1764 goto notify_cleanup;
1771 setlocale(LC_TIME, oldlocale);
1784 int res = 0, txtdes;
1786 int sound_duration = 0;
1789 char ext_context[256] =
"";
1798 domain = strchr(
tmp,
'@');
1806 ast_log(
LOG_ERROR,
"Can't allocate temporary account for '%s@%s'\n", username, domain);
1812 if (strcmp(vmu->
domain,
"localhost"))
1813 snprintf(ext_context,
sizeof(ext_context),
"%s@%s", username, vmu->
domain);
1833 create_dirpath(tmpdir,
sizeof(tmpdir),
"0000_minivm_temp",
"mediafiles",
"");
1834 ast_debug(3,
"Creating temporary directory %s\n", tmpdir);
1838 snprintf(tmptxtfile,
sizeof(tmptxtfile),
"%s/XXXXXX", tmpdir);
1841 txtdes = mkstemp(tmptxtfile);
1860 ast_debug(2,
"Open file for metadata: %s\n", tmptxtfile);
1862 res =
play_record_review(chan,
NULL, tmptxtfile,
global_vmmaxmessage, fmt, 1, vmu, &duration, &sound_duration,
NULL,
options->record_gain);
1864 txt = fdopen(txtdes,
"w+");
1871 char logbuf[BUFSIZ];
1874 ast_strftime(timebuf,
sizeof(timebuf),
"%H:%M:%S", &tm);
1880 snprintf(logbuf,
sizeof(logbuf),
1882 "%s:%s:%s:%d:%s:%s:%s:%s:%d:%s:%s\n",
1895 fprintf(txt,
"%s", logbuf);
1912 ast_debug(1,
"The recorded media file is gone, so we should remove the .txt file too!\n");
1922 snprintf(timebuf,
sizeof(timebuf),
"%d", duration);
1934 ast_debug(2,
"-_-_- Deleted audio file after notification :: %s \n", tmptxtfile);
1950static void queue_mwi_event(
const char *channel_id,
const char *mbx,
const char *ctx,
int urgent,
int new,
int old)
1986 domain = strchr(
tmp,
'@');
1992 ast_log(
LOG_ERROR,
"Need mailbox@context as argument. Sorry. Argument 0 %s\n", argv[0]);
2013 const char *
template =
"";
2014 const char *filename;
2016 const char *duration_string;
2029 domain = strchr(
tmp,
'@');
2035 ast_log(
LOG_ERROR,
"Need username@domain as argument. Sorry. Argument 0 %s\n", argv[0]);
2041 ast_log(
LOG_WARNING,
"Could not allocate temporary memory for '%s@%s'\n", username, domain);
2091 memset(&leave_options, 0,
sizeof(leave_options));
2123 ast_log(
LOG_ERROR,
"Could not leave voicemail. The path is already locked.\n");
2147 char ext_context[256] =
"";
2149 char ecodes[16] =
"#";
2169 domain = strchr(
tmp,
'@');
2175 ast_log(
LOG_ERROR,
"Need username@domain as argument. Sorry. Argument: %s\n", argv[0]);
2178 ast_debug(1,
"Trying to find configuration for user %s in domain %s\n", username, domain);
2190 if (strcmp(vmu->
domain,
"localhost"))
2191 snprintf(ext_context,
sizeof(ext_context),
"%s@%s", username, vmu->
domain);
2202 snprintf(prefile,
sizeof(prefile),
"%s%s/%s/unavail",
MVM_SPOOL_DIR, vmu->
domain, username);
2205 snprintf(tempfile,
sizeof(tempfile),
"%s%s/%s/temp",
MVM_SPOOL_DIR, vmu->
domain, username);
2207 ast_debug(2,
"Temporary message directory does not exist, using default (%s)\n", tempfile);
2210 ast_debug(2,
"Preparing to play message ...\n");
2217 strncat(ecodes,
"0",
sizeof(ecodes) - strlen(ecodes) - 1);
2222 strncat(ecodes,
"0",
sizeof(ecodes) - strlen(ecodes) - 1);
2230 strncat(ecodes,
"*",
sizeof(ecodes) - strlen(ecodes) - 1);
2234 strncat(ecodes,
"*",
sizeof(ecodes) - strlen(ecodes) - 1);
2243 ast_debug(2,
"%s doesn't exist, doing what we can\n", prefile);
2247 ast_debug(2,
"Hang up during prefile playback\n");
2279 }
else if (res ==
'0') {
2290 }
else if (res < 0) {
2310 char filename[BUFSIZ];
2321 ast_log(
LOG_ERROR,
"No filename given in application arguments or channel variable MVM_FILENAME\n");
2330 ast_debug(2,
"Can't delete file: %s\n", filename);
2333 ast_debug(2,
"Deleted voicemail file :: %s \n", filename);
2337 ast_debug(2,
"Filename does not exist: %s\n", filename);
2352 char *tmpptr =
NULL;
2363 ast_log(
LOG_ERROR,
"MinivmAccmess needs at least two arguments: account and option\n");
2371 ast_log(
LOG_ERROR,
"MinivmAccmess needs at least two arguments: account and option\n");
2374 if (!
error && strlen(argv[1]) > 1) {
2375 ast_log(
LOG_ERROR,
"MinivmAccmess can only handle one option at a time. Bad option string: %s\n", argv[1]);
2391 domain = strchr(
tmp,
'@');
2397 ast_log(
LOG_ERROR,
"Need username@domain as argument. Sorry. Argument 0 %s\n", argv[0]);
2404 ast_log(
LOG_WARNING,
"Could not allocate temporary memory for '%s@%s'\n", username, domain);
2429 play_record_review(chan,
prompt, filename,
global_maxgreet,
default_vmformat, 0, vmu, &duration,
NULL,
NULL,
FALSE);
2431 ast_debug(1,
"Recorded new %s message in %s (duration %d)\n",
message, filename, duration);
2448 char accbuf[BUFSIZ];
2450 ast_debug(3,
"Creating %s account for [%s]\n", realtime ?
"realtime" :
"static",
name);
2454 domain = strchr(accbuf,
'@');
2464 ast_debug(3,
"Creating static account for user %s domain %s\n", username, domain);
2480 if (!strcasecmp(
var->name,
"serveremail")) {
2482 }
else if (!strcasecmp(
var->name,
"email")) {
2484 }
else if (!strcasecmp(
var->name,
"accountcode")) {
2486 }
else if (!strcasecmp(
var->name,
"pincode")) {
2488 }
else if (!strcasecmp(
var->name,
"domain")) {
2490 }
else if (!strcasecmp(
var->name,
"language")) {
2492 }
else if (!strcasecmp(
var->name,
"timezone")) {
2494 }
else if (!strcasecmp(
var->name,
"externnotify")) {
2496 }
else if (!strcasecmp(
var->name,
"etemplate")) {
2498 }
else if (!strcasecmp(
var->name,
"ptemplate")) {
2500 }
else if (!strcasecmp(
var->name,
"fullname")) {
2502 }
else if (!strcasecmp(
var->name,
"setvar")) {
2504 char varname[strlen(
var->value) + 1];
2507 strcpy(varname,
var->value);
2508 if ((varval = strchr(varname,
'='))) {
2516 }
else if (!strcasecmp(
var->name,
"pager")) {
2518 }
else if (!strcasecmp(
var->name,
"volgain")) {
2559 char *msg_format, *timezone_str;
2562 if (newzone ==
NULL)
2567 timezone_str =
strsep(&msg_format,
"|");
2589 char buf[BUFSIZ * 6];
2590 char readbuf[BUFSIZ];
2591 char filenamebuf[BUFSIZ];
2599 if (*filename ==
'/')
2604 if (!(fi = fopen(filenamebuf,
"r"))) {
2605 ast_log(
LOG_ERROR,
"Can't read message template from file: %s\n", filenamebuf);
2609 while (fgets(readbuf,
sizeof(readbuf), fi)) {
2611 if (writepos !=
buf) {
2616 writepos += strlen(readbuf) - 1;
2621 ast_debug(4,
"---> Size of allocation %d\n", (
int) strlen(
buf + 1) );
2622 ast_debug(4,
"---> Done reading message template : \n%s\n---- END message template--- \n", messagebody);
2630 char *tmpread, *tmpwrite;
2635 while ((tmpwrite = strchr(tmpread,
'\\'))) {
2636 int len = strlen(
"\n");
2637 switch (tmpwrite[1]) {
2639 memmove(tmpwrite +
len, tmpwrite + 2, strlen(tmpwrite + 2) + 1);
2643 memmove(tmpwrite +
len, tmpwrite + 2, strlen(tmpwrite + 2) + 1);
2647 ast_log(
LOG_NOTICE,
"Substitution routine does not support this character: %c\n", tmpwrite[1]);
2649 tmpread = tmpwrite +
len;
2661 if (!strcmp(
var->name,
"mailcmd")) {
2663 }
else if (!strcmp(
var->name,
"maxgreet")) {
2665 }
else if (!strcmp(
var->name,
"maxsilence")) {
2669 }
else if (!strcmp(
var->name,
"logfile")) {
2671 if(*(
var->value) ==
'/')
2676 }
else if (!strcmp(
var->name,
"externnotify")) {
2679 }
else if (!strcmp(
var->name,
"silencethreshold") || !strcmp(
var->name,
"silencetreshold")) {
2682 }
else if (!strcmp(
var->name,
"maxmessage")) {
2684 if (sscanf(
var->value,
"%30d", &x) == 1) {
2690 }
else if (!strcmp(
var->name,
"minmessage")) {
2692 if (sscanf(
var->value,
"%30d", &x) == 1) {
2695 ast_log(
LOG_WARNING,
"maxsilence should be less than minmessage or you may get empty messages\n");
2700 }
else if (!strcmp(
var->name,
"format")) {
2702 }
else if (!strcmp(
var->name,
"review")) {
2704 }
else if (!strcmp(
var->name,
"operator")) {
2737 ast_debug(2,
"Destroyed memory objects...\n");
2759 ast_log(
LOG_WARNING,
"Failed to load configuration file. Module activated with default settings.\n");
2764 ast_debug(2,
"Loaded configuration file, now parsing\n");
2770 ast_debug(3,
"Found configuration section [%s]\n", cat);
2771 if (!strcasecmp(cat,
"general")) {
2774 }
else if (!strncasecmp(cat,
"template-", 9)) {
2776 char *
name = cat + 9;
2782 if (!strcasecmp(cat,
"zonemessages")) {
2816 template->attachment =
TRUE;
2830 template->attachment =
FALSE;
2858#define HVLT_OUTPUT_FORMAT "%-15s %-10s %-10s %-15.15s %-50s\n"
2863 e->
command =
"minivm list templates";
2865 "Usage: minivm list templates\n"
2866 " Lists message templates for e-mail, paging and IM\n";
2877 ast_cli(
a->fd,
"There are no message templates defined\n");
2892 ast_cli(
a->fd,
"\n * Total: %d minivoicemail message templates\n", count);
2901 const char *domain =
"";
2906 wordlen = strlen(
word);
2908 if (!strncasecmp(
word, vmu->
domain, wordlen)) {
2909 if (domain && strcmp(domain, vmu->
domain) && ++which >
state)
2922#define HMSU_OUTPUT_FORMAT "%-23s %-15s %-15s %-10s %-10s %-50s\n"
2927 e->
command =
"minivm list accounts [for]";
2929 "Usage: minivm list accounts [for <domain>]\n"
2930 " Lists all mailboxes currently set up\n";
2936 if ((
a->argc < 3) || (
a->argc > 5) || (
a->argc == 4))
2938 if ((
a->argc == 5) && strcmp(
a->argv[3],
"for"))
2943 ast_cli(
a->fd,
"There are no voicemail users currently defined\n");
2951 if ((
a->argc == 3) || ((
a->argc == 5) && !strcmp(
a->argv[4], vmu->
domain))) {
2962 ast_cli(
a->fd,
"\n * Total: %d minivoicemail accounts\n", count);
2970#define HMSZ_OUTPUT_FORMAT "%-15s %-20s %-45s\n"
2975 e->
command =
"minivm list zones";
2977 "Usage: minivm list zones\n"
2978 " Lists zone message formats\n";
2984 if (
a->argc != e->
args)
2995 ast_cli(
a->fd,
"There are no voicemail zones currently defined\n");
3008 e->
command =
"minivm show settings";
3010 "Usage: minivm show settings\n"
3011 " Display Mini-Voicemail general settings\n";
3017 ast_cli(
a->fd,
"* Mini-Voicemail general settings\n");
3018 ast_cli(
a->fd,
" -------------------------------\n");
3044 e->
command =
"minivm show stats";
3046 "Usage: minivm show stats\n"
3047 " Display Mini-Voicemail counters\n";
3053 ast_cli(
a->fd,
"* Mini-Voicemail statistics\n");
3054 ast_cli(
a->fd,
" -------------------------\n");
3060 ast_cli(
a->fd,
" Received messages since last reset: <none>\n");
3065 ast_cli(
a->fd,
" Last received voicemail: %s\n",
buf);
3079 char *username, *domain, *colname;
3083 if ((colname = strchr(username,
':'))) {
3089 if ((domain = strchr(username,
'@'))) {
3094 ast_log(
LOG_ERROR,
"This function needs a username and a domain: username@domain\n");
3101 if (!strcasecmp(colname,
"hasaccount")) {
3103 }
else if (!strcasecmp(colname,
"fullname")) {
3105 }
else if (!strcasecmp(colname,
"email")) {
3110 }
else if (!strcasecmp(colname,
"pager")) {
3112 }
else if (!strcasecmp(colname,
"etemplate")) {
3117 }
else if (!strcasecmp(colname,
"language")) {
3119 }
else if (!strcasecmp(colname,
"timezone")) {
3121 }
else if (!strcasecmp(colname,
"ptemplate")) {
3126 }
else if (!strcasecmp(colname,
"accountcode")) {
3128 }
else if (!strcasecmp(colname,
"pincode")) {
3130 }
else if (!strcasecmp(colname,
"path")) {
3136 if (!strcmp(
var->name, colname)) {
3172 char filename[BUFSIZ];
3173 char readbuf[BUFSIZ];
3175 int old = 0, counter = 0;
3181 snprintf(filename,
sizeof(filename),
"%s/%s.counter", directory, countername);
3183 counterfile = fopen(filename,
"r");
3185 if(fgets(readbuf,
sizeof(readbuf), counterfile)) {
3186 ast_debug(3,
"Read this string from counter file: %s\n", readbuf);
3187 old = counter = atoi(readbuf);
3189 fclose(counterfile);
3195 ast_debug(2,
"MINIVM Counter %s/%s: Value %d\n", directory, countername, counter);
3209 counterfile = fopen(filename,
"w");
3211 ast_log(
LOG_ERROR,
"Could not open counter file for writing : %s - %s\n", filename, strerror(
errno));
3215 fprintf(counterfile,
"%d\n\n", counter);
3216 fclose(counterfile);
3218 ast_debug(2,
"MINIVM Counter %s/%s: Old value %d New value %d\n", directory, countername, old, counter);
3225 char *username, *domain, *countername;
3226 char userpath[BUFSIZ];
3233 if ((countername = strchr(username,
':'))) {
3234 *countername =
'\0';
3238 if ((domain = strchr(username,
'@'))) {
3250 ast_log(
LOG_ERROR,
"This function needs two arguments: Account:countername\n");
3262 ast_log(
LOG_ERROR,
"Minivm account does not exist: %s@%s\n", username, domain);
3271 snprintf(
buf,
len,
"%d", res);
3278 char *username, *domain, *countername, *operand;
3279 char userpath[BUFSIZ];
3285 change = atoi(
value);
3289 if ((countername = strchr(username,
':'))) {
3290 *countername =
'\0';
3293 if ((operand = strchr(countername,
':'))) {
3298 if ((domain = strchr(username,
'@'))) {
3316 ast_log(
LOG_ERROR,
"Writing to this function requires three arguments: Account:countername:operand\n");
3322 ast_log(
LOG_ERROR,
"Minivm account does not exist: %s@%s\n", username, domain);
3328 if (*operand ==
'i')
3330 else if (*operand ==
'd') {
3331 change = change * -1;
3333 }
else if (*operand ==
's')
3357 .
name =
"MINIVMCOUNTER",
3363 .
name =
"MINIVMACCOUNT",
3409 "Usage: minivm reload\n"
3410 " Reload mini-voicemail configuration and reset statistics\n";
3417 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 cofiguration.
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.
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.
char * strsep(char **str, const char *delims)
char * mkdtemp(char *template_s)
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.
#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)
@ CONFIG_FLAG_FILEUNCHANGED
#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.