00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #include <stdlib.h>
00041 #include <errno.h>
00042 #include <unistd.h>
00043 #include <string.h>
00044 #include <stdlib.h>
00045 #include <stdio.h>
00046 #include <sys/time.h>
00047 #include <sys/stat.h>
00048 #include <sys/types.h>
00049 #include <sys/mman.h>
00050 #include <time.h>
00051 #include <dirent.h>
00052
00053 #include "asterisk.h"
00054
00055 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 75748 $")
00056
00057 #include "asterisk/lock.h"
00058 #include "asterisk/file.h"
00059 #include "asterisk/logger.h"
00060 #include "asterisk/channel.h"
00061 #include "asterisk/pbx.h"
00062 #include "asterisk/options.h"
00063 #include "asterisk/config.h"
00064 #include "asterisk/say.h"
00065 #include "asterisk/module.h"
00066 #include "asterisk/adsi.h"
00067 #include "asterisk/app.h"
00068 #include "asterisk/manager.h"
00069 #include "asterisk/dsp.h"
00070 #include "asterisk/localtime.h"
00071 #include "asterisk/cli.h"
00072 #include "asterisk/utils.h"
00073 #ifdef USE_ODBC_STORAGE
00074 #include "asterisk/res_odbc.h"
00075 #endif
00076
00077 #define COMMAND_TIMEOUT 5000
00078 #define VOICEMAIL_DIR_MODE 0700
00079 #define VOICEMAIL_FILE_MODE 0600
00080 #define CHUNKSIZE 65536
00081
00082 #define VOICEMAIL_CONFIG "voicemail.conf"
00083 #define ASTERISK_USERNAME "asterisk"
00084
00085
00086
00087 #define SENDMAIL "/usr/sbin/sendmail -t"
00088
00089 #define INTRO "vm-intro"
00090
00091 #define MAXMSG 100
00092 #define MAXMSGLIMIT 9999
00093
00094 #define BASEMAXINLINE 256
00095 #define BASELINELEN 72
00096 #define BASEMAXINLINE 256
00097 #define eol "\r\n"
00098
00099 #define MAX_DATETIME_FORMAT 512
00100 #define MAX_NUM_CID_CONTEXTS 10
00101
00102 #define VM_REVIEW (1 << 0)
00103 #define VM_OPERATOR (1 << 1)
00104 #define VM_SAYCID (1 << 2)
00105 #define VM_SVMAIL (1 << 3)
00106 #define VM_ENVELOPE (1 << 4)
00107 #define VM_SAYDURATION (1 << 5)
00108 #define VM_SKIPAFTERCMD (1 << 6)
00109 #define VM_FORCENAME (1 << 7)
00110 #define VM_FORCEGREET (1 << 8)
00111 #define VM_PBXSKIP (1 << 9)
00112 #define VM_DIRECFORWARD (1 << 10)
00113 #define VM_ATTACH (1 << 11)
00114 #define VM_DELETE (1 << 12)
00115 #define VM_ALLOCED (1 << 13)
00116 #define VM_SEARCH (1 << 14)
00117
00118 #define ERROR_LOCK_PATH -100
00119
00120 enum {
00121 OPT_SILENT = (1 << 0),
00122 OPT_BUSY_GREETING = (1 << 1),
00123 OPT_UNAVAIL_GREETING = (1 << 2),
00124 OPT_RECORDGAIN = (1 << 3),
00125 OPT_PREPEND_MAILBOX = (1 << 4),
00126 OPT_PRIORITY_JUMP = (1 << 5),
00127 } vm_option_flags;
00128
00129 enum {
00130 OPT_ARG_RECORDGAIN = 0,
00131 OPT_ARG_ARRAY_SIZE = 1,
00132 } vm_option_args;
00133
00134 AST_APP_OPTIONS(vm_app_options, {
00135 AST_APP_OPTION('s', OPT_SILENT),
00136 AST_APP_OPTION('b', OPT_BUSY_GREETING),
00137 AST_APP_OPTION('u', OPT_UNAVAIL_GREETING),
00138 AST_APP_OPTION_ARG('g', OPT_RECORDGAIN, OPT_ARG_RECORDGAIN),
00139 AST_APP_OPTION('p', OPT_PREPEND_MAILBOX),
00140 AST_APP_OPTION('j', OPT_PRIORITY_JUMP),
00141 });
00142
00143 static int load_config(void);
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206 struct baseio {
00207 int iocp;
00208 int iolen;
00209 int linelength;
00210 int ateof;
00211 unsigned char iobuf[BASEMAXINLINE];
00212 };
00213
00214
00215 struct ast_vm_user {
00216 char context[AST_MAX_CONTEXT];
00217 char mailbox[AST_MAX_EXTENSION];
00218 char password[80];
00219 char fullname[80];
00220 char email[80];
00221 char pager[80];
00222 char serveremail[80];
00223 char mailcmd[160];
00224 char language[MAX_LANGUAGE];
00225 char zonetag[80];
00226 char callback[80];
00227 char dialout[80];
00228 char uniqueid[20];
00229 char exit[80];
00230 unsigned int flags;
00231 int saydurationm;
00232 int maxmsg;
00233 struct ast_vm_user *next;
00234 };
00235
00236 struct vm_zone {
00237 char name[80];
00238 char timezone[80];
00239 char msg_format[512];
00240 struct vm_zone *next;
00241 };
00242
00243 struct vm_state {
00244 char curbox[80];
00245 char username[80];
00246 char curdir[PATH_MAX];
00247 char vmbox[PATH_MAX];
00248 char fn[PATH_MAX];
00249 char fn2[PATH_MAX];
00250 int *deleted;
00251 int *heard;
00252 int curmsg;
00253 int lastmsg;
00254 int newmessages;
00255 int oldmessages;
00256 int starting;
00257 int repeats;
00258 };
00259 static int advanced_options(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int msg,
00260 int option, signed char record_gain);
00261 static int dialout(struct ast_channel *chan, struct ast_vm_user *vmu, char *num, char *outgoing_context);
00262 static int play_record_review(struct ast_channel *chan, char *playfile, char *recordfile, int maxtime,
00263 char *fmt, int outsidecaller, struct ast_vm_user *vmu, int *duration, const char *unlockdir,
00264 signed char record_gain);
00265 static int vm_tempgreeting(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain);
00266 static int vm_play_folder_name(struct ast_channel *chan, char *mbox);
00267
00268 static void apply_options(struct ast_vm_user *vmu, const char *options);
00269
00270 #ifdef USE_ODBC_STORAGE
00271 static char odbc_database[80];
00272 static char odbc_table[80];
00273 #define RETRIEVE(a,b) retrieve_file(a,b)
00274 #define DISPOSE(a,b) remove_file(a,b)
00275 #define STORE(a,b,c,d) store_file(a,b,c,d)
00276 #define EXISTS(a,b,c,d) (message_exists(a,b))
00277 #define RENAME(a,b,c,d,e,f,g,h) (rename_file(a,b,c,d,e,f))
00278 #define COPY(a,b,c,d,e,f,g,h) (copy_file(a,b,c,d,e,f))
00279 #define DELETE(a,b,c) (delete_file(a,b))
00280 #else
00281 #define RETRIEVE(a,b)
00282 #define DISPOSE(a,b)
00283 #define STORE(a,b,c,d)
00284 #define EXISTS(a,b,c,d) (ast_fileexists(c,NULL,d) > 0)
00285 #define RENAME(a,b,c,d,e,f,g,h) (rename_file(g,h));
00286 #define COPY(a,b,c,d,e,f,g,h) (copy_file(g,h));
00287 #define DELETE(a,b,c) (vm_delete(c))
00288 #endif
00289
00290 static char VM_SPOOL_DIR[AST_CONFIG_MAX_PATH];
00291
00292 static char ext_pass_cmd[128];
00293
00294 static char *tdesc = "Comedian Mail (Voicemail System)";
00295
00296 static char *addesc = "Comedian Mail";
00297
00298 static char *synopsis_vm =
00299 "Leave a Voicemail message";
00300
00301 static char *descrip_vm =
00302 " VoiceMail(mailbox[@context][&mailbox[@context]][...][|options]): This\n"
00303 "application allows the calling party to leave a message for the specified\n"
00304 "list of mailboxes. When multiple mailboxes are specified, the greeting will\n"
00305 "be taken from the first mailbox specified. Dialplan execution will stop if the\n"
00306 "specified mailbox does not exist.\n"
00307 " The Voicemail application will exit if any of the following DTMF digits are\n"
00308 "received:\n"
00309 " 0 - Jump to the 'o' extension in the current dialplan context.\n"
00310 " * - Jump to the 'a' extension in the current dialplan context.\n"
00311 " This application will set the following channel variable upon completion:\n"
00312 " VMSTATUS - This indicates the status of the execution of the VoiceMail\n"
00313 " application. The possible values are:\n"
00314 " SUCCESS | USEREXIT | FAILED\n\n"
00315 " Options:\n"
00316 " b - Play the 'busy' greeting to the calling party.\n"
00317 " g(#) - Use the specified amount of gain when recording the voicemail\n"
00318 " message. The units are whole-number decibels (dB).\n"
00319 " s - Skip the playback of instructions for leaving a message to the\n"
00320 " calling party.\n"
00321 " u - Play the 'unavailable' greeting.\n"
00322 " j - Jump to priority n+101 if the mailbox is not found or some other\n"
00323 " error occurs.\n";
00324
00325 static char *synopsis_vmain =
00326 "Check Voicemail messages";
00327
00328 static char *descrip_vmain =
00329 " VoiceMailMain([mailbox][@context][|options]): This application allows the\n"
00330 "calling party to check voicemail messages. A specific mailbox, and optional\n"
00331 "corresponding context, may be specified. If a mailbox is not provided, the\n"
00332 "calling party will be prompted to enter one. If a context is not specified,\n"
00333 "the 'default' context will be used.\n\n"
00334 " Options:\n"
00335 " p - Consider the mailbox parameter as a prefix to the mailbox that\n"
00336 " is entered by the caller.\n"
00337 " g(#) - Use the specified amount of gain when recording a voicemail\n"
00338 " message. The units are whole-number decibels (dB).\n"
00339 " s - Skip checking the passcode for the mailbox.\n";
00340
00341 static char *synopsis_vm_box_exists =
00342 "Check to see if Voicemail mailbox exists";
00343
00344 static char *descrip_vm_box_exists =
00345 " MailboxExists(mailbox[@context][|options]): Check to see if the specified\n"
00346 "mailbox exists. If no voicemail context is specified, the 'default' context\n"
00347 "will be used.\n"
00348 " This application will set the following channel variable upon completion:\n"
00349 " VMBOXEXISTSSTATUS - This will contain the status of the execution of the\n"
00350 " MailboxExists application. Possible values include:\n"
00351 " SUCCESS | FAILED\n\n"
00352 " Options:\n"
00353 " j - Jump to priority n+101 if the mailbox is found.\n";
00354
00355 static char *synopsis_vmauthenticate =
00356 "Authenticate with Voicemail passwords";
00357
00358 static char *descrip_vmauthenticate =
00359 " VMAuthenticate([mailbox][@context][|options]): This application behaves the\n"
00360 "same way as the Authenticate application, but the passwords are taken from\n"
00361 "voicemail.conf.\n"
00362 " If the mailbox is specified, only that mailbox's password will be considered\n"
00363 "valid. If the mailbox is not specified, the channel variable AUTH_MAILBOX will\n"
00364 "be set with the authenticated mailbox.\n\n"
00365 " Options:\n"
00366 " s - Skip playing the initial prompts.\n";
00367
00368
00369 static char *app = "VoiceMail";
00370
00371
00372 static char *app2 = "VoiceMailMain";
00373
00374 static char *app3 = "MailboxExists";
00375 static char *app4 = "VMAuthenticate";
00376
00377 AST_MUTEX_DEFINE_STATIC(vmlock);
00378 struct ast_vm_user *users;
00379 struct ast_vm_user *usersl;
00380 struct vm_zone *zones = NULL;
00381 struct vm_zone *zonesl = NULL;
00382 static int maxsilence;
00383 static int maxmsg;
00384 static int silencethreshold = 128;
00385 static char serveremail[80];
00386 static char mailcmd[160];
00387 static char externnotify[160];
00388
00389 static char vmfmts[80];
00390 static int vmminmessage;
00391 static int vmmaxmessage;
00392 static int maxgreet;
00393 static int skipms;
00394 static int maxlogins;
00395
00396 static struct ast_flags globalflags = {0};
00397
00398 static int saydurationminfo;
00399
00400 static char dialcontext[AST_MAX_CONTEXT];
00401 static char callcontext[AST_MAX_CONTEXT];
00402 static char exitcontext[AST_MAX_CONTEXT];
00403
00404 static char cidinternalcontexts[MAX_NUM_CID_CONTEXTS][64];
00405
00406
00407 static char *emailbody = NULL;
00408 static char *emailsubject = NULL;
00409 static char *pagerbody = NULL;
00410 static char *pagersubject = NULL;
00411 static char fromstring[100];
00412 static char pagerfromstring[100];
00413 static char emailtitle[100];
00414 static char charset[32] = "ISO-8859-1";
00415
00416 static unsigned char adsifdn[4] = "\x00\x00\x00\x0F";
00417 static unsigned char adsisec[4] = "\x9B\xDB\xF7\xAC";
00418 static int adsiver = 1;
00419 static char emaildateformat[32] = "%A, %B %d, %Y at %r";
00420
00421 STANDARD_LOCAL_USER;
00422
00423 LOCAL_USER_DECL;
00424
00425 static void populate_defaults(struct ast_vm_user *vmu)
00426 {
00427 ast_copy_flags(vmu, (&globalflags), AST_FLAGS_ALL);
00428 if (saydurationminfo)
00429 vmu->saydurationm = saydurationminfo;
00430 if (callcontext)
00431 ast_copy_string(vmu->callback, callcontext, sizeof(vmu->callback));
00432 if (dialcontext)
00433 ast_copy_string(vmu->dialout, dialcontext, sizeof(vmu->dialout));
00434 if (exitcontext)
00435 ast_copy_string(vmu->exit, exitcontext, sizeof(vmu->exit));
00436 if (maxmsg)
00437 vmu->maxmsg = maxmsg;
00438 }
00439
00440 static void apply_option(struct ast_vm_user *vmu, const char *var, const char *value)
00441 {
00442 int x;
00443 if (!strcasecmp(var, "attach")) {
00444 ast_set2_flag(vmu, ast_true(value), VM_ATTACH);
00445 } else if (!strcasecmp(var, "serveremail")) {
00446 ast_copy_string(vmu->serveremail, value, sizeof(vmu->serveremail));
00447 } else if (!strcasecmp(var, "language")) {
00448 ast_copy_string(vmu->language, value, sizeof(vmu->language));
00449 } else if (!strcasecmp(var, "tz")) {
00450 ast_copy_string(vmu->zonetag, value, sizeof(vmu->zonetag));
00451 } else if (!strcasecmp(var, "delete") || !strcasecmp(var, "deletevoicemail")) {
00452 ast_set2_flag(vmu, ast_true(value), VM_DELETE);
00453 } else if (!strcasecmp(var, "saycid")){
00454 ast_set2_flag(vmu, ast_true(value), VM_SAYCID);
00455 } else if (!strcasecmp(var,"sendvoicemail")){
00456 ast_set2_flag(vmu, ast_true(value), VM_SVMAIL);
00457 } else if (!strcasecmp(var, "review")){
00458 ast_set2_flag(vmu, ast_true(value), VM_REVIEW);
00459 } else if (!strcasecmp(var, "operator")){
00460 ast_set2_flag(vmu, ast_true(value), VM_OPERATOR);
00461 } else if (!strcasecmp(var, "envelope")){
00462 ast_set2_flag(vmu, ast_true(value), VM_ENVELOPE);
00463 } else if (!strcasecmp(var, "sayduration")){
00464 ast_set2_flag(vmu, ast_true(value), VM_SAYDURATION);
00465 } else if (!strcasecmp(var, "saydurationm")){
00466 if (sscanf(value, "%d", &x) == 1) {
00467 vmu->saydurationm = x;
00468 } else {
00469 ast_log(LOG_WARNING, "Invalid min duration for say duration\n");
00470 }
00471 } else if (!strcasecmp(var, "forcename")){
00472 ast_set2_flag(vmu, ast_true(value), VM_FORCENAME);
00473 } else if (!strcasecmp(var, "forcegreetings")){
00474 ast_set2_flag(vmu, ast_true(value), VM_FORCEGREET);
00475 } else if (!strcasecmp(var, "callback")) {
00476 ast_copy_string(vmu->callback, value, sizeof(vmu->callback));
00477 } else if (!strcasecmp(var, "dialout")) {
00478 ast_copy_string(vmu->dialout, value, sizeof(vmu->dialout));
00479 } else if (!strcasecmp(var, "exitcontext")) {
00480 ast_copy_string(vmu->exit, value, sizeof(vmu->exit));
00481 } else if (!strcasecmp(var, "maxmsg")) {
00482 vmu->maxmsg = atoi(value);
00483 if (vmu->maxmsg <= 0) {
00484 ast_log(LOG_WARNING, "Invalid number of messages per folder maxmsg=%s. Using default value %i\n", value, MAXMSG);
00485 vmu->maxmsg = MAXMSG;
00486 } else if (vmu->maxmsg > MAXMSGLIMIT) {
00487 ast_log(LOG_WARNING, "Maximum number of messages per folder is %i. Cannot accept value maxmsg=%s\n", MAXMSGLIMIT, value);
00488 vmu->maxmsg = MAXMSGLIMIT;
00489 }
00490 } else if (!strcasecmp(var, "options")) {
00491 apply_options(vmu, value);
00492 }
00493 }
00494
00495 static int change_password_realtime(struct ast_vm_user *vmu, const char *password)
00496 {
00497 int res;
00498 if (!ast_strlen_zero(vmu->uniqueid)) {
00499 res = ast_update_realtime("voicemail", "uniqueid", vmu->uniqueid, "password", password, NULL);
00500 if (res > 0) {
00501 ast_copy_string(vmu->password, password, sizeof(vmu->password));
00502 res = 0;
00503 } else if (!res) {
00504 res = -1;
00505 }
00506 return res;
00507 }
00508 return -1;
00509 }
00510
00511 static void apply_options(struct ast_vm_user *vmu, const char *options)
00512 {
00513 char *stringp;
00514 char *s;
00515 char *var, *value;
00516 stringp = ast_strdupa(options);
00517 while ((s = strsep(&stringp, "|"))) {
00518 value = s;
00519 if ((var = strsep(&value, "=")) && value) {
00520 apply_option(vmu, var, value);
00521 }
00522 }
00523 }
00524
00525 static struct ast_vm_user *find_user_realtime(struct ast_vm_user *ivm, const char *context, const char *mailbox)
00526 {
00527 struct ast_variable *var, *tmp;
00528 struct ast_vm_user *retval;
00529
00530 if (ivm)
00531 retval=ivm;
00532 else
00533 retval=malloc(sizeof(struct ast_vm_user));
00534
00535 if (retval) {
00536 memset(retval, 0, sizeof(struct ast_vm_user));
00537 if (!ivm)
00538 ast_set_flag(retval, VM_ALLOCED);
00539 if (mailbox)
00540 ast_copy_string(retval->mailbox, mailbox, sizeof(retval->mailbox));
00541 populate_defaults(retval);
00542 if (!context && ast_test_flag((&globalflags), VM_SEARCH))
00543 var = ast_load_realtime("voicemail", "mailbox", mailbox, NULL);
00544 else
00545 var = ast_load_realtime("voicemail", "mailbox", mailbox, "context", context, NULL);
00546 if (var) {
00547 tmp = var;
00548 while(tmp) {
00549 printf("%s => %s\n", tmp->name, tmp->value);
00550 if (!strcasecmp(tmp->name, "password")) {
00551 ast_copy_string(retval->password, tmp->value, sizeof(retval->password));
00552 } else if (!strcasecmp(tmp->name, "uniqueid")) {
00553 ast_copy_string(retval->uniqueid, tmp->value, sizeof(retval->uniqueid));
00554 } else if (!strcasecmp(tmp->name, "pager")) {
00555 ast_copy_string(retval->pager, tmp->value, sizeof(retval->pager));
00556 } else if (!strcasecmp(tmp->name, "email")) {
00557 ast_copy_string(retval->email, tmp->value, sizeof(retval->email));
00558 } else if (!strcasecmp(tmp->name, "fullname")) {
00559 ast_copy_string(retval->fullname, tmp->value, sizeof(retval->fullname));
00560 } else if (!strcasecmp(tmp->name, "context")) {
00561 ast_copy_string(retval->context, tmp->value, sizeof(retval->context));
00562 } else
00563 apply_option(retval, tmp->name, tmp->value);
00564 tmp = tmp->next;
00565 }
00566 ast_variables_destroy(var);
00567 } else {
00568 if (!ivm)
00569 free(retval);
00570 retval = NULL;
00571 }
00572 }
00573 return retval;
00574 }
00575
00576 static struct ast_vm_user *find_user(struct ast_vm_user *ivm, const char *context, const char *mailbox)
00577 {
00578
00579 struct ast_vm_user *vmu=NULL, *cur;
00580 ast_mutex_lock(&vmlock);
00581 cur = users;
00582
00583 if (!context && !ast_test_flag((&globalflags), VM_SEARCH))
00584 context = "default";
00585
00586 while (cur) {
00587 if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(mailbox, cur->mailbox))
00588 break;
00589 if (context && (!strcasecmp(context, cur->context)) && (!strcasecmp(mailbox, cur->mailbox)))
00590 break;
00591 cur=cur->next;
00592 }
00593 if (cur) {
00594 if (ivm)
00595 vmu = ivm;
00596 else
00597
00598 vmu = malloc(sizeof(struct ast_vm_user));
00599 if (vmu) {
00600 memcpy(vmu, cur, sizeof(struct ast_vm_user));
00601 ast_set2_flag(vmu, !ivm, VM_ALLOCED);
00602 vmu->next = NULL;
00603 }
00604 } else
00605 vmu = find_user_realtime(ivm, context, mailbox);
00606 ast_mutex_unlock(&vmlock);
00607 return vmu;
00608 }
00609
00610 static int reset_user_pw(const char *context, const char *mailbox, const char *newpass)
00611 {
00612
00613 struct ast_vm_user *cur;
00614 int res = -1;
00615 ast_mutex_lock(&vmlock);
00616 cur = users;
00617 while (cur) {
00618 if ((!context || !strcasecmp(context, cur->context)) &&
00619 (!strcasecmp(mailbox, cur->mailbox)))
00620 break;
00621 cur=cur->next;
00622 }
00623 if (cur) {
00624 ast_copy_string(cur->password, newpass, sizeof(cur->password));
00625 res = 0;
00626 }
00627 ast_mutex_unlock(&vmlock);
00628 return res;
00629 }
00630
00631 static void vm_change_password(struct ast_vm_user *vmu, const char *newpassword)
00632 {
00633
00634
00635
00636
00637 FILE *configin;
00638 FILE *configout;
00639 int linenum=0;
00640 char inbuf[256];
00641 char orig[256];
00642 char currcontext[256] = "";
00643 char tmpin[AST_CONFIG_MAX_PATH];
00644 char tmpout[AST_CONFIG_MAX_PATH];
00645 struct stat statbuf;
00646
00647 if (!change_password_realtime(vmu, newpassword))
00648 return;
00649
00650 snprintf(tmpin, sizeof(tmpin), "%s/voicemail.conf", ast_config_AST_CONFIG_DIR);
00651 snprintf(tmpout, sizeof(tmpout), "%s/voicemail.conf.new", ast_config_AST_CONFIG_DIR);
00652 configin = fopen(tmpin,"r");
00653 if (configin)
00654 configout = fopen(tmpout,"w+");
00655 else
00656 configout = NULL;
00657 if (!configin || !configout) {
00658 if (configin)
00659 fclose(configin);
00660 else
00661 ast_log(LOG_WARNING, "Warning: Unable to open '%s' for reading: %s\n", tmpin, strerror(errno));
00662 if (configout)
00663 fclose(configout);
00664 else
00665 ast_log(LOG_WARNING, "Warning: Unable to open '%s' for writing: %s\n", tmpout, strerror(errno));
00666 return;
00667 }
00668
00669 while (!feof(configin)) {
00670 char *user = NULL, *pass = NULL, *rest = NULL, *comment = NULL, *tmpctx = NULL, *tmpctxend = NULL;
00671
00672
00673 if (fgets(inbuf, sizeof(inbuf), configin) == NULL)
00674 continue;
00675 linenum++;
00676
00677
00678 ast_copy_string(orig, inbuf, sizeof(orig));
00679
00680
00681
00682
00683
00684 if (inbuf[strlen(inbuf) - 1] == '\n')
00685 inbuf[strlen(inbuf) - 1] = '\0';
00686
00687 if ((comment = strchr(inbuf, ';')))
00688 *comment++ = '\0';
00689
00690 if (ast_strlen_zero(inbuf)) {
00691 fprintf(configout, "%s", orig);
00692 continue;
00693 }
00694
00695
00696 if ((tmpctx = strchr(inbuf, '['))) {
00697 tmpctxend = strchr(tmpctx, ']');
00698 if (tmpctxend) {
00699
00700 ast_copy_string(currcontext, tmpctx + 1, tmpctxend - tmpctx);
00701 fprintf(configout, "%s", orig);
00702 continue;
00703 }
00704 }
00705
00706
00707 user = inbuf;
00708 if ((pass = strchr(user, '='))) {
00709
00710 *pass++ = '\0';
00711
00712 user = ast_strip(user);
00713
00714 if (*pass == '>')
00715 *pass++ = '\0';
00716
00717 pass = ast_skip_blanks(pass);
00718
00719
00720
00721
00722
00723
00724 if ((rest = strchr(pass, ',')))
00725 *rest++ = '\0';
00726 } else {
00727 user = NULL;
00728 }
00729
00730
00731 if (!ast_strlen_zero(user) && !strcmp(user, vmu->mailbox) &&
00732 !ast_strlen_zero(pass) && !strcmp(pass, vmu->password) &&
00733 !strcasecmp(currcontext, vmu->context)) {
00734
00735 if (rest) {
00736 fprintf(configout, "%s => %s,%s", user, newpassword, rest);
00737 } else {
00738 fprintf(configout, "%s => %s", user, newpassword);
00739 }
00740
00741 if (comment) {
00742 fprintf(configout, ";%s\n", comment);
00743 } else {
00744 fprintf(configout, "\n");
00745 }
00746 } else {
00747
00748 fprintf(configout, "%s", orig);
00749 }
00750 }
00751 fclose(configin);
00752 fclose(configout);
00753
00754 stat(tmpin, &statbuf);
00755 chmod(tmpout, statbuf.st_mode);
00756 chown(tmpout, statbuf.st_uid, statbuf.st_gid);
00757 unlink(tmpin);
00758 rename(tmpout, tmpin);
00759 reset_user_pw(vmu->context, vmu->mailbox, newpassword);
00760 ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
00761 }
00762
00763 static void vm_change_password_shell(struct ast_vm_user *vmu, char *newpassword)
00764 {
00765 char buf[255];
00766 snprintf(buf,255,"%s %s %s %s",ext_pass_cmd,vmu->context,vmu->mailbox,newpassword);
00767 if (!ast_safe_system(buf)) {
00768 reset_user_pw(vmu->context, vmu->mailbox, newpassword);
00769 ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
00770 }
00771 }
00772
00773 static int make_dir(char *dest, int len, char *context, char *ext, char *mailbox)
00774 {
00775 return snprintf(dest, len, "%s%s/%s/%s", VM_SPOOL_DIR, context, ext, mailbox);
00776 }
00777
00778 static int make_file(char *dest, int len, char *dir, int num)
00779 {
00780 return snprintf(dest, len, "%s/msg%04d", dir, num);
00781 }
00782
00783
00784
00785
00786
00787
00788
00789
00790 static int create_dirpath(char *dest, int len, char *context, char *ext, char *mailbox)
00791 {
00792 mode_t mode = VOICEMAIL_DIR_MODE;
00793
00794 if(context && context[0] != '\0') {
00795 make_dir(dest, len, context, "", "");
00796 if(mkdir(dest, mode) && errno != EEXIST) {
00797 ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", dest, strerror(errno));
00798 return -1;
00799 }
00800 }
00801 if(ext && ext[0] != '\0') {
00802 make_dir(dest, len, context, ext, "");
00803 if(mkdir(dest, mode) && errno != EEXIST) {
00804 ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", dest, strerror(errno));
00805 return -1;
00806 }
00807 }
00808 if(mailbox && mailbox[0] != '\0') {
00809 make_dir(dest, len, context, ext, mailbox);
00810 if(mkdir(dest, mode) && errno != EEXIST) {
00811 ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", dest, strerror(errno));
00812 return -1;
00813 }
00814 }
00815 return 0;
00816 }
00817
00818
00819
00820
00821 static int vm_lock_path(const char *path)
00822 {
00823 switch (ast_lock_path(path)) {
00824 case AST_LOCK_TIMEOUT:
00825 return -1;
00826 default:
00827 return 0;
00828 }
00829 }
00830
00831
00832 #ifdef USE_ODBC_STORAGE
00833 static int retrieve_file(char *dir, int msgnum)
00834 {
00835 int x = 0;
00836 int res;
00837 int fd=-1;
00838 size_t fdlen = 0;
00839 void *fdm = MAP_FAILED;
00840 SQLSMALLINT colcount=0;
00841 SQLHSTMT stmt;
00842 char sql[PATH_MAX];
00843 char fmt[80]="";
00844 char *c;
00845 char coltitle[256];
00846 SQLSMALLINT collen;
00847 SQLSMALLINT datatype;
00848 SQLSMALLINT decimaldigits;
00849 SQLSMALLINT nullable;
00850 SQLULEN colsize;
00851 FILE *f=NULL;
00852 char rowdata[80];
00853 char fn[PATH_MAX];
00854 char full_fn[PATH_MAX];
00855 char msgnums[80];
00856
00857 odbc_obj *obj;
00858 obj = fetch_odbc_obj(odbc_database, 0);
00859 if (obj) {
00860 ast_copy_string(fmt, vmfmts, sizeof(fmt));
00861 c = strchr(fmt, '|');
00862 if (c)
00863 *c = '\0';
00864 if (!strcasecmp(fmt, "wav49"))
00865 strcpy(fmt, "WAV");
00866 snprintf(msgnums, sizeof(msgnums),"%d", msgnum);
00867 if (msgnum > -1)
00868 make_file(fn, sizeof(fn), dir, msgnum);
00869 else
00870 ast_copy_string(fn, dir, sizeof(fn));
00871 snprintf(full_fn, sizeof(full_fn), "%s.txt", fn);
00872
00873 if (!(f = fopen(full_fn, "w+"))) {
00874 ast_log(LOG_WARNING, "Failed to open/create '%s'\n", full_fn);
00875 goto yuck;
00876 }
00877
00878 snprintf(full_fn, sizeof(full_fn), "%s.%s", fn, fmt);
00879 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt);
00880 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00881 ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n");
00882 goto yuck;
00883 }
00884 snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE dir=? AND msgnum=?",odbc_table);
00885 res = SQLPrepare(stmt, sql, SQL_NTS);
00886 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00887 ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql);
00888 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
00889 goto yuck;
00890 }
00891 SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(dir), 0, (void *)dir, 0, NULL);
00892 SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(msgnums), 0, (void *)msgnums, 0, NULL);
00893 res = odbc_smart_execute(obj, stmt);
00894