[asterisk-commits] jcollie: branch jcollie/bug6082 r39420 - in
/team/jcollie/bug6082: ./ apps/ c...
asterisk-commits at lists.digium.com
asterisk-commits at lists.digium.com
Tue Aug 8 14:18:58 MST 2006
Author: jcollie
Date: Tue Aug 8 16:18:57 2006
New Revision: 39420
URL: http://svn.digium.com/view/asterisk?rev=39420&view=rev
Log:
Merged revisions 39272,39274,39295,39316,39332-39333,39349,39351,39353,39378,39380,39404 via svnmerge from
https://origsvn.digium.com/svn/asterisk/trunk
................
r39272 | russell | 2006-08-08 01:32:04 -0500 (Tue, 08 Aug 2006) | 56 lines
Merge team/russell/ast_verbose_threadstorage
- instead of defining a free() wrapper in a bunch of files, define it as
ast_free() in utils.h and remove the copies from all the files.
- centralize and abstract the code used for doing thread storage. The code
lives in threadstorage.h, with one function being implemented in utils.c.
This new API includes generic thread storage as well as special functions
for handling thread local dynamic length string buffers.
- update ast_inet_ntoa() to use the new threadstorage API
- update ast_state2str() to use the new threadstorage API
- update ast_cli() to use the new threadstorage API
- Modify manager_event() to use thread storage. Instead of using a buffer of
4096 characters as the workspace for building the manager event, use a thread
local dynamic string. Now there is no length limitation on the length of the
body of a manager event.
- Significantly simplify the handling of ast_verbose() ...
- Instead of using a static char buffer and a lock to make sure only one
thread can be using ast_verbose() at a time, use a thread local dynamic
string as the workspace for preparing the verbose message. Instead of
locking around the entire function, the only locking done now is when the
message has been built and is being deliviered to the list of registered
verbose message handlers.
- This function was doing a strdup() on every message passed to it and
keeping a queue of the last 200 messages in memory. This has been
completely removed. The only place this was used was that if there were
any messages in the verbose queue when a verbose handler was registered,
all of the messages in the queue would be fed to it. So, I just made sure
that the console verbose handler and the network verbose handler (for
remote asterisk consoles) were registered before any verbose messages.
pbx_gtkconsole and pbx_kdeconsole will now lose a few verbose messages at
startup, but I didn't feel the performance hit of this message queue was
worth saving the initial verbose output for these very rarely used modules.
- I have removed the last three arguments to the verbose handlers, leaving
only the string itself because they aren't needed anymore. For example,
ast_verbose had some logic for telling the verbose handler to add
a newline if the buffer was completely full. Now that the buffer can grow
as needed, this doesn't matter anymore.
- remove unused function, ast_verbose_dmesg() which was to dispatch the
message queue
- Convert the list of verbose handlers to use the linked list macros.
- add missing newline characters to a few ast_verbose() calls
- convert the list of log channels to use the linked list macros in logger.c
- fix close_logger() to close all of the files it opened for logging
- update ast_log() to use a thread local dynamic string for its workspace
for preparing log messages instead of a buffer of size BUFSIZ (8kB on my
system) allocated on the stack. The dynamic string in this case is limited
to only growing to a maximum size of BUFSIZ.
................
r39274 | russell | 2006-08-08 01:36:47 -0500 (Tue, 08 Aug 2006) | 3 lines
change constant name from MAXSTRLEN to INITLEN since it is not the maximum
length, it is the initial length of the string when first allocated
................
r39295 | crichter | 2006-08-08 04:19:06 -0500 (Tue, 08 Aug 2006) | 14 lines
* added possibility to change echocancel settings during calls
* removed the holded element from the chan_list struct, we know this from the
state already
* added a few tweaks to make HOLD/RETRIEVE work again (TRANSFER does not work
yet)
* added possibility to debug mISDN frames via syslog
* added misdn_lib_port_is_blocked function to check if a port is blocked
* removed ec_training=1 from empty_bc, we don't use ec_training anymore
* removed unused misdn_lib_get_l2_status function
* added the nt bit to dummy misdn_bchannel objects
* setting bc->out_fac_type to FACILITY_NONE defaultly
* removed HANDLER_DEBUG stuff for better readability
................
r39316 | oej | 2006-08-08 09:47:17 -0500 (Tue, 08 Aug 2006) | 3 lines
Marking PRI_CAUSE as deprecated to be replaced by hangup(cause)
(Issue #7610)
................
r39332 | tilghman | 2006-08-08 10:37:53 -0500 (Tue, 08 Aug 2006) | 2 lines
Bug 6237 - add volgain parameter, such that voicemail messages may be amplified after recording
................
r39333 | file | 2006-08-08 10:53:51 -0500 (Tue, 08 Aug 2006) | 2 lines
Clarify volgain option a bit, it needs sox to work.
................
r39349 | file | 2006-08-08 12:02:45 -0500 (Tue, 08 Aug 2006) | 2 lines
Add support for Sigma Designs cards. These basically allow you to offload dialtone generation to the board. If you're using a quicknet board where this might work, give it a try as well. (issue #6092 reported by ywalther - minor mods by moi)
................
r39351 | mogorman | 2006-08-08 12:07:41 -0500 (Tue, 08 Aug 2006) | 3 lines
some code clean up and catch for a act_hook being called
without a packet.
................
r39353 | russell | 2006-08-08 12:29:09 -0500 (Tue, 08 Aug 2006) | 9 lines
Blocked revisions 39350 via svnmerge
........
r39350 | russell | 2006-08-08 13:04:10 -0400 (Tue, 08 Aug 2006) | 2 lines
Increase the buffer size for the callid (issue #7675, reported by pssatcs)
........
................
r39378 | nadi | 2006-08-08 13:13:40 -0500 (Tue, 08 Aug 2006) | 7 lines
* first bits of decoding facility information elements
* fail on misdn_cfg_init() if elements in the config enum don't match with the config structs in misdn_config.c
* implemented first bits for encoding ISDN facility information elements via ASN.1 descriptions
* using unnamed semaphore for syncing in misdn_thread
* advanced fax detection: configurable detect timeout and context to jump into
................
r39380 | kpfleming | 2006-08-08 13:39:41 -0500 (Tue, 08 Aug 2006) | 10 lines
Merged revisions 39379 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.2
........
r39379 | kpfleming | 2006-08-08 13:39:16 -0500 (Tue, 08 Aug 2006) | 2 lines
add explicit listing of anthm's contributions (issue #7683)
........
................
r39404 | mogorman | 2006-08-08 15:35:59 -0500 (Tue, 08 Aug 2006) | 3 lines
support for imap in app_voicemail as well as some
credits fixed.
................
Added:
team/jcollie/bug6082/channels/misdn/asn1.c
- copied unchanged from r39404, trunk/channels/misdn/asn1.c
team/jcollie/bug6082/channels/misdn/asn1.h
- copied unchanged from r39404, trunk/channels/misdn/asn1.h
team/jcollie/bug6082/doc/imapstorage.txt
- copied unchanged from r39404, trunk/doc/imapstorage.txt
team/jcollie/bug6082/include/asterisk/threadstorage.h
- copied unchanged from r39404, trunk/include/asterisk/threadstorage.h
Modified:
team/jcollie/bug6082/ (props changed)
team/jcollie/bug6082/CREDITS
team/jcollie/bug6082/UPGRADE.txt
team/jcollie/bug6082/apps/app_voicemail.c
team/jcollie/bug6082/asterisk.c
team/jcollie/bug6082/channel.c
team/jcollie/bug6082/channels/chan_iax2.c
team/jcollie/bug6082/channels/chan_jingle.c
team/jcollie/bug6082/channels/chan_misdn.c
team/jcollie/bug6082/channels/chan_phone.c
team/jcollie/bug6082/channels/chan_sip.c
team/jcollie/bug6082/channels/misdn/Makefile
team/jcollie/bug6082/channels/misdn/chan_misdn_config.h
team/jcollie/bug6082/channels/misdn/fac.c
team/jcollie/bug6082/channels/misdn/fac.h
team/jcollie/bug6082/channels/misdn/isdn_lib.c
team/jcollie/bug6082/channels/misdn/isdn_lib.h
team/jcollie/bug6082/channels/misdn/isdn_msg_parser.c
team/jcollie/bug6082/channels/misdn_config.c
team/jcollie/bug6082/cli.c
team/jcollie/bug6082/configs/phone.conf.sample
team/jcollie/bug6082/configs/voicemail.conf.sample
team/jcollie/bug6082/include/asterisk/compiler.h
team/jcollie/bug6082/include/asterisk/logger.h
team/jcollie/bug6082/include/asterisk/utils.h
team/jcollie/bug6082/logger.c
team/jcollie/bug6082/manager.c
team/jcollie/bug6082/pbx/pbx_ael.c
team/jcollie/bug6082/pbx/pbx_config.c
team/jcollie/bug6082/res/res_agi.c
team/jcollie/bug6082/res/res_features.c
team/jcollie/bug6082/res/res_jabber.c
team/jcollie/bug6082/utils.c
Propchange: team/jcollie/bug6082/
------------------------------------------------------------------------------
automerge = *
Propchange: team/jcollie/bug6082/
------------------------------------------------------------------------------
Binary property 'branch-1.2-blocked' - no diff available.
Propchange: team/jcollie/bug6082/
------------------------------------------------------------------------------
Binary property 'branch-1.2-merged' - no diff available.
Propchange: team/jcollie/bug6082/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Tue Aug 8 16:18:57 2006
@@ -1,1 +1,1 @@
-/trunk:1-39251
+/trunk:1-39405
Modified: team/jcollie/bug6082/CREDITS
URL: http://svn.digium.com/view/asterisk/team/jcollie/bug6082/CREDITS?rev=39420&r1=39419&r2=39420&view=diff
==============================================================================
--- team/jcollie/bug6082/CREDITS (original)
+++ team/jcollie/bug6082/CREDITS Tue Aug 8 16:18:57 2006
@@ -41,6 +41,39 @@
russelb at clemson.edu
Anthony Minessale II - Countless big and small fixes, and relentless forward push
+also:
+app_chanspy
+app_forkcdr
+app_controlplayback
+app_while
+app_dumpchan
+app_dictate
+app_realtime
+app_macroif
+app_execif
+app_execiftime
+res_odbc
+res_config_odbc
+format_slin
+app_retrydial
+cdr_custom
+res_muxmon (now MixMonitor)
+res_sqlite
+format_mp3
+Several Features in app_dial including L(), G() and enhancements to M() and D()
+The concept design and initial implementation of dialplan functions with several examples.
+Several CDR enhancements including CDR variables.
+Attended Transfer
+One Touch Record
+Native Music On Hold
+Pluggable config backend (res_config)
+Realtime Caching options and SIP/IAX clusterability
+IAX codec preferences
+Modifications to the manager API to disable events.
+command line '-t' flag to allow recording/voicemail on nfs shares.
+#exec parser in config files.
+setvar from iax and sip peers.
+mulit-line comments in config files.
anthmct at yahoo.com http://www.asterlink.com
James Golovich - Innumerable contributions
@@ -131,6 +164,16 @@
John Martin, Aupix - Improved video support in the SIP channel
Steve Underwood - Provided T.38 pass through support.
+
+George Konstantoulakis - Support for Greek in voicemail added by InAccess Networks (work funded by HOL, www.hol.gr) gkon at inaccessnetworks.com
+
+Daniel Nylander - Support for Swedish and Norwegian languages in voicemail. http://www.danielnylander.se/
+
+Stojan Sljivic - An option for maximum number of messsages per mailbox in voicemail. Also an issue with voicemail synchronization has been fixed. GDS Partners www.gdspartners.com . stojan.sljivic at gdspartners.com
+
+Bartosz Supczinski - Support for Polish added by DIR (www.dir.pl) Bartosz.Supczinski at dir.pl
+
+James Rothenberger - Support for IMAP storage integration added by OneBizTone LLC Work funded by University of Pennsylvania jar at onebiztone.com
=== OTHER CONTRIBUTIONS ===
John Todd - Monkey sounds and associated teletorture prompt
Modified: team/jcollie/bug6082/UPGRADE.txt
URL: http://svn.digium.com/view/asterisk/team/jcollie/bug6082/UPGRADE.txt?rev=39420&r1=39419&r2=39420&view=diff
==============================================================================
--- team/jcollie/bug6082/UPGRADE.txt (original)
+++ team/jcollie/bug6082/UPGRADE.txt Tue Aug 8 16:18:57 2006
@@ -240,6 +240,10 @@
* Builtin transfer functionality sets the variable ${TRANSFERERNAME} in the new
created channel. This variables holds the channel name of the transferer.
+* The dial plan variable PRI_CAUSE will be removed from future versions
+ of Asterisk.
+ It is replaced by adding a cause value to the hangup() application.
+
Functions:
* The function ${CHECK_MD5()} has been deprecated in favor of using an
Modified: team/jcollie/bug6082/apps/app_voicemail.c
URL: http://svn.digium.com/view/asterisk/team/jcollie/bug6082/apps/app_voicemail.c?rev=39420&r1=39419&r2=39420&view=diff
==============================================================================
--- team/jcollie/bug6082/apps/app_voicemail.c (original)
+++ team/jcollie/bug6082/apps/app_voicemail.c Tue Aug 8 16:18:57 2006
@@ -28,20 +28,6 @@
* \note This module requires res_adsi to load.
*/
-/*
- * 12-16-2004 : Support for Greek added by InAccess Networks (work funded by HOL, www.hol.gr)
- * George Konstantoulakis <gkon at inaccessnetworks.com>
- *
- * 05-10-2005 : Support for Swedish and Norwegian added by Daniel Nylander, http://www.danielnylander.se/
- *
- * 05-11-2005 : An option for maximum number of messsages per mailbox added by GDS Partners (www.gdspartners.com)
- * 07-11-2005 : An issue with voicemail synchronization has been fixed by GDS Partners (www.gdspartners.com)
- * Stojan Sljivic <stojan.sljivic at gdspartners.com>
- *
- * 12-04-2006 : Support for Polish added by DIR (www.dir.pl)
- * Bartosz Supczinski <Bartosz.Supczinski at dir.pl>
- */
-
/*** MAKEOPTS
<category name="MENUSELECT_OPTS_app_voicemail" displayname="Voicemail Build Options" positive_output="yes" remove_on_change="apps/app_voicemail.o">
<member name="ODBC_STORAGE" displayname="Storage of Voicemail using ODBC">
@@ -76,7 +62,14 @@
#include <sys/mman.h>
#include <time.h>
#include <dirent.h>
-
+#ifdef IMAP_STORAGE
+#include <ctype.h>
+#include <signal.h>
+#include <pwd.h>
+#include "c-client.h"
+#include "imap4r1.h"
+#include "linkage.h"
+#endif
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
@@ -95,10 +88,56 @@
#include "asterisk/utils.h"
#include "asterisk/stringfields.h"
#include "asterisk/smdi.h"
-#define SMDI_MWI_WAIT_TIMEOUT 1000 /* 1 second */
#ifdef ODBC_STORAGE
#include "asterisk/res_odbc.h"
#endif
+
+#ifdef IMAP_STORAGE
+char *curhst = NIL; /* currently connected host */
+char *curusr = NIL; /* current login user */
+
+char temp[1024];
+
+static char imapserver[48];
+static char imapport[8];
+static char imapflags[128];
+static char authuser[32];
+static char authpassword[42];
+static int expungeonhangup = 1;
+static char delimiter = '\0';
+
+struct vm_state;
+
+int init_mailstream (struct vm_state *vms);
+void write_file (char *filename, char *buffer, unsigned long len);
+void status (MAILSTREAM *stream);
+void display_body (BODY *body, char *pfx, long i);
+static char *get_header_by_tag(char *header, char *tag);
+static void vm_imap_delete(int msgnum, struct vm_state *vms);
+static char *get_user_by_mailbox(char *mailbox);
+static struct vm_state *get_vm_state_by_imapuser(char *user, int interactive);
+static struct vm_state *get_vm_state_by_mailbox(const char *mailbox, int interactive);
+static void vmstate_insert(struct vm_state *vms);
+static void vmstate_delete(struct vm_state *vms);
+static void set_update(MAILSTREAM * stream);
+static void init_vm_state(struct vm_state *vms);
+static void check_msgArray(struct vm_state *vms);
+static void copy_msgArray(struct vm_state *dst, struct vm_state *src);
+static int save_body(BODY *body, struct vm_state *vms, char *section, char *format);
+static int make_gsm_file(char *dest, char *imapuser, char *dir, int num);
+static void get_mailbox_delimiter(MAILSTREAM *stream);
+void mm_parsequota (MAILSTREAM *stream, unsigned char *msg, QUOTALIST *pquota);
+/* should define TMP in config file... */
+#define TMP "/tmp"
+struct vmstate {
+ struct vm_state *vms;
+ struct vmstate *next;
+};
+AST_MUTEX_DEFINE_STATIC(vmstate_lock);
+static struct vmstate *vmstates = NULL;
+#endif
+
+#define SMDI_MWI_WAIT_TIMEOUT 1000 /* 1 second */
#define COMMAND_TIMEOUT 5000
/* Don't modify these here; set your umask at runtime instead */
@@ -142,6 +181,7 @@
#define VM_SEARCH (1 << 14)
#define VM_TEMPGREETWARN (1 << 15) /*!< Remind user tempgreeting is set */
#define ERROR_LOCK_PATH -100
+
enum {
OPT_SILENT = (1 << 0),
@@ -272,6 +312,10 @@
unsigned int flags; /*!< VM_ flags */
int saydurationm;
int maxmsg; /*!< Maximum number of msgs per folder for this mailbox */
+#ifdef IMAP_STORAGE
+ char imapuser[80]; /* IMAP server login */
+#endif
+ double volgain; /*!< Volume gain for voicemails sent via email */
AST_LIST_ENTRY(ast_vm_user) list;
};
@@ -297,6 +341,17 @@
int oldmessages;
int starting;
int repeats;
+#ifdef IMAP_STORAGE
+ int updated; /* decremented on each mail check until 1 -allows delay */
+ long msgArray[256];
+ MAILSTREAM *mailstream;
+ int vmArrayIndex;
+ char imapuser[80]; /* IMAP server login */
+ int interactive;
+ unsigned int quota_limit;
+ unsigned int quota_usage;
+ struct vm_state *persist_vms;
+#endif
};
static int advanced_options(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int msg, int option, signed char record_gain);
static int dialout(struct ast_channel *chan, struct ast_vm_user *vmu, char *num, char *outgoing_context);
@@ -305,7 +360,10 @@
signed char record_gain);
static int vm_tempgreeting(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain);
static int vm_play_folder_name(struct ast_channel *chan, char *mbox);
-
+static int notify_new_message(struct ast_channel *chan, struct ast_vm_user *vmu, int msgnum, long duration, char *fmt, char *cidnum, char *cidname);
+#ifndef ODBC_STORAGE
+static int __has_voicemail(const char *context, const char *mailbox, const char *folder, int shortcircuit);
+#endif
static void apply_options(struct ast_vm_user *vmu, const char *options);
#ifdef ODBC_STORAGE
@@ -319,6 +377,16 @@
#define COPY(a,b,c,d,e,f,g,h) (copy_file(a,b,c,d,e,f))
#define DELETE(a,b,c) (delete_file(a,b))
#else
+#ifdef IMAP_STORAGE
+#define RETRIEVE(a,b)
+#define DISPOSE(a,b)
+#define STORE(a,b,c,d)
+#define EXISTS(a,b,c,d) (ast_fileexists(c,NULL,d) > 0)
+#define RENAME(a,b,c,d,e,f,g,h) (rename_file(g,h));
+#define COPY(a,b,c,d,e,f,g,h) (copy_file(g,h));
+#define IMAP_DELETE(a,b,c,d) (vm_imap_delete(b,d))
+#define DELETE(a,b,c) (vm_delete(c))
+#else
#define RETRIEVE(a,b)
#define DISPOSE(a,b)
#define STORE(a,b,c,d)
@@ -327,12 +395,20 @@
#define COPY(a,b,c,d,e,f,g,h) (copy_file(g,h));
#define DELETE(a,b,c) (vm_delete(c))
#endif
+#endif
static char VM_SPOOL_DIR[PATH_MAX];
static char ext_pass_cmd[128];
-
+#ifdef ODBC_STORAGE
+static char *tdesc = "Comedian Mail (Voicemail System) with ODBC Storage";
+#else
+#ifdef IMAP_STORAGE
+static char *tdesc = "Comedian Mail (Voicemail System) with IMAP Storage";
+#else
static char *tdesc = "Comedian Mail (Voicemail System)";
+#endif
+#endif
static char *addesc = "Comedian Mail";
@@ -359,7 +435,7 @@
" message. The units are whole-number decibels (dB).\n"
" s - Skip the playback of instructions for leaving a message to the\n"
" calling party.\n"
-" u - Play the 'unavailable greeting.\n"
+" u - Play the 'unavailble greeting.\n"
" j - Jump to priority n+101 if the mailbox is not found or some other\n"
" error occurs.\n";
@@ -427,6 +503,7 @@
static char externnotify[160];
static struct ast_smdi_interface *smdi_iface = NULL;
static char vmfmts[80];
+static double volgain;
static int vmminmessage;
static int vmmaxmessage;
static int maxgreet;
@@ -473,6 +550,7 @@
ast_copy_string(vmu->exit, exitcontext, sizeof(vmu->exit));
if (maxmsg)
vmu->maxmsg = maxmsg;
+ vmu->volgain = volgain;
}
static void apply_option(struct ast_vm_user *vmu, const char *var, const char *value)
@@ -488,6 +566,10 @@
ast_copy_string(vmu->language, value, sizeof(vmu->language));
} else if (!strcasecmp(var, "tz")) {
ast_copy_string(vmu->zonetag, value, sizeof(vmu->zonetag));
+#ifdef IMAP_STORAGE
+ } else if (!strcasecmp(var, "imapuser")) {
+ strncpy(vmu->imapuser, value, sizeof(vmu->imapuser) - 1);
+#endif
} else if (!strcasecmp(var, "delete") || !strcasecmp(var, "deletevoicemail")) {
ast_set2_flag(vmu, ast_true(value), VM_DELETE);
} else if (!strcasecmp(var, "saycid")){
@@ -529,6 +611,8 @@
ast_log(LOG_WARNING, "Maximum number of messages per folder is %i. Cannot accept value maxmsg=%s\n", MAXMSGLIMIT, value);
vmu->maxmsg = MAXMSGLIMIT;
}
+ } else if (!strcasecmp(var, "volgain")) {
+ sscanf(value, "%lf", &vmu->volgain);
} else if (!strcasecmp(var, "options")) {
apply_options(vmu, value);
}
@@ -794,10 +878,8 @@
{
char buf[255];
snprintf(buf,255,"%s %s %s %s",ext_pass_cmd,vmu->context,vmu->mailbox,newpassword);
- if (!ast_safe_system(buf)) {
- reset_user_pw(vmu->context, vmu->mailbox, newpassword);
+ if (!ast_safe_system(buf))
ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
- }
}
static int make_dir(char *dest, int len, const char *context, const char *ext, const char *folder)
@@ -805,6 +887,40 @@
return snprintf(dest, len, "%s%s/%s/%s", VM_SPOOL_DIR, context, ext, folder);
}
+#ifdef IMAP_STORAGE
+static int make_gsm_file(char *dest, char *imapuser, char *dir, int num)
+{
+ char gsmdir[256];
+
+ sprintf(gsmdir,"%s/%s",dir,imapuser);
+ if (mkdir(gsmdir, 01777) && (errno != EEXIST)) {
+ ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", gsmdir, strerror(errno));
+ return sprintf(dest, "%s/msg%04d", dir, num);
+ }
+ /* return sprintf(dest, "%s/s/msg%04d", dir, imapuser, num); */
+ return sprintf(dest, "%s/%s/msg%04d", dir, imapuser, num);
+}
+
+static void vm_imap_delete(int msgnum, struct vm_state *vms)
+{
+ unsigned long messageNum = 0;
+ char arg[10];
+
+ /* find real message number based on msgnum */
+ /* this may be an index into vms->msgArray based on the msgnum. */
+
+ messageNum = vms->msgArray[msgnum];
+ if (messageNum == 0) {
+ ast_log(LOG_WARNING, "msgnum %d, mailbox message %lu is zero.\n",msgnum,messageNum);
+ return;
+ }
+ ast_log(LOG_DEBUG, "deleting msgnum %d, which is mailbox message %lu\n",msgnum,messageNum);
+ /* delete message */
+ sprintf (arg,"%lu",messageNum);
+ mail_setflag (vms->mailstream,arg,"\\DELETED");
+}
+
+#endif
static int make_file(char *dest, int len, char *dir, int num)
{
return snprintf(dest, len, "%s/msg%04d", dir, num);
@@ -1441,7 +1557,6 @@
}
#else
-
static int count_messages(struct ast_vm_user *vmu, char *dir)
{
/* Find all .txt files - even if they are not in sequence from 0000 */
@@ -1750,7 +1865,7 @@
return p;
}
-static int sendmail(char *srcemail, struct ast_vm_user *vmu, int msgnum, char *context, char *mailbox, char *cidnum, char *cidname, char *attach, char *format, int duration, int attach_user_voicemail, const char *category)
+static int sendmail(char *srcemail, struct ast_vm_user *vmu, int msgnum, char *context, char *mailbox, char *cidnum, char *cidname, char *attach, char *format, int duration, int attach_user_voicemail, struct ast_channel *chan, const char *category)
{
FILE *p=NULL;
char date[256];
@@ -1761,6 +1876,7 @@
char dur[256];
char tmp[80] = "/tmp/astmail-XXXXXX";
char tmp2[256];
+ char tmpcmd[256];
struct tm tm;
if (vmu && ast_strlen_zero(vmu->email)) {
@@ -1832,6 +1948,23 @@
else
fprintf(p, "Subject: [PBX]: New message %d in mailbox %s\n", msgnum + 1, mailbox);
fprintf(p, "Message-ID: <Asterisk-%d-%d-%s-%d@%s>\n", msgnum, (unsigned int)ast_random(), mailbox, getpid(), host);
+#ifdef IMAP_STORAGE
+ /* additional information needed for IMAP searching */
+ fprintf(p, "X-Asterisk-VM-Message-Num: %d\n", msgnum + 1);
+ /* fprintf(p, "X-Asterisk-VM-Orig-Mailbox: %s\n", ext); */
+ fprintf(p, "X-Asterisk-VM-Server-Name: %s\n", fromstring);
+ fprintf(p, "X-Asterisk-VM-Context: %s\n", context);
+ fprintf(p, "X-Asterisk-VM-Extension: %s\n", chan->exten);
+ fprintf(p, "X-Asterisk-VM-Priority: %d\n", chan->priority);
+ fprintf(p, "X-Asterisk-VM-Caller-channel: %s\n", chan->name);
+ fprintf(p, "X-Asterisk-VM-Caller-ID-Num: %s\n", cidnum);
+ fprintf(p, "X-Asterisk-VM-Caller-ID-Name: %s\n", cidname);
+ fprintf(p, "X-Asterisk-VM-Duration: %d\n", duration);
+ if (category != NULL)
+ fprintf(p, "X-Asterisk-VM-Category: %s\n", category);
+ fprintf(p, "X-Asterisk-VM-Orig-date: %s\n", date);
+ fprintf(p, "X-Asterisk-VM-Orig-time: %ld\n", (long)time(NULL));
+#endif
if (!ast_strlen_zero(cidnum))
fprintf(p, "X-Asterisk-CallerID: %s\n", cidnum);
if (!ast_strlen_zero(cidname))
@@ -1871,7 +2004,19 @@
if (attach_user_voicemail) {
/* Eww. We want formats to tell us their own MIME type */
char *ctype = (!strcasecmp(format, "ogg")) ? "application/" : "audio/x-";
+ char tmpdir[256], newtmp[256];
+ int tmpfd;
+ create_dirpath(tmpdir, sizeof(tmpdir), vmu->context, vmu->mailbox, "tmp");
+ snprintf(newtmp, sizeof(newtmp), "%s/XXXXXX", tmpdir);
+ tmpfd = mkstemp(newtmp);
+ ast_log(LOG_DEBUG, "newtmp: %s\n", newtmp);
+ if (vmu->volgain < -.001 || vmu->volgain > .001) {
+ snprintf(tmpcmd, sizeof(tmpcmd), "sox -v %.4f %s.%s %s.%s", vmu->volgain, attach, format, newtmp, format);
+ ast_safe_system(tmpcmd);
+ attach = newtmp;
+ ast_log(LOG_DEBUG, "VOLGAIN: Stored at: %s.%s - Level: %.4f - Mailbox: %s\n", attach, format, vmu->volgain, mailbox);
+ }
fprintf(p, "--%s\n", bound);
fprintf(p, "Content-Type: %s%s; name=\"msg%04d.%s\"\n", ctype, format, msgnum, format);
fprintf(p, "Content-Transfer-Encoding: base64\n");
@@ -1880,7 +2025,24 @@
snprintf(fname, sizeof(fname), "%s.%s", attach, format);
base_encode(fname, p);
+#ifdef IMAP_STORAGE
+ /* only attach if necessary */
+ ast_log(LOG_DEBUG, "Before second attachment with format set to:%s\n",format);
+ if (strcmp(format, "gsm")) {
+ fprintf(p, "--%s\n", bound);
+ fprintf(p, "Content-Type: audio/x-gsm; name=\"msg%04d.%s\"\n", msgnum, format);
+ fprintf(p, "Content-Transfer-Encoding: base64\n");
+ fprintf(p, "Content-Description: Voicemail sound attachment.\n");
+ fprintf(p, "Content-Disposition: attachment; filename=\"msg%04d.gsm\"\n\n", msgnum);
+
+ snprintf(fname, sizeof(fname), "%s.gsm", attach);
+ base_encode(fname, p);
+ }
+#endif
fprintf(p, "\n\n--%s--\n.\n", bound);
+ if (tmpfd > -1)
+ close(tmpfd);
+ unlink(newtmp);
}
fclose(p);
snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
@@ -1973,6 +2135,7 @@
return 0;
}
+#ifndef IMAP_STORAGE
static int get_date(char *s, int len)
{
struct tm tm;
@@ -1981,6 +2144,7 @@
localtime_r(&t,&tm);
return strftime(s, len, "%a %b %e %r %Z %Y", &tm);
}
+#endif
static int invent_message(struct ast_channel *chan, char *context, char *ext, int busy, char *ecodes)
{
@@ -2225,7 +2389,205 @@
}
#else
-
+#ifdef IMAP_STORAGE
+static int messagecount(const char *mailbox, int *newmsgs, int *oldmsgs)
+{
+ SEARCHPGM *pgm;
+ SEARCHHEADER *hdr;
+
+ struct ast_vm_user *vmu;
+ struct vm_state *vms_p;
+ char tmp[256]="";
+ char *mb, *cur;
+ char *mailboxnc;
+ char *context;
+ int ret = 0;
+ if (newmsgs)
+ *newmsgs = 0;
+ if (oldmsgs)
+ *oldmsgs = 0;
+
+ ast_log (LOG_DEBUG,"Mailbox is set to %s\n",mailbox);
+ /* If no mailbox, return immediately */
+ if (ast_strlen_zero(mailbox))
+ return 0;
+ if (strchr(mailbox, ',')) {
+ int tmpnew, tmpold;
+ strncpy(tmp, mailbox, sizeof(tmp) - 1);
+ mb = tmp;
+ ret = 0;
+ while((cur = strsep(&mb, ", "))) {
+ if (!ast_strlen_zero(cur)) {
+ if (messagecount(cur, newmsgs ? &tmpnew : NULL, oldmsgs ? &tmpold : NULL))
+ return -1;
+ else {
+ if (newmsgs)
+ *newmsgs += tmpnew;
+ if (oldmsgs)
+ *oldmsgs += tmpold;
+ }
+ }
+ }
+ return 0;
+ }
+
+ strncpy(tmp, mailbox, sizeof(tmp) - 1);
+ context = strchr(tmp, '@');
+ if (context) {
+ *context = '\0';
+ mailboxnc = tmp;
+ context++;
+ } else {
+ context = "default";
+ mailboxnc = (char *)mailbox;
+ }
+
+ /* We have to get the user before we can open the stream! */
+ /*ast_log (LOG_DEBUG,"Before find_user, context is %s and mailbox is %s\n",context,mailbox); */
+ vmu = find_user(NULL, context, mailboxnc);
+ if (vmu == NULL) {
+ ast_log (LOG_ERROR,"Couldn't find mailbox %s in context %s\n",mailboxnc,context);
+ return -1;
+ } else {
+ /* No IMAP account available */
+ if (vmu->imapuser[0] == '\0') {
+ ast_log (LOG_WARNING,"IMAP user not set for mailbox %s\n",vmu->mailbox);
+ return -1;
+ }
+ }
+
+ /* check if someone is accessing this box right now... */
+ vms_p = get_vm_state_by_imapuser(vmu->imapuser,1);
+ if (vms_p == NULL) {
+ vms_p = get_vm_state_by_mailbox(mailboxnc,1);
+ }
+ if (vms_p != NULL) {
+ ast_log (LOG_DEBUG,"Returning before search - user is logged in\n");
+ *newmsgs = vms_p->newmessages;
+ *oldmsgs = vms_p->oldmessages;
+ return 0;
+ }
+
+ /* add one if not there... */
+ vms_p = get_vm_state_by_imapuser(vmu->imapuser,0);
+ if (vms_p == NULL) {
+ vms_p = get_vm_state_by_mailbox(mailboxnc,0);
+ }
+
+ if (vms_p == NULL) {
+ ast_log (LOG_DEBUG,"Adding new vmstate for %s\n",vmu->imapuser);
+ vms_p = (struct vm_state *)malloc(sizeof(struct vm_state));
+ strcpy(vms_p->imapuser,vmu->imapuser);
+ strcpy(vms_p->username,mailboxnc); /* save for access from interactive entry point */
+ vms_p->mailstream = NIL; /* save for access from interactive entry point */
+ ast_log (LOG_DEBUG,"Copied %s to %s\n",vmu->imapuser,vms_p->imapuser);
+ vms_p->updated = 1;
+ vms_p->interactive = 0;
+ /* set mailbox to INBOX! */
+ strncpy(vms_p->curbox, mbox(0), sizeof(vms_p->curbox) - 1);
+ init_vm_state(vms_p);
+ vmstate_insert(vms_p);
+ }
+ if (vms_p->mailstream == NULL)
+ ret = init_mailstream(vms_p);
+ if (vms_p->mailstream == NULL) {
+ ast_log (LOG_ERROR,"Houston we have a problem - IMAP mailstream is NULL\n");
+ return -1;
+ }
+ if (newmsgs && ret==0 && vms_p->updated==1 ) {
+ pgm = mail_newsearchpgm ();
+ hdr = mail_newsearchheader ("X-Asterisk-VM-Extension", (char *)mailboxnc);
+ pgm->header = hdr;
+ pgm->unseen = 1;
+ pgm->seen = 0;
+ pgm->undeleted = 1;
+ pgm->deleted = 0;
+
+ vms_p->vmArrayIndex = 0;
+
+ ast_log (LOG_DEBUG,"Before search of mailbox %s for NEW messages\n",vms_p->mailstream->mailbox);
+ mail_search_full (vms_p->mailstream, NULL, pgm, NIL);
+ ast_log (LOG_DEBUG,"After search\n");
+ *newmsgs = vms_p->vmArrayIndex;
+ vms_p->newmessages = vms_p->vmArrayIndex;
+ ast_log (LOG_DEBUG,"There are %d NEW messages\n",vms_p->newmessages);
+ }
+ if (oldmsgs && ret==0 && vms_p->updated==1 ) {
+ pgm = mail_newsearchpgm ();
+ hdr = mail_newsearchheader ("X-Asterisk-VM-Extension", (char *)mailboxnc);
+ pgm->header = hdr;
+ pgm->unseen = 0;
+ pgm->seen = 1;
+ pgm->deleted = 0;
+ pgm->undeleted = 1;
+
+ vms_p->vmArrayIndex = 0;
+
+ ast_log (LOG_DEBUG,"Before search of mailbox %s for OLD messages\n",vms_p->mailstream->mailbox);
+ mail_search_full (vms_p->mailstream, NULL, pgm, NIL);
+ *oldmsgs = vms_p->vmArrayIndex;
+ vms_p->oldmessages = vms_p->vmArrayIndex;
+ ast_log (LOG_DEBUG,"There are %d OLD messages\n",vms_p->oldmessages);
+ }
+ if (vms_p->updated == 1) { /* changes, so we did the searches above */
+ vms_p->updated = 0;
+ } else if (vms_p->updated > 1) { /* decrement delay count */
+ vms_p->updated--;
+ } else { /* no changes, so don't search */
+ ast_log (LOG_DEBUG,"Calling mail_ping on mailbox %s\n",vms_p->mailstream->mailbox);
+ mail_ping(vms_p->mailstream);
+ /* Keep the old data */
+ *newmsgs = vms_p->newmessages;
+ *oldmsgs = vms_p->oldmessages;
+ }
+ return 0;
+ }
+#else
+
+static int messagecount(const char *context, const char *mailbox, const char *folder)
+{
+ return __has_voicemail(context, mailbox, folder, 0);
+}
+
+#endif
+#endif
+
+/* copy message only used by file storage */
+static int copy_message(struct ast_channel *chan, struct ast_vm_user *vmu, int imbox, int msgnum, long duration, struct ast_vm_user *recip, char *fmt)
+{
+ char fromdir[256], todir[256], frompath[256], topath[256];
+ const char *frombox = mbox(imbox);
+ int recipmsgnum;
+
+ ast_log(LOG_NOTICE, "Copying message from %s@%s to %s@%s\n", vmu->mailbox, vmu->context, recip->mailbox, recip->context);
+
+ create_dirpath(todir, sizeof(todir), recip->context, recip->mailbox, "INBOX");
+
+ make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, frombox);
+ make_file(frompath, sizeof(frompath), fromdir, msgnum);
+
+ if (vm_lock_path(todir))
+ return ERROR_LOCK_PATH;
+
+ recipmsgnum = 0;
+ do {
+ make_file(topath, sizeof(topath), todir, recipmsgnum);
+ if (!EXISTS(todir, recipmsgnum, topath, chan->language))
+ break;
+ recipmsgnum++;
+ } while (recipmsgnum < recip->maxmsg);
+ if (recipmsgnum < recip->maxmsg) {
+ COPY(fromdir, msgnum, todir, recipmsgnum, recip->mailbox, recip->context, frompath, topath);
+ } else {
+ ast_log(LOG_ERROR, "Recipient mailbox %s@%s is full\n", recip->mailbox, recip->context);
+ }
+ ast_unlock_path(todir);
+ notify_new_message(chan, recip, recipmsgnum, duration, fmt, chan->cid.cid_num, chan->cid.cid_name);
+
+ return 0;
+}
+
+#ifndef ODBC_STORAGE
static int __has_voicemail(const char *context, const char *mailbox, const char *folder, int shortcircuit)
{
DIR *dir;
@@ -2256,6 +2618,7 @@
return ret;
}
+
static int has_voicemail(const char *mailbox, const char *folder)
{
char tmp[256], *tmp2 = tmp, *mbox, *context;
@@ -2271,10 +2634,6 @@
return 0;
}
-static int messagecount(const char *context, const char *mailbox, const char *folder)
-{
- return __has_voicemail(context, mailbox, folder, 0);
-}
static int inboxcount(const char *mailbox, int *newmsgs, int *oldmsgs)
{
@@ -2324,42 +2683,6 @@
#endif
-static int notify_new_message(struct ast_channel *chan, struct ast_vm_user *vmu, int msgnum, long duration, char *fmt, char *cidnum, char *cidname);
-
-static int copy_message(struct ast_channel *chan, struct ast_vm_user *vmu, int imbox, int msgnum, long duration, struct ast_vm_user *recip, char *fmt)
-{
- char fromdir[256], todir[256], frompath[256], topath[256];
- const char *frombox = mbox(imbox);
- int recipmsgnum;
-
- ast_log(LOG_NOTICE, "Copying message from %s@%s to %s@%s\n", vmu->mailbox, vmu->context, recip->mailbox, recip->context);
-
- create_dirpath(todir, sizeof(todir), recip->context, recip->mailbox, "INBOX");
-
- make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, frombox);
- make_file(frompath, sizeof(frompath), fromdir, msgnum);
-
- if (vm_lock_path(todir))
- return ERROR_LOCK_PATH;
-
- recipmsgnum = 0;
- do {
- make_file(topath, sizeof(topath), todir, recipmsgnum);
- if (!EXISTS(todir, recipmsgnum, topath, chan->language))
- break;
- recipmsgnum++;
- } while (recipmsgnum < recip->maxmsg);
- if (recipmsgnum < recip->maxmsg) {
- COPY(fromdir, msgnum, todir, recipmsgnum, recip->mailbox, recip->context, frompath, topath);
- } else {
- ast_log(LOG_ERROR, "Recipient mailbox %s@%s is full\n", recip->mailbox, recip->context);
- }
- ast_unlock_path(todir);
- notify_new_message(chan, recip, recipmsgnum, duration, fmt, chan->cid.cid_num, chan->cid.cid_name);
-
- return 0;
-}
-
static void run_externnotify(char *context, char *extension)
{
char arguments[255];
@@ -2407,16 +2730,22 @@
static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_options *options)
{
- char txtfile[256], tmptxtfile[256];
+#ifdef IMAP_STORAGE
+ int newmsgs, oldmsgs;
+ struct vm_state *vms;
+#else
+ char tmptxtfile[256], txtfile[256];
char callerid[256];
FILE *txt;
- int res = 0, txtdes;
+ char date[256];
+ int txtdes;
+#endif
+ int res = 0;
int msgnum;
int duration = 0;
int ausemacro = 0;
int ousemacro = 0;
int ouseexten = 0;
- char date[256];
char dir[256], tmpdir[260];
char fn[256];
char prefile[256]="";
@@ -2445,6 +2774,7 @@
category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY");
+ ast_log(LOG_DEBUG, "Before find_user\n");
if (!(vmu = find_user(&svm, context, ext))) {
ast_log(LOG_WARNING, "No entry in voicemail config file for '%s'\n", ext);
if (ast_test_flag(options, OPT_PRIORITY_JUMP) || ast_opt_priority_jumping)
@@ -2483,8 +2813,8 @@
ouseexten = 1;
}
else if (!ast_strlen_zero(chan->macrocontext) && ast_exists_extension(chan, chan->macrocontext, "o", 1, chan->cid.cid_num)) {
- strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
- ousemacro = 1;
+ strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
+ ousemacro = 1;
}
}
@@ -2574,6 +2904,55 @@
if (!ast_strlen_zero(fmt)) {
msgnum = 0;
+#ifdef IMAP_STORAGE
+ /* Is ext a mailbox? */
+ /* must open stream for this user to get info! */
+ vms = get_vm_state_by_mailbox(ext,0);
+ if (vms != NULL) {
+ ast_log(LOG_DEBUG, "Using vm_state, interactive set to %d.\n",vms->interactive);
+ newmsgs = vms->newmessages++;
+ oldmsgs = vms->oldmessages;
+ } else {
+ ast_log(LOG_DEBUG, "About to call messagecount.\n");
+ res = messagecount(ext, &newmsgs, &oldmsgs);
+ if(res < 0) {
+ ast_log(LOG_NOTICE,"Can not leave voicemail, unable to count messages\n");
+ return -1;
+ }
+ }
+ /* here is a big difference! We add one to it later */
+ msgnum = newmsgs + oldmsgs;
+ ast_log(LOG_NOTICE, "Messagecount set to %d\n",msgnum);
+ sprintf(fn, "%s/msg%s%04d", TMP, vmu->mailbox, msgnum);
+ /* set variable for compatability */
+ pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", "IMAP_STORAGE");
+
+ /* Check if mailbox is full */
+ if (vms->quota_usage >= vms->quota_limit) {
+ ast_log(LOG_DEBUG, "*** QUOTA EXCEEDED!!\n");
+ ast_play_and_wait(chan, "vm-mailboxfull");
+ return -1;
+ }
+
+ /* play beep */
+ res = ast_streamfile(chan, "beep", chan->language);
+ if (!res)
+ res = ast_waitstream(chan, "");
+ /* play_record_review does recording and verify */
+ ast_log(LOG_DEBUG, "About to record message in file %s\n",fn);
+ res = play_record_review(chan, NULL, fn, vmmaxmessage, fmt, 1, vmu, &duration, dir, options->record_gain);
+ if (res == '0') {
+ goto transfer;
+ }
+ if (res > 0) res = 0;
+
+ if (duration < vmminmessage) {
+ if (option_verbose > 2)
+ ast_verbose( VERBOSE_PREFIX_3 "Recording was %d seconds long but needs to be at least %d - abandoning\n", duration, vmminmessage);
+ goto leave_vm_out;
+ }
+ notify_new_message(chan, vmu, msgnum, duration, fmt, chan->cid.cid_num, chan->cid.cid_name);
+#else
if (count_messages(vmu, dir) >= vmu->maxmsg) {
res = ast_streamfile(chan, "vm-mailboxfull", chan->language);
if (!res)
@@ -2599,7 +2978,7 @@
/* Unless we're *really* silent, try to send the beep */
res = ast_stream_and_wait(chan, "beep", chan->language, "");
}
-
+
/* Store information */
txt = fdopen(txtdes, "w+");
if (txt) {
@@ -2631,12 +3010,11 @@
} else
ast_log(LOG_WARNING, "Error opening text file for output\n");
res = play_record_review(chan, NULL, tmptxtfile, vmmaxmessage, fmt, 1, vmu, &duration, NULL, options->record_gain);
-
+
if (txt) {
if (duration < vmminmessage) {
if (option_verbose > 2)
ast_verbose( VERBOSE_PREFIX_3 "Recording was %d seconds long but needs to be at least %d - abandoning\n", duration, vmminmessage);
- fclose(txt);
ast_filedelete(tmptxtfile, NULL);
[... 5302 lines stripped ...]
More information about the asterisk-commits
mailing list