diff --git a/conf/autoload_configs/voicemail.conf.xml b/conf/autoload_configs/voicemail.conf.xml index f573d99173..ae5cac7e42 100644 --- a/conf/autoload_configs/voicemail.conf.xml +++ b/conf/autoload_configs/voicemail.conf.xml @@ -2,7 +2,7 @@ - + @@ -31,18 +31,20 @@ + + - To: <${voicemail_email}> -Subject: Voicemail from ${voicemail_caller_id_name} ${voicemail_caller_id_number} +Subject: ${voicemail_message_len} sec Voicemail from ${voicemail_caller_id_name} ${voicemail_caller_id_number} X-Priority: ${voicemail_priority} X-Mailer: FreeSWITCH ]]> diff --git a/conf/mime.types b/conf/mime.types new file mode 100644 index 0000000000..34d5fc9055 --- /dev/null +++ b/conf/mime.types @@ -0,0 +1,983 @@ +# This is a comment. I love comments. + +# This file controls what Internet media types are sent to the client for +# given file extension(s). Sending the correct media type to the client +# is important so they know how to handle the content of the file. +# Extra types can either be added here or by using an AddType directive +# in your config files. For more information about Internet media types, +# please read RFC 2045, 2046, 2047, 2048, and 2077. The Internet media type +# registry is at . + +# MIME type Extensions +application/activemessage +application/andrew-inset ez +application/applefile +application/atom+xml atom +application/atomcat+xml atomcat +application/atomicmail +application/atomsvc+xml atomsvc +application/auth-policy+xml +application/batch-smtp +application/beep+xml +application/cals-1840 +application/ccxml+xml ccxml +application/cellml+xml +application/cnrp+xml +application/commonground +application/conference-info+xml +application/cpl+xml +application/csta+xml +application/cstadata+xml +application/cybercash +application/davmount+xml davmount +application/dca-rft +application/dec-dx +application/dialog-info+xml +application/dicom +application/dns +application/dvcs +application/ecmascript ecma +application/edi-consent +application/edi-x12 +application/edifact +application/epp+xml +application/eshop +application/fastinfoset +application/fastsoap +application/fits +application/font-tdpfr pfr +application/h224 +application/http +application/hyperstudio stk +application/iges +application/im-iscomposing+xml +application/index +application/index.cmd +application/index.obj +application/index.response +application/index.vnd +application/iotp +application/ipp +application/isup +application/javascript js +application/json json +application/kpml-request+xml +application/kpml-response+xml +application/mac-binhex40 hqx +application/mac-compactpro cpt +application/macwriteii +application/marc mrc +application/mathematica ma nb mb +application/mathml+xml mathml +application/mbms-associated-procedure-description+xml +application/mbms-deregister+xml +application/mbms-envelope+xml +application/mbms-msk+xml +application/mbms-msk-response+xml +application/mbms-protection-description+xml +application/mbms-reception-report+xml +application/mbms-register+xml +application/mbms-register-response+xml +application/mbms-user-service-description+xml +application/mbox mbox +application/mediaservercontrol+xml mscml +application/mikey +application/mp4 mp4s +application/mpeg4-generic +application/mpeg4-iod +application/mpeg4-iod-xmt +application/msword doc dot +application/mxf mxf +application/nasdata +application/news-message-id +application/news-transmission +application/nss +application/ocsp-request +application/ocsp-response +application/octet-stream bin dms lha lzh class so iso dmg dist distz pkg bpk dump elc +application/oda oda +application/oebps-package+xml +application/ogg ogg +application/parityfec +application/pdf pdf +application/pgp-encrypted pgp +application/pgp-keys +application/pgp-signature asc sig +application/pics-rules prf +application/pidf+xml +application/pkcs10 p10 +application/pkcs7-mime p7m p7c +application/pkcs7-signature p7s +application/pkix-cert cer +application/pkix-crl crl +application/pkix-pkipath pkipath +application/pkixcmp pki +application/pls+xml pls +application/poc-settings+xml +application/postscript ai eps ps +application/prs.alvestrand.titrax-sheet +application/prs.cww cww +application/prs.nprend +application/prs.plucker +application/qsig +application/rdf+xml rdf +application/reginfo+xml rif +application/relax-ng-compact-syntax rnc +application/remote-printing +application/resource-lists+xml rl +application/riscos +application/rlmi+xml +application/rls-services+xml rs +application/rsd+xml rsd +application/rss+xml rss +application/rtf rtf +application/rtx +application/samlassertion+xml +application/samlmetadata+xml +application/sbml+xml sbml +application/sdp sdp +application/set-payment +application/set-payment-initiation setpay +application/set-registration +application/set-registration-initiation setreg +application/sgml +application/sgml-open-catalog +application/shf+xml shf +application/sieve +application/simple-filter+xml +application/simple-message-summary +application/simplesymbolcontainer +application/slate +application/smil +application/smil+xml smi smil +application/soap+fastinfoset +application/soap+xml +application/spirits-event+xml +application/srgs gram +application/srgs+xml grxml +application/ssml+xml ssml +application/timestamp-query +application/timestamp-reply +application/tve-trigger +application/vemmi +application/vividence.scriptfile +application/vnd.3gpp.bsf+xml +application/vnd.3gpp.pic-bw-large plb +application/vnd.3gpp.pic-bw-small psb +application/vnd.3gpp.pic-bw-var pvb +application/vnd.3gpp.sms +application/vnd.3gpp2.bcmcsinfo+xml +application/vnd.3gpp2.sms +application/vnd.3m.post-it-notes pwn +application/vnd.accpac.simply.aso aso +application/vnd.accpac.simply.imp imp +application/vnd.acucobol acu +application/vnd.acucorp atc acutc +application/vnd.adobe.xdp+xml xdp +application/vnd.adobe.xfdf xfdf +application/vnd.aether.imp +application/vnd.amiga.ami ami +application/vnd.anser-web-certificate-issue-initiation cii +application/vnd.anser-web-funds-transfer-initiation fti +application/vnd.antix.game-component atx +application/vnd.apple.installer+xml mpkg +application/vnd.audiograph aep +application/vnd.autopackage +application/vnd.avistar+xml +application/vnd.blueice.multipass mpm +application/vnd.bmi bmi +application/vnd.businessobjects rep +application/vnd.cab-jscript +application/vnd.canon-cpdl +application/vnd.canon-lips +application/vnd.cendio.thinlinc.clientconf +application/vnd.chemdraw+xml cdxml +application/vnd.chipnuts.karaoke-mmd mmd +application/vnd.cinderella cdy +application/vnd.cirpack.isdn-ext +application/vnd.claymore cla +application/vnd.clonk.c4group c4g c4d c4f c4p c4u +application/vnd.commerce-battelle +application/vnd.commonspace csp cst +application/vnd.contact.cmsg cdbcmsg +application/vnd.cosmocaller cmc +application/vnd.crick.clicker clkx +application/vnd.crick.clicker.keyboard clkk +application/vnd.crick.clicker.palette clkp +application/vnd.crick.clicker.template clkt +application/vnd.crick.clicker.wordbank clkw +application/vnd.criticaltools.wbs+xml wbs +application/vnd.ctc-posml pml +application/vnd.cups-pdf +application/vnd.cups-postscript +application/vnd.cups-ppd ppd +application/vnd.cups-raster +application/vnd.cups-raw +application/vnd.curl curl +application/vnd.cybank +application/vnd.data-vision.rdz rdz +application/vnd.denovo.fcselayout-link fe_launch +application/vnd.dna dna +application/vnd.dolby.mlp mlp +application/vnd.dpgraph dpg +application/vnd.dreamfactory dfac +application/vnd.dvb.esgcontainer +application/vnd.dvb.ipdcesgaccess +application/vnd.dxr +application/vnd.ecdis-update +application/vnd.ecowin.chart mag +application/vnd.ecowin.filerequest +application/vnd.ecowin.fileupdate +application/vnd.ecowin.series +application/vnd.ecowin.seriesrequest +application/vnd.ecowin.seriesupdate +application/vnd.enliven nml +application/vnd.epson.esf esf +application/vnd.epson.msf msf +application/vnd.epson.quickanime qam +application/vnd.epson.salt slt +application/vnd.epson.ssf ssf +application/vnd.ericsson.quickcall +application/vnd.eszigno3+xml es3 et3 +application/vnd.eudora.data +application/vnd.ezpix-album ez2 +application/vnd.ezpix-package ez3 +application/vnd.fdf fdf +application/vnd.ffsns +application/vnd.fints +application/vnd.flographit gph +application/vnd.fluxtime.clip ftc +application/vnd.framemaker fm frame maker +application/vnd.frogans.fnc fnc +application/vnd.frogans.ltf ltf +application/vnd.fsc.weblaunch fsc +application/vnd.fujitsu.oasys oas +application/vnd.fujitsu.oasys2 oa2 +application/vnd.fujitsu.oasys3 oa3 +application/vnd.fujitsu.oasysgp fg5 +application/vnd.fujitsu.oasysprs bh2 +application/vnd.fujixerox.art-ex +application/vnd.fujixerox.art4 +application/vnd.fujixerox.hbpl +application/vnd.fujixerox.ddd ddd +application/vnd.fujixerox.docuworks xdw +application/vnd.fujixerox.docuworks.binder xbd +application/vnd.fut-misnet +application/vnd.fuzzysheet fzs +application/vnd.genomatix.tuxedo txd +application/vnd.google-earth.kml+xml kml +application/vnd.google-earth.kmz kmz +application/vnd.grafeq gqf gqs +application/vnd.gridmp +application/vnd.groove-account gac +application/vnd.groove-help ghf +application/vnd.groove-identity-message gim +application/vnd.groove-injector grv +application/vnd.groove-tool-message gtm +application/vnd.groove-tool-template tpl +application/vnd.groove-vcard vcg +application/vnd.handheld-entertainment+xml zmm +application/vnd.hbci hbci +application/vnd.hcl-bireports +application/vnd.hhe.lesson-player les +application/vnd.hp-hpgl hpgl +application/vnd.hp-hpid hpid +application/vnd.hp-hps hps +application/vnd.hp-jlyt jlt +application/vnd.hp-pcl pcl +application/vnd.hp-pclxl pclxl +application/vnd.httphone +application/vnd.hzn-3d-crossword x3d +application/vnd.ibm.afplinedata +application/vnd.ibm.electronic-media +application/vnd.ibm.minipay mpy +application/vnd.ibm.modcap afp listafp list3820 +application/vnd.ibm.rights-management irm +application/vnd.ibm.secure-container sc +application/vnd.igloader igl +application/vnd.immervision-ivp ivp +application/vnd.immervision-ivu ivu +application/vnd.informedcontrol.rms+xml +application/vnd.intercon.formnet xpw xpx +application/vnd.intertrust.digibox +application/vnd.intertrust.nncp +application/vnd.intu.qbo qbo +application/vnd.intu.qfx qfx +application/vnd.ipunplugged.rcprofile rcprofile +application/vnd.irepository.package+xml irp +application/vnd.is-xpr xpr +application/vnd.jam jam +application/vnd.japannet-directory-service +application/vnd.japannet-jpnstore-wakeup +application/vnd.japannet-payment-wakeup +application/vnd.japannet-registration +application/vnd.japannet-registration-wakeup +application/vnd.japannet-setstore-wakeup +application/vnd.japannet-verification +application/vnd.japannet-verification-wakeup +application/vnd.jcp.javame.midlet-rms rms +application/vnd.jisp jisp +application/vnd.kahootz ktz ktr +application/vnd.kde.karbon karbon +application/vnd.kde.kchart chrt +application/vnd.kde.kformula kfo +application/vnd.kde.kivio flw +application/vnd.kde.kontour kon +application/vnd.kde.kpresenter kpr kpt +application/vnd.kde.kspread ksp +application/vnd.kde.kword kwd kwt +application/vnd.kenameaapp htke +application/vnd.kidspiration kia +application/vnd.kinar kne knp +application/vnd.koan skp skd skt skm +application/vnd.liberty-request+xml +application/vnd.llamagraphics.life-balance.desktop lbd +application/vnd.llamagraphics.life-balance.exchange+xml lbe +application/vnd.lotus-1-2-3 123 +application/vnd.lotus-approach apr +application/vnd.lotus-freelance pre +application/vnd.lotus-notes nsf +application/vnd.lotus-organizer org +application/vnd.lotus-screencam scm +application/vnd.lotus-wordpro lwp +application/vnd.macports.portpkg portpkg +application/vnd.marlin.drm.actiontoken+xml +application/vnd.marlin.drm.conftoken+xml +application/vnd.marlin.drm.mdcf +application/vnd.mcd mcd +application/vnd.medcalcdata mc1 +application/vnd.mediastation.cdkey cdkey +application/vnd.meridian-slingshot +application/vnd.mfer mwf +application/vnd.mfmp mfm +application/vnd.micrografx.flo flo +application/vnd.micrografx.igx igx +application/vnd.mif mif +application/vnd.minisoft-hp3000-save +application/vnd.mitsubishi.misty-guard.trustweb +application/vnd.mobius.daf daf +application/vnd.mobius.dis dis +application/vnd.mobius.mbk mbk +application/vnd.mobius.mqy mqy +application/vnd.mobius.msl msl +application/vnd.mobius.plc plc +application/vnd.mobius.txf txf +application/vnd.mophun.application mpn +application/vnd.mophun.certificate mpc +application/vnd.motorola.flexsuite +application/vnd.motorola.flexsuite.adsi +application/vnd.motorola.flexsuite.fis +application/vnd.motorola.flexsuite.gotap +application/vnd.motorola.flexsuite.kmr +application/vnd.motorola.flexsuite.ttc +application/vnd.motorola.flexsuite.wem +application/vnd.mozilla.xul+xml xul +application/vnd.ms-artgalry cil +application/vnd.ms-asf asf +application/vnd.ms-cab-compressed cab +application/vnd.ms-excel xls xlm xla xlc xlt xlw +application/vnd.ms-fontobject eot +application/vnd.ms-htmlhelp chm +application/vnd.ms-ims ims +application/vnd.ms-lrm lrm +application/vnd.ms-playready.initiator+xml +application/vnd.ms-powerpoint ppt pps pot +application/vnd.ms-project mpp mpt +application/vnd.ms-tnef +application/vnd.ms-wmdrm.lic-chlg-req +application/vnd.ms-wmdrm.lic-resp +application/vnd.ms-wmdrm.meter-chlg-req +application/vnd.ms-wmdrm.meter-resp +application/vnd.ms-works wps wks wcm wdb +application/vnd.ms-wpl wpl +application/vnd.ms-xpsdocument xps +application/vnd.mseq mseq +application/vnd.msign +application/vnd.music-niff +application/vnd.musician mus +application/vnd.ncd.control +application/vnd.nervana +application/vnd.netfpx +application/vnd.neurolanguage.nlu nlu +application/vnd.noblenet-directory nnd +application/vnd.noblenet-sealer nns +application/vnd.noblenet-web nnw +application/vnd.nokia.catalogs +application/vnd.nokia.conml+wbxml +application/vnd.nokia.conml+xml +application/vnd.nokia.isds-radio-presets +application/vnd.nokia.iptv.config+xml +application/vnd.nokia.landmark+wbxml +application/vnd.nokia.landmark+xml +application/vnd.nokia.landmarkcollection+xml +application/vnd.nokia.n-gage.ac+xml +application/vnd.nokia.n-gage.data ngdat +application/vnd.nokia.n-gage.symbian.install n-gage +application/vnd.nokia.ncd +application/vnd.nokia.pcd+wbxml +application/vnd.nokia.pcd+xml +application/vnd.nokia.radio-preset rpst +application/vnd.nokia.radio-presets rpss +application/vnd.novadigm.edm edm +application/vnd.novadigm.edx edx +application/vnd.novadigm.ext ext +application/vnd.oasis.opendocument.chart odc +application/vnd.oasis.opendocument.chart-template otc +application/vnd.oasis.opendocument.formula odf +application/vnd.oasis.opendocument.formula-template otf +application/vnd.oasis.opendocument.graphics odg +application/vnd.oasis.opendocument.graphics-template otg +application/vnd.oasis.opendocument.image odi +application/vnd.oasis.opendocument.image-template oti +application/vnd.oasis.opendocument.presentation odp +application/vnd.oasis.opendocument.presentation-template otp +application/vnd.oasis.opendocument.spreadsheet ods +application/vnd.oasis.opendocument.spreadsheet-template ots +application/vnd.oasis.opendocument.text odt +application/vnd.oasis.opendocument.text-master otm +application/vnd.oasis.opendocument.text-template ott +application/vnd.oasis.opendocument.text-web oth +application/vnd.obn +application/vnd.olpc-sugar xo +application/vnd.oma-scws-config +application/vnd.oma-scws-http-request +application/vnd.oma-scws-http-response +application/vnd.oma.bcast.associated-procedure-parameter+xml +application/vnd.oma.bcast.drm-trigger+xml +application/vnd.oma.bcast.imd+xml +application/vnd.oma.bcast.notification+xml +application/vnd.oma.bcast.sgboot +application/vnd.oma.bcast.sgdd+xml +application/vnd.oma.bcast.sgdu +application/vnd.oma.bcast.simple-symbol-container +application/vnd.oma.bcast.smartcard-trigger+xml +application/vnd.oma.bcast.sprov+xml +application/vnd.oma.dd2+xml dd2 +application/vnd.oma.drm.risd+xml +application/vnd.oma.group-usage-list+xml +application/vnd.oma.poc.groups+xml +application/vnd.oma.xcap-directory+xml +application/vnd.omads-email+xml +application/vnd.omads-file+xml +application/vnd.omads-folder+xml +application/vnd.omaloc-supl-init +application/vnd.openofficeorg.extension oxt +application/vnd.osa.netdeploy +application/vnd.osgi.dp dp +application/vnd.otps.ct-kip+xml +application/vnd.palm prc pdb pqa oprc +application/vnd.paos.xml +application/vnd.pg.format str +application/vnd.pg.osasli ei6 +application/vnd.piaccess.application-licence +application/vnd.picsel efif +application/vnd.poc.group-advertisement+xml +application/vnd.pocketlearn plf +application/vnd.powerbuilder6 pbd +application/vnd.powerbuilder6-s +application/vnd.powerbuilder7 +application/vnd.powerbuilder7-s +application/vnd.powerbuilder75 +application/vnd.powerbuilder75-s +application/vnd.preminet +application/vnd.previewsystems.box box +application/vnd.proteus.magazine mgz +application/vnd.publishare-delta-tree qps +application/vnd.pvi.ptid1 ptid +application/vnd.pwg-multiplexed +application/vnd.pwg-xhtml-print+xml +application/vnd.qualcomm.brew-app-res +application/vnd.quark.quarkxpress qxd qxt qwd qwt qxl qxb +application/vnd.rapid +application/vnd.recordare.musicxml mxl +application/vnd.recordare.musicxml+xml +application/vnd.renlearn.rlprint +application/vnd.rn-realmedia rm +application/vnd.ruckus.download +application/vnd.s3sms +application/vnd.scribus +application/vnd.sealed.3df +application/vnd.sealed.csf +application/vnd.sealed.doc +application/vnd.sealed.eml +application/vnd.sealed.mht +application/vnd.sealed.net +application/vnd.sealed.ppt +application/vnd.sealed.tiff +application/vnd.sealed.xls +application/vnd.sealedmedia.softseal.html +application/vnd.sealedmedia.softseal.pdf +application/vnd.seemail see +application/vnd.sema sema +application/vnd.semd semd +application/vnd.semf semf +application/vnd.shana.informed.formdata ifm +application/vnd.shana.informed.formtemplate itp +application/vnd.shana.informed.interchange iif +application/vnd.shana.informed.package ipk +application/vnd.simtech-mindmapper twd twds +application/vnd.smaf mmf +application/vnd.solent.sdkm+xml sdkm sdkd +application/vnd.spotfire.dxp dxp +application/vnd.spotfire.sfs sfs +application/vnd.sss-cod +application/vnd.sss-dtf +application/vnd.sss-ntf +application/vnd.street-stream +application/vnd.sun.wadl+xml +application/vnd.sus-calendar sus susp +application/vnd.svd svd +application/vnd.swiftview-ics +application/vnd.syncml+xml xsm +application/vnd.syncml.dm+wbxml bdm +application/vnd.syncml.dm+xml xdm +application/vnd.syncml.ds.notification +application/vnd.tao.intent-module-archive tao +application/vnd.tmobile-livetv tmo +application/vnd.trid.tpt tpt +application/vnd.triscape.mxs mxs +application/vnd.trueapp tra +application/vnd.truedoc +application/vnd.ufdl ufd ufdl +application/vnd.uiq.theme utz +application/vnd.umajin umj +application/vnd.unity unityweb +application/vnd.uoml+xml uoml +application/vnd.uplanet.alert +application/vnd.uplanet.alert-wbxml +application/vnd.uplanet.bearer-choice +application/vnd.uplanet.bearer-choice-wbxml +application/vnd.uplanet.cacheop +application/vnd.uplanet.cacheop-wbxml +application/vnd.uplanet.channel +application/vnd.uplanet.channel-wbxml +application/vnd.uplanet.list +application/vnd.uplanet.list-wbxml +application/vnd.uplanet.listcmd +application/vnd.uplanet.listcmd-wbxml +application/vnd.uplanet.signal +application/vnd.vcx vcx +application/vnd.vd-study +application/vnd.vectorworks +application/vnd.vidsoft.vidconference +application/vnd.visio vsd vst vss vsw +application/vnd.visionary vis +application/vnd.vividence.scriptfile +application/vnd.vsf vsf +application/vnd.wap.sic +application/vnd.wap.slc +application/vnd.wap.wbxml wbxml +application/vnd.wap.wmlc wmlc +application/vnd.wap.wmlscriptc wmlsc +application/vnd.webturbo wtb +application/vnd.wfa.wsc +application/vnd.wordperfect wpd +application/vnd.wqd wqd +application/vnd.wrq-hp3000-labelled +application/vnd.wt.stf stf +application/vnd.wv.csp+wbxml +application/vnd.wv.csp+xml +application/vnd.wv.ssp+xml +application/vnd.xara xar +application/vnd.xfdl xfdl +application/vnd.xmpie.cpkg +application/vnd.xmpie.dpkg +application/vnd.xmpie.plan +application/vnd.xmpie.ppkg +application/vnd.xmpie.xlim +application/vnd.yamaha.hv-dic hvd +application/vnd.yamaha.hv-script hvs +application/vnd.yamaha.hv-voice hvp +application/vnd.yamaha.smaf-audio saf +application/vnd.yamaha.smaf-phrase spf +application/vnd.yellowriver-custom-menu cmp +application/vnd.zzazz.deck+xml zaz +application/voicexml+xml vxml +application/watcherinfo+xml +application/whoispp-query +application/whoispp-response +application/winhlp hlp +application/wita +application/wordperfect5.1 +application/wsdl+xml wsdl +application/wspolicy+xml wspolicy +application/x-ace-compressed ace +application/x-bcpio bcpio +application/x-bittorrent torrent +application/x-bzip bz +application/x-bzip2 bz2 boz +application/x-cdlink vcd +application/x-chat chat +application/x-chess-pgn pgn +application/x-compress +application/x-cpio cpio +application/x-csh csh +application/x-director dcr dir dxr fgd +application/x-dvi dvi +application/x-futuresplash spl +application/x-gtar gtar +application/x-gzip +application/x-hdf hdf +application/x-latex latex +application/x-ms-wmd wmd +application/x-ms-wmz wmz +application/x-msaccess mdb +application/x-msbinder obd +application/x-mscardfile crd +application/x-msclip clp +application/x-msdownload exe dll com bat msi +application/x-msmediaview mvb m13 m14 +application/x-msmetafile wmf +application/x-msmoney mny +application/x-mspublisher pub +application/x-msschedule scd +application/x-msterminal trm +application/x-mswrite wri +application/x-netcdf nc cdf +application/x-pkcs12 p12 pfx +application/x-pkcs7-certificates p7b spc +application/x-pkcs7-certreqresp p7r +application/x-rar-compressed rar +application/x-sh sh +application/x-shar shar +application/x-shockwave-flash swf +application/x-stuffit sit +application/x-stuffitx sitx +application/x-sv4cpio sv4cpio +application/x-sv4crc sv4crc +application/x-tar tar +application/x-tcl tcl +application/x-tex tex +application/x-texinfo texinfo texi +application/x-ustar ustar +application/x-wais-source src +application/x-x509-ca-cert der crt +application/x400-bp +application/xcap-att+xml +application/xcap-caps+xml +application/xcap-el+xml +application/xcap-error+xml +application/xcap-ns+xml +application/xenc+xml xenc +application/xhtml+xml xhtml xht +application/xml xml xsl +application/xml-dtd dtd +application/xml-external-parsed-entity +application/xmpp+xml +application/xop+xml xop +application/xslt+xml xslt +application/xspf+xml xspf +application/xv+xml mxml xhvml xvml xvm +application/zip zip +audio/32kadpcm +audio/3gpp +audio/3gpp2 +audio/ac3 +audio/amr +audio/amr-wb +audio/amr-wb+ +audio/asc +audio/basic au snd +audio/bv16 +audio/bv32 +audio/clearmode +audio/cn +audio/dat12 +audio/dls +audio/dsr-es201108 +audio/dsr-es202050 +audio/dsr-es202211 +audio/dsr-es202212 +audio/dvi4 +audio/eac3 +audio/evrc +audio/evrc-qcp +audio/evrc0 +audio/evrc1 +audio/evrcb +audio/evrcb0 +audio/evrcb1 +audio/g722 +audio/g7221 +audio/g723 +audio/g726-16 +audio/g726-24 +audio/g726-32 +audio/g726-40 +audio/g728 +audio/g729 +audio/g7291 +audio/g729d +audio/g729e +audio/gsm +audio/gsm-efr +audio/ilbc +audio/l16 +audio/l20 +audio/l24 +audio/l8 +audio/lpc +audio/midi mid midi kar rmi +audio/mobile-xmf +audio/mp4 mp4a +audio/mp4a-latm +audio/mpa +audio/mpa-robust +audio/mpeg mpga mp2 mp2a mp3 m2a m3a +audio/mpeg4-generic +audio/parityfec +audio/pcma +audio/pcmu +audio/prs.sid +audio/qcelp +audio/red +audio/rtp-enc-aescm128 +audio/rtp-midi +audio/rtx +audio/smv +audio/smv0 +audio/smv-qcp +audio/sp-midi +audio/t140c +audio/t38 +audio/telephone-event +audio/tone +audio/vdvi +audio/vmr-wb +audio/vnd.3gpp.iufp +audio/vnd.4sb +audio/vnd.audiokoz +audio/vnd.celp +audio/vnd.cisco.nse +audio/vnd.cmles.radio-events +audio/vnd.cns.anp1 +audio/vnd.cns.inf1 +audio/vnd.digital-winds eol +audio/vnd.dlna.adts +audio/vnd.dolby.mlp +audio/vnd.everad.plj +audio/vnd.hns.audio +audio/vnd.lucent.voice lvp +audio/vnd.nokia.mobile-xmf +audio/vnd.nortel.vbk +audio/vnd.nuera.ecelp4800 ecelp4800 +audio/vnd.nuera.ecelp7470 ecelp7470 +audio/vnd.nuera.ecelp9600 ecelp9600 +audio/vnd.octel.sbc +audio/vnd.qcelp +audio/vnd.rhetorex.32kadpcm +audio/vnd.sealedmedia.softseal.mpeg +audio/vnd.vmx.cvsd +audio/wav wav +audio/x-aiff aif aiff aifc +audio/x-mpegurl m3u +audio/x-ms-wax wax +audio/x-ms-wma wma +audio/x-pn-realaudio ram ra +audio/x-pn-realaudio-plugin rmp +audio/x-wav wav +chemical/x-cdx cdx +chemical/x-cif cif +chemical/x-cmdf cmdf +chemical/x-cml cml +chemical/x-csml csml +chemical/x-pdb pdb +chemical/x-xyz xyz +image/bmp bmp +image/cgm cgm +image/fits +image/g3fax g3 +image/gif gif +image/ief ief +image/jp2 +image/jpeg jpeg jpg jpe +image/jpm +image/jpx +image/naplps +image/png png +image/prs.btif btif +image/prs.pti +image/svg+xml svg svgz +image/t38 +image/tiff tiff tif +image/tiff-fx +image/vnd.adobe.photoshop psd +image/vnd.cns.inf2 +image/vnd.djvu djvu djv +image/vnd.dwg dwg +image/vnd.dxf dxf +image/vnd.fastbidsheet fbs +image/vnd.fpx fpx +image/vnd.fst fst +image/vnd.fujixerox.edmics-mmr mmr +image/vnd.fujixerox.edmics-rlc rlc +image/vnd.globalgraphics.pgb +image/vnd.microsoft.icon ico +image/vnd.mix +image/vnd.ms-modi mdi +image/vnd.net-fpx npx +image/vnd.sealed.png +image/vnd.sealedmedia.softseal.gif +image/vnd.sealedmedia.softseal.jpg +image/vnd.svf +image/vnd.wap.wbmp wbmp +image/vnd.xiff xif +image/x-cmu-raster ras +image/x-cmx cmx +image/x-icon +image/x-pcx pcx +image/x-pict pic pct +image/x-portable-anymap pnm +image/x-portable-bitmap pbm +image/x-portable-graymap pgm +image/x-portable-pixmap ppm +image/x-rgb rgb +image/x-xbitmap xbm +image/x-xpixmap xpm +image/x-xwindowdump xwd +message/cpim +message/delivery-status +message/disposition-notification +message/external-body +message/http +message/news +message/partial +message/rfc822 eml mime +message/s-http +message/sip +message/sipfrag +message/tracking-status +model/iges igs iges +model/mesh msh mesh silo +model/vnd.dwf dwf +model/vnd.flatland.3dml +model/vnd.gdl gdl +model/vnd.gs.gdl +model/vnd.gtw gtw +model/vnd.moml+xml +model/vnd.mts mts +model/vnd.parasolid.transmit.binary +model/vnd.parasolid.transmit.text +model/vnd.vtu vtu +model/vrml wrl vrml +multipart/alternative +multipart/appledouble +multipart/byteranges +multipart/digest +multipart/encrypted +multipart/form-data +multipart/header-set +multipart/mixed +multipart/parallel +multipart/related +multipart/report +multipart/signed +multipart/voice-message +text/calendar ics ifb +text/css css +text/csv csv +text/directory +text/dns +text/enriched +text/html html htm +text/parityfec +text/plain txt text conf def list log in +text/prs.fallenstein.rst +text/prs.lines.tag dsc +text/red +text/rfc822-headers +text/richtext rtx +text/rtf +text/rtp-enc-aescm128 +text/rtx +text/sgml sgml sgm +text/t140 +text/tab-separated-values tsv +text/troff t tr roff man me ms +text/uri-list uri uris urls +text/vnd.abc +text/vnd.curl +text/vnd.dmclientscript +text/vnd.esmertec.theme-descriptor +text/vnd.fly fly +text/vnd.fmi.flexstor flx +text/vnd.in3d.3dml 3dml +text/vnd.in3d.spot spot +text/vnd.iptc.newsml +text/vnd.iptc.nitf +text/vnd.latex-z +text/vnd.motorola.reflex +text/vnd.ms-mediapackage +text/vnd.net2phone.commcenter.command +text/vnd.sun.j2me.app-descriptor jad +text/vnd.trolltech.linguist +text/vnd.wap.si +text/vnd.wap.sl +text/vnd.wap.wml wml +text/vnd.wap.wmlscript wmls +text/x-asm s asm +text/x-c c cc cxx cpp h hh dic +text/x-fortran f for f77 f90 +text/x-pascal p pas +text/x-java-source java +text/x-setext etx +text/x-uuencode uu +text/x-vcalendar vcs +text/x-vcard vcf +text/xml +text/xml-external-parsed-entity +video/3gpp 3gp +video/3gpp-tt +video/3gpp2 3g2 +video/bmpeg +video/bt656 +video/celb +video/dv +video/h261 h261 +video/h263 h263 +video/h263-1998 +video/h263-2000 +video/h264 h264 +video/jpeg jpgv +video/jpm jpm jpgm +video/mj2 mj2 mjp2 +video/mp1s +video/mp2p +video/mp2t +video/mp4 mp4 mp4v mpg4 +video/mp4v-es +video/mpeg mpeg mpg mpe m1v m2v +video/mpeg4-generic +video/mpv +video/nv +video/parityfec +video/pointer +video/quicktime qt mov +video/raw +video/rtp-enc-aescm128 +video/rtx +video/smpte292m +video/vc1 +video/vnd.dlna.mpeg-tts +video/vnd.fvt fvt +video/vnd.hns.video +video/vnd.motorola.video +video/vnd.motorola.videop +video/vnd.mpegurl mxu m4u +video/vnd.nokia.interleaved-multimedia +video/vnd.nokia.videovoip +video/vnd.objectvideo +video/vnd.sealed.mpeg1 +video/vnd.sealed.mpeg4 +video/vnd.sealed.swf +video/vnd.sealedmedia.softseal.mov +video/vnd.vivo viv +video/x-fli fli +video/x-ms-asf asf asx +video/x-ms-wm wm +video/x-ms-wmv wmv +video/x-ms-wmx wmx +video/x-ms-wvx wvx +video/x-msvideo avi +video/x-sgi-movie movie +x-conference/x-cooltalk ice diff --git a/src/include/private/switch_core_pvt.h b/src/include/private/switch_core_pvt.h index 184dedb346..460bb01d83 100644 --- a/src/include/private/switch_core_pvt.h +++ b/src/include/private/switch_core_pvt.h @@ -158,6 +158,7 @@ struct switch_media_bug { struct switch_runtime { switch_time_t initiated; switch_hash_t *global_vars; + switch_hash_t *mime_types; switch_memory_pool_t *memory_pool; const switch_state_handler_table_t *state_handlers[SWITCH_MAX_STATE_HANDLERS]; int state_handler_index; diff --git a/src/include/switch_core.h b/src/include/switch_core.h index c3c49eaf11..814db2934b 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -1494,6 +1494,9 @@ SWITCH_DECLARE(void) switch_core_set_globals(void); SWITCH_DECLARE(uint8_t) switch_core_session_compare(switch_core_session_t *a, switch_core_session_t *b); +SWITCH_DECLARE(const char *) switch_core_mime_ext2type(const char *ext); +SWITCH_DECLARE(switch_status_t) switch_core_mime_add_type(const char *type, const char *ext); + SWITCH_DECLARE(switch_loadable_module_interface_t *) switch_loadable_module_create_module_interface(switch_memory_pool_t *pool, const char *name); SWITCH_DECLARE(void *) switch_loadable_module_create_interface(switch_loadable_module_interface_t *mod, switch_module_interface_name_t iname); SWITCH_DECLARE(switch_time_t) switch_timestamp_now(void); diff --git a/src/include/switch_utils.h b/src/include/switch_utils.h index 0bb187b09b..3caf62c222 100644 --- a/src/include/switch_utils.h +++ b/src/include/switch_utils.h @@ -69,6 +69,8 @@ static inline switch_bool_t switch_is_digit_string(const char *s) { return SWITCH_TRUE; } +switch_size_t switch_fd_read_line(int fd, char *buf, switch_size_t len); + /*! \brief Evaluate the truthfullness of a string expression \param expr a string expression diff --git a/src/mod/applications/mod_voicemail/mod_voicemail.c b/src/mod/applications/mod_voicemail/mod_voicemail.c index d3544df6d9..68b1996478 100644 --- a/src/mod/applications/mod_voicemail/mod_voicemail.c +++ b/src/mod/applications/mod_voicemail/mod_voicemail.c @@ -95,6 +95,7 @@ struct vm_profile { switch_mutex_t *mutex; uint32_t record_threshold; uint32_t record_silence_hits; + uint32_t record_sample_rate; #ifdef SWITCH_HAVE_ODBC switch_odbc_handle_t *master_odbc; #else @@ -208,8 +209,8 @@ static switch_bool_t vm_execute_sql_callback(vm_profile_t *profile, static char vm_sql[] = "CREATE TABLE voicemail_data (\n" - " created_epoch INTEGER(8),\n" - " read_epoch INTEGER(8),\n" + " created_epoch INTEGER,\n" + " read_epoch INTEGER,\n" " user VARCHAR(255),\n" " domain VARCHAR(255),\n" " uuid VARCHAR(255),\n" @@ -217,6 +218,7 @@ static char vm_sql[] = " cid_number VARCHAR(255),\n" " in_folder VARCHAR(255),\n" " file_path VARCHAR(255),\n" + " message_len INTEGER,\n" " flags VARCHAR(255),\n" " read_flags VARCHAR(255)\n" ");\n"; @@ -301,6 +303,7 @@ static switch_status_t load_config(void) char *date_fmt = "%A, %B %d %Y, %I %M %p"; uint32_t record_threshold = 200; uint32_t record_silence_hits = 2; + uint32_t record_sample_rate = 0; switch_core_db_t *db; uint32_t timeout = 10000, max_login_attempts = 3, max_record_len = 300; @@ -398,6 +401,16 @@ static switch_status_t load_config(void) } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "invalid threshold value [%s] must be between 0 and 10000 ms\n", val); } + } else if (!strcasecmp(var, "record-sample-rate")) { + int tmp = 0; + if (!switch_strlen_zero(val)) { + tmp = atoi(val); + } + if (tmp == 8000 || tmp == 16000 || tmp == 32000 || tmp == 11025 || tmp == 22050 || tmp == 44100) { + record_sample_rate = tmp; + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "invalid samplerate %s\n", val); + } } else if (!strcasecmp(var, "record-silence-hits")) { int tmp = 0; if (!switch_strlen_zero(val)) { @@ -481,13 +494,20 @@ static switch_status_t load_config(void) } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Connected ODBC DSN: %s\n", profile->odbc_dsn); - switch_odbc_handle_exec(profile->master_odbc, vm_sql, NULL); - switch_odbc_handle_exec(profile->master_odbc, vm_pref_sql, NULL); + if (switch_odbc_handle_exec(profile->master_odbc, "select count(message_len) from voicemail_data", NULL) != SWITCH_ODBC_SUCCESS) { + switch_odbc_handle_exec(profile->master_odbc, "drop table voicemail_data", NULL); + switch_odbc_handle_exec(profile->master_odbc, vm_sql, NULL); + } + + if (switch_odbc_handle_exec(profile->master_odbc, "select count(user) from voicemail_prefs", NULL) != SWITCH_ODBC_SUCCESS) { + switch_odbc_handle_exec(profile->master_odbc, "drop table voicemail_data", NULL); + switch_odbc_handle_exec(profile->master_odbc, vm_pref_sql, NULL); + } } else { #endif if ((db = switch_core_db_open_file(profile->dbname))) { - switch_core_db_test_reactive(db, "select * from voicemail_data", NULL, vm_sql); - switch_core_db_test_reactive(db, "select * from voicemail_prefs", NULL, vm_pref_sql); + switch_core_db_test_reactive(db, "select count(message_len) from voicemail_data", "drop table voicemail_data", vm_sql); + switch_core_db_test_reactive(db, "select count(user) from voicemail_prefs", "drop table voicemail_data", vm_pref_sql); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Cannot Open SQL Database!\n"); continue; @@ -527,6 +547,7 @@ static switch_status_t load_config(void) *profile->operator_key = *operator_key; profile->record_threshold = record_threshold; profile->record_silence_hits = record_silence_hits; + profile->record_sample_rate = record_sample_rate; profile->operator_ext = switch_core_strdup(globals.pool, operator_ext); profile->storage_dir = switch_core_strdup(globals.pool, storage_dir); @@ -783,7 +804,7 @@ typedef enum { static uint32_t DEFAULT_DIR_PERMS = SWITCH_FPROT_UREAD | SWITCH_FPROT_UWRITE | SWITCH_FPROT_UEXECUTE | SWITCH_FPROT_GREAD | SWITCH_FPROT_GEXECUTE; -static switch_status_t create_file(switch_core_session_t *session, vm_profile_t *profile, char *macro_name, char *file_path) +static switch_status_t create_file(switch_core_session_t *session, vm_profile_t *profile, char *macro_name, char *file_path, uint32_t *message_len) { switch_channel_t *channel; switch_status_t status = SWITCH_STATUS_SUCCESS; @@ -792,19 +813,13 @@ static switch_status_t create_file(switch_core_session_t *session, vm_profile_t char term; char input[10] = "" , key_buf[80] = ""; cc_t cc = { 0 }; - + switch_codec_t *read_codec; channel = switch_core_session_get_channel(session); assert(channel != NULL); + read_codec = switch_core_session_get_read_codec(session); while(switch_channel_ready(channel)) { - - - switch_channel_set_variable(channel, "RECORD_COMMENT", macro_name); - - - - snprintf(key_buf, sizeof(key_buf), "%s:%s:%s", profile->listen_file_key, @@ -820,9 +835,9 @@ static switch_status_t create_file(switch_core_session_t *session, vm_profile_t memset(&fh, 0, sizeof(fh)); fh.thresh = profile->record_threshold; fh.silence_hits = profile->record_silence_hits; - - + fh.samplerate = profile->record_sample_rate; switch_ivr_record_file(session, &fh, file_path, &args, profile->max_record_len); + *message_len = fh.sample_count / read_codec->implementation->actual_samples_per_second; status = SWITCH_STATUS_SUCCESS; play_file: @@ -873,6 +888,7 @@ struct listen_callback { char cid_number[255]; char in_folder[255]; char file_path[255]; + char message_len[255]; char flags[255]; char read_flags[255]; char *email; @@ -899,8 +915,9 @@ static int listen_callback(void *pArg, int argc, char **argv, char **columnNames switch_copy_string(cbt->cid_number, argv[6], 255); switch_copy_string(cbt->in_folder, argv[7], 255); switch_copy_string(cbt->file_path, argv[8], 255); - switch_copy_string(cbt->flags, argv[9], 255); - switch_copy_string(cbt->read_flags, argv[10], 255); + switch_copy_string(cbt->message_len, argv[9], 255); + switch_copy_string(cbt->flags, argv[10], 255); + switch_copy_string(cbt->read_flags, argv[11], 255); return -1; @@ -1024,7 +1041,7 @@ static switch_status_t listen_file(switch_core_session_t *session, vm_profile_t if (!strcmp(input, profile->email_key) && !switch_strlen_zero(cbt->email)) { switch_event_t *event; char *from; - char *headers; + char *headers, *header_string; char *body; int priority = 3; switch_size_t retsize; @@ -1035,12 +1052,14 @@ static switch_status_t listen_file(switch_core_session_t *session, vm_profile_t int total_saved_messages = 0; int total_new_urgent_messages = 0; int total_saved_urgent_messages = 0; - + int32_t message_len = 0; + char *p; + if (!strcasecmp(cbt->read_flags, URGENT_FLAG_STRING)) { priority = 1; } - + message_count(profile, cbt->user, cbt->domain, cbt->in_folder, &total_new_messages, &total_saved_messages, &total_new_urgent_messages, &total_saved_urgent_messages); @@ -1065,8 +1084,10 @@ static switch_status_t listen_file(switch_core_session_t *session, vm_profile_t switch_channel_set_variable(channel, "voicemail_time", date); snprintf(tmp,sizeof(tmp), "%d", priority); switch_channel_set_variable(channel, "voicemail_priority", tmp); - - + message_len = atoi(cbt->message_len); + switch_channel_set_variable(channel, "voicemail_message_len", cbt->message_len); + switch_channel_set_variable(channel, "voicemail_email", cbt->email); + if(switch_strlen_zero(profile->email_headers)) { from = switch_core_session_sprintf(session, "%s@%s", cbt->user, cbt->domain); } else { @@ -1081,6 +1102,15 @@ static switch_status_t listen_file(switch_core_session_t *session, vm_profile_t headers = switch_channel_expand_variables(channel,profile->email_headers); } + p = headers + (strlen(headers) - 1); + if (*p == '\n') { + if (*(p-1) == '\r') { + p--; + } + *p = '\0'; + } + + header_string = switch_core_session_sprintf(session, "%s\nX-Voicemail-Length: %u", headers, message_len); if (switch_event_create(&event, SWITCH_EVENT_MESSAGE) == SWITCH_STATUS_SUCCESS) { /* this isnt done? it was in the other place @@ -1097,7 +1127,7 @@ static switch_status_t listen_file(switch_core_session_t *session, vm_profile_t body = switch_channel_expand_variables(channel,profile->email_body); } - switch_simple_email(cbt->email, from, headers, body, cbt->file_path); + switch_simple_email(cbt->email, from, header_string, body, cbt->file_path); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Sending message to %s\n", cbt->email); switch_safe_free(body); TRY_CODE(switch_ivr_phrase_macro(session, VM_ACK_MACRO, "emailed", NULL, NULL)); @@ -1295,6 +1325,8 @@ static void voicemail_check_main(switch_core_session_t *session, const char *pro callback_t cbt = { 0 }; char msg_count[80] = ""; cc_t cc = { 0 }; + uint32_t message_len = 0; + cbt.buf = msg_count; cbt.len = sizeof(msg_count); sql = switch_mprintf("select count(*) from voicemail_prefs where user='%q' and domain = '%q'", myid, domain_name); @@ -1362,7 +1394,7 @@ static void voicemail_check_main(switch_core_session_t *session, const char *pro TRY_CODE(switch_ivr_phrase_macro(session, VM_CHOOSE_GREETING_FAIL_MACRO, NULL, NULL, NULL)); } else { file_path = switch_mprintf("%s%sgreeting_%d.%s", dir_path, SWITCH_PATH_SEPARATOR, num, profile->file_ext); - TRY_CODE(create_file(session, profile, VM_RECORD_GREETING_MACRO, file_path)); + TRY_CODE(create_file(session, profile, VM_RECORD_GREETING_MACRO, file_path, &message_len)); sql = switch_mprintf("update voicemail_prefs set greeting_path='%s' where user='%s' and domain='%s'", file_path, myid, domain_name); vm_execute_sql(profile, sql, profile->mutex); switch_safe_free(sql); @@ -1371,7 +1403,7 @@ static void voicemail_check_main(switch_core_session_t *session, const char *pro } else if (!strcmp(input, profile->record_name_key)) { file_path = switch_mprintf("%s%srecorded_name.%s", dir_path, SWITCH_PATH_SEPARATOR, profile->file_ext); - TRY_CODE(create_file(session, profile, VM_RECORD_NAME_MACRO, file_path)); + TRY_CODE(create_file(session, profile, VM_RECORD_NAME_MACRO, file_path, &message_len)); sql = switch_mprintf("update voicemail_prefs set name_path='%s' where user='%s' and domain='%s'", file_path, myid, domain_name); vm_execute_sql(profile, sql, profile->mutex); switch_safe_free(file_path); @@ -1585,6 +1617,12 @@ static switch_status_t voicemail_leave_main(switch_core_session_t *session, cons char buf[2]; char *greet_path = NULL; const char *voicemail_greeting_number = NULL; + uint32_t message_len = 0; + switch_time_exp_t tm; + char date[80] = ""; + switch_size_t retsize; + switch_time_t ts = switch_timestamp_now(); + char *dbuf = NULL; memset(&cbt, 0, sizeof(cbt)); if (!(profile = switch_core_hash_find(globals.profile_hash, profile_name))) { @@ -1732,8 +1770,19 @@ static switch_status_t voicemail_leave_main(switch_core_session_t *session, cons cc.noexit = 1; args.buf = &cc; + dbuf = switch_mprintf("%s (%s)", caller_profile->caller_id_name, caller_profile->caller_id_number); + switch_channel_set_variable(channel, "RECORD_ARTIST", dbuf); + free(dbuf); - status = create_file(session, profile, VM_RECORD_MESSAGE_MACRO, file_path); + switch_time_exp_lt(&tm, ts); + switch_strftime(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm); + switch_channel_set_variable(channel, "RECORD_DATE", date); + switch_channel_set_variable(channel, "RECORD_SOFTWARE", "FreeSWITCH"); + switch_channel_set_variable(channel, "RECORD_TITLE", "FreeSWITCH Voicemail"); + switch_channel_set_variable(channel, "RECORD_COMMENT", "FreeSWITCH Voicemail"); + switch_channel_set_variable(channel, "RECORD_COPYRIGHT", "http://www.freeswitch.org"); + + status = create_file(session, profile, VM_RECORD_MESSAGE_MACRO, file_path, &message_len); if ((status == SWITCH_STATUS_SUCCESS || status == SWITCH_STATUS_BREAK) && switch_channel_ready(channel)) { char input[10] = "", key_buf[80] = "", term = 0; @@ -1761,8 +1810,9 @@ static switch_status_t voicemail_leave_main(switch_core_session_t *session, cons int total_new_urgent_messages = 0; int total_saved_urgent_messages = 0; - usql = switch_mprintf("insert into voicemail_data values(%ld,0,'%q','%q','%q','%q','%q','%q','%q','','%q')", (long)time(NULL), - id, domain_name, uuid, caller_profile->caller_id_name, caller_profile->caller_id_number, myfolder, file_path, read_flags); + usql = switch_mprintf("insert into voicemail_data values(%ld,0,'%q','%q','%q','%q','%q','%q','%q','%u','','%q')", (long)time(NULL), + id, domain_name, uuid, caller_profile->caller_id_name, caller_profile->caller_id_number, + myfolder, file_path, message_len, read_flags); vm_execute_sql(profile, usql, profile->mutex); switch_safe_free(usql); @@ -1788,6 +1838,7 @@ static switch_status_t voicemail_leave_main(switch_core_session_t *session, cons char *from; char *body; char *headers; + char *header_string; switch_size_t retsize; switch_time_exp_t tm; char date[80] = ""; @@ -1796,7 +1847,8 @@ static switch_status_t voicemail_leave_main(switch_core_session_t *session, cons int total_saved_messages = 0; int total_new_urgent_messages = 0; int total_saved_urgent_messages = 0; - + char *p; + message_count(profile, id, domain_name, myfolder, &total_new_messages, &total_saved_messages, &total_new_urgent_messages, &total_saved_urgent_messages); @@ -1821,25 +1873,39 @@ static switch_status_t voicemail_leave_main(switch_core_session_t *session, cons switch_channel_set_variable(channel, "voicemail_time", date); snprintf(tmp,sizeof(tmp), "%d", priority); switch_channel_set_variable(channel, "voicemail_priority", tmp); + switch_channel_set_variable(channel, "voicemail_email", email_vm); + snprintf(tmp,sizeof(tmp), "%d", message_len); + switch_channel_set_variable(channel, "voicemail_message_len", tmp); - if(switch_strlen_zero(profile->email_from)) { + if (switch_strlen_zero(profile->email_from)) { from = switch_core_session_sprintf(session, "%s@%s", id, domain_name); } else { from = switch_channel_expand_variables(channel, profile->email_headers); } - if(switch_strlen_zero(profile->email_headers)) { - headers = switch_core_session_sprintf(session, "From: FreeSWITCH mod_voicemail <%s@%s>\nSubject: Voicemail from %s %s\nX-Priority: %d", + if (switch_strlen_zero(profile->email_headers)) { + headers = switch_core_session_sprintf(session, + "From: FreeSWITCH mod_voicemail <%s@%s>\n" + "Subject: Voicemail from %s %s\nX-Priority: %d", id, domain_name, caller_profile->caller_id_name, caller_profile->caller_id_number, priority); } else { - headers = switch_channel_expand_variables(channel,profile->email_headers); + headers = switch_channel_expand_variables(channel, profile->email_headers); } + p = headers + (strlen(headers) - 1); + if (*p == '\n') { + if (*(p-1) == '\r') { + p--; + } + *p = '\0'; + } + + header_string = switch_core_session_sprintf(session, "%s\nX-Voicemail-Length: %u", headers, message_len); if (switch_event_create(&event, SWITCH_EVENT_MESSAGE) == SWITCH_STATUS_SUCCESS) { @@ -1847,22 +1913,22 @@ static switch_status_t voicemail_leave_main(switch_core_session_t *session, cons switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Message-Type", "voicemail"); switch_event_fire(&event); } - if(!switch_strlen_zero(profile->email_headers)) { + if (!switch_strlen_zero(profile->email_headers)) { body = switch_mprintf("Voicemail from %s %s", caller_profile->caller_id_name, caller_profile->caller_id_number); } else { body = switch_channel_expand_variables(channel,profile->email_body); } - if(email_attach) { - switch_simple_email(email_vm, from, headers, body, file_path); + if (email_attach) { + switch_simple_email(email_vm, from, header_string, body, file_path); } else { - switch_simple_email(email_vm, from, headers, body, NULL); + switch_simple_email(email_vm, from, header_string, body, NULL); } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Sending message to %s\n", email_vm); switch_safe_free(body); - if(email_delete) { + if (email_delete) { unlink(file_path); } } diff --git a/src/mod/formats/mod_local_stream/mod_local_stream.c b/src/mod/formats/mod_local_stream/mod_local_stream.c index f082cc5755..82e723e82e 100644 --- a/src/mod/formats/mod_local_stream/mod_local_stream.c +++ b/src/mod/formats/mod_local_stream/mod_local_stream.c @@ -237,6 +237,7 @@ static switch_status_t local_stream_file_read(switch_file_handle_t *handle, void *len = need / 2; } switch_mutex_unlock(context->audio_mutex); + handle->sample_count += *len; return SWITCH_STATUS_SUCCESS; } diff --git a/src/mod/formats/mod_shout/mod_shout.c b/src/mod/formats/mod_shout/mod_shout.c index 9cefbb9bc9..b9dbdeaeb8 100644 --- a/src/mod/formats/mod_shout/mod_shout.c +++ b/src/mod/formats/mod_shout/mod_shout.c @@ -65,6 +65,7 @@ struct shout_context { uint8_t thread_running; uint8_t shout_init; uint32_t prebuf; + int lame_ready; }; typedef struct shout_context shout_context_t; @@ -91,6 +92,7 @@ static inline void free_context(shout_context_t * context) } lame_mp3_tags_fid(context->gfp, context->fp); + fclose(context->fp); context->fp = NULL; } @@ -576,19 +578,23 @@ static switch_status_t shout_file_open(switch_file_handle_t *handle, const char goto error; } + if (!handle->handler) { + id3tag_init(context->gfp); + id3tag_v2_only(context->gfp); + id3tag_pad_v2(context->gfp); + + } + lame_set_num_channels(context->gfp, handle->channels); lame_set_in_samplerate(context->gfp, handle->samplerate); - lame_set_brate(context->gfp, 64); + lame_set_brate(context->gfp, 24); lame_set_mode(context->gfp, 3); lame_set_quality(context->gfp, 2); /* 2=high 5 = medium 7=low */ - + lame_set_errorf(context->gfp, log_error); lame_set_debugf(context->gfp, log_debug); lame_set_msgf(context->gfp, log_msg); - lame_init_params(context->gfp); - lame_print_config(context->gfp); - if (handle->handler) { if (switch_buffer_create_dynamic(&context->audio_buffer, MY_BLOCK_SIZE, MY_BUF_LEN, 0) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Memory Error!\n"); @@ -674,7 +680,7 @@ static switch_status_t shout_file_open(switch_file_handle_t *handle, const char goto error; } - if (shout_set_audio_info(context->shout, "bitrate", "64000") != SHOUTERR_SUCCESS) { + if (shout_set_audio_info(context->shout, "bitrate", "24000") != SHOUTERR_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error setting user: %s\n", shout_get_error(context->shout)); goto error; } @@ -780,6 +786,8 @@ static switch_status_t shout_file_read(switch_file_handle_t *handle, void *data, *len = bytes / sizeof(int16_t); } + handle->sample_count += *len; + return SWITCH_STATUS_SUCCESS; } @@ -817,6 +825,13 @@ static switch_status_t shout_file_write(switch_file_handle_t *handle, void *data return SWITCH_STATUS_FALSE; } } else { + + if (!context->lame_ready) { + lame_init_params(context->gfp); + lame_print_config(context->gfp); + context->lame_ready = 1; + } + if ((rlen = lame_encode_buffer(context->gfp, audio, NULL, nsamples, mp3buf, sizeof(mp3buf))) < 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "MP3 encode error %d!\n", rlen); return SWITCH_STATUS_FALSE; @@ -828,26 +843,63 @@ static switch_status_t shout_file_write(switch_file_handle_t *handle, void *data } } + handle->sample_count += *len; + return SWITCH_STATUS_SUCCESS; } static switch_status_t shout_file_set_string(switch_file_handle_t *handle, switch_audio_col_t col, const char *string) { shout_context_t *context = handle->private_info; - + switch_status_t status = SWITCH_STATUS_FALSE; + + if (!context->shout) { + switch (col) { + case SWITCH_AUDIO_COL_STR_TITLE: + id3tag_set_title(context->gfp, string); + break; + case SWITCH_AUDIO_COL_STR_COMMENT: + id3tag_set_comment(context->gfp, string); + break; + case SWITCH_AUDIO_COL_STR_ARTIST: + id3tag_set_artist(context->gfp, string); + break; + case SWITCH_AUDIO_COL_STR_DATE: + id3tag_set_year(context->gfp, string); + break; + case SWITCH_AUDIO_COL_STR_SOFTWARE: + break; + id3tag_set_album(context->gfp, string); + case SWITCH_AUDIO_COL_STR_COPYRIGHT: + id3tag_set_genre(context->gfp, string); + break; + default: + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Value Ignored\n"); + break; + } + + return status; + } + switch (col) { case SWITCH_AUDIO_COL_STR_TITLE: - if (shout_set_name(context->shout, string) != SHOUTERR_SUCCESS) { + if (shout_set_name(context->shout, string) == SHOUTERR_SUCCESS) { + status = SWITCH_STATUS_SUCCESS; + } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error setting name: %s\n", shout_get_error(context->shout)); } break; case SWITCH_AUDIO_COL_STR_COMMENT: - if (shout_set_url(context->shout, string) != SHOUTERR_SUCCESS) { + if (shout_set_url(context->shout, string) == SHOUTERR_SUCCESS) { + status = SWITCH_STATUS_SUCCESS; + } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error setting name: %s\n", shout_get_error(context->shout)); } break; case SWITCH_AUDIO_COL_STR_ARTIST: - if (shout_set_description(context->shout, string) != SHOUTERR_SUCCESS) { + if (shout_set_description(context->shout, string) == SHOUTERR_SUCCESS) { + status = SWITCH_STATUS_SUCCESS; + } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error setting name: %s\n", shout_get_error(context->shout)); } break; @@ -855,7 +907,8 @@ static switch_status_t shout_file_set_string(switch_file_handle_t *handle, switc switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Value Ignored\n"); break; } - return SWITCH_STATUS_FALSE; + + return status; } static switch_status_t shout_file_get_string(switch_file_handle_t *handle, switch_audio_col_t col, const char **string) diff --git a/src/mod/formats/mod_sndfile/mod_sndfile.c b/src/mod/formats/mod_sndfile/mod_sndfile.c index 686aa2fba4..cc29445523 100644 --- a/src/mod/formats/mod_sndfile/mod_sndfile.c +++ b/src/mod/formats/mod_sndfile/mod_sndfile.c @@ -205,6 +205,8 @@ static switch_status_t sndfile_file_read(switch_file_handle_t *handle, void *dat *len = (size_t) sf_readf_int(context->handle, (int *) data, inlen); } + handle->sample_count += *len; + return SWITCH_STATUS_SUCCESS; } @@ -227,6 +229,8 @@ static switch_status_t sndfile_file_write(switch_file_handle_t *handle, void *da *len = (size_t) sf_writef_int(context->handle, (int *) data, inlen); } + handle->sample_count += *len; + return SWITCH_STATUS_SUCCESS; } diff --git a/src/switch_core.c b/src/switch_core.c index 1eca5903a6..6e90c50bc4 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -549,6 +549,87 @@ SWITCH_DECLARE(void) switch_core_runtime_loop(int bg) } } +SWITCH_DECLARE(const char *) switch_core_mime_ext2type(const char *ext) +{ + return (const char *) switch_core_hash_find(runtime.mime_types, ext); +} + +SWITCH_DECLARE(switch_status_t) switch_core_mime_add_type(const char *type, const char *ext) +{ + const char *check = (const char *) switch_core_hash_find(runtime.mime_types, ext); + switch_status_t status = SWITCH_STATUS_FALSE; + + assert(type); + assert(ext); + + if (!check) { + char *ptype = switch_core_permanent_strdup(type); + char *ext_list = strdup(ext); + int argc = 0; + char *argv[20] = { 0 }; + int x; + + assert(ext_list); + + if ((argc = switch_separate_string(ext_list, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) { + + for (x = 0; x < argc; x++) { + switch_core_hash_insert(runtime.mime_types, argv[x], ptype); + } + + status = SWITCH_STATUS_SUCCESS; + } + + free(ext_list); + } + + return status; +} + +static void load_mime_types(void) +{ + char *cf = "mime.types"; + int fd = -1; + char line_buf[1024] = ""; + char *mime_path = NULL; + + mime_path = switch_mprintf("%s/%s", SWITCH_GLOBAL_dirs.conf_dir, cf); + assert(mime_path); + + if (!(fd = open(mime_path, O_RDONLY))) { + return; + } + + while((switch_fd_read_line(fd, line_buf, sizeof(line_buf)))) { + char *p; + char *type = line_buf; + + if (*line_buf == '#') { + continue; + } + + if ((p = strchr(line_buf, '\r')) || (p = strchr(line_buf, '\n'))) { + *p = '\0'; + } + + if ((p = strchr(type, '\t')) || (p = strchr(type, ' '))) { + *p++ = '\0'; + + while(*p == ' ' || *p == '\t') { + p++; + } + + switch_core_mime_add_type(type, p); + } + + } + + if (fd > -1) { + close(fd); + fd = -1; + } + +} SWITCH_DECLARE(switch_status_t) switch_core_init(const char *console, switch_core_flag_t flags, const char **err) { @@ -578,6 +659,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_init(const char *console, switch_cor switch_core_set_globals(); switch_core_session_init(runtime.memory_pool); switch_core_hash_init(&runtime.global_vars, runtime.memory_pool); + switch_core_hash_init(&runtime.mime_types, runtime.memory_pool); + load_mime_types(); runtime.flags = flags; runtime.sps_total = 30; @@ -591,8 +674,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_init(const char *console, switch_cor apr_terminate(); return SWITCH_STATUS_MEMERR; } - - + if ((xml = switch_xml_open_cfg("switch.conf", &cfg, NULL))) { switch_xml_t settings, param; @@ -918,6 +1000,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_destroy(void) switch_core_hash_destroy(&runtime.global_vars); + switch_core_hash_destroy(&runtime.mime_types); if (runtime.memory_pool) { apr_pool_destroy(runtime.memory_pool); diff --git a/src/switch_ivr_play_say.c b/src/switch_ivr_play_say.c index d3b3f5383c..d7304b7b70 100644 --- a/src/switch_ivr_play_say.c +++ b/src/switch_ivr_play_say.c @@ -348,6 +348,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se const char *vval; time_t start = 0; uint32_t org_silence_hits = 0; + switch_audio_resampler_t *resampler = NULL; + int16_t resamp_out[2048]; if (!fh) { fh = &lfh; @@ -360,13 +362,27 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se assert(read_codec != NULL); fh->channels = read_codec->implementation->number_of_channels; - fh->samplerate = read_codec->implementation->actual_samples_per_second; + if (fh->samplerate) { + if (fh->samplerate != read_codec->implementation->actual_samples_per_second) { + if (switch_resample_create(&resampler, + read_codec->implementation->actual_samples_per_second, + read_codec->implementation->actual_samples_per_second * 20, + fh->samplerate, + fh->samplerate * 20, + switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Unable to create resampler!\n"); + return SWITCH_STATUS_GENERR; + } + } + } else { + fh->samplerate = read_codec->implementation->actual_samples_per_second; + } if (switch_core_file_open(fh, file, - read_codec->implementation->number_of_channels, - read_codec->implementation->actual_samples_per_second, + fh->channels, + fh->samplerate, SWITCH_FILE_FLAG_WRITE | SWITCH_FILE_DATA_SHORT, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) { switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); switch_core_session_reset(session); @@ -539,7 +555,17 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se if (!switch_test_flag(fh, SWITCH_FILE_PAUSE)) { len = (switch_size_t) read_frame->datalen / 2; - if (switch_core_file_write(fh, read_frame->data, &len) != SWITCH_STATUS_SUCCESS) { + int16_t *data = read_frame->data; + + if (resampler) { + resampler->from_len = switch_short_to_float(read_frame->data, resampler->from, (int) len); + resampler->to_len = switch_resample_process(resampler, resampler->from, resampler->from_len, resampler->to, resampler->to_size, 0); + switch_float_to_short(resampler->to, resamp_out, read_frame->datalen); + len = resampler->to_len; + data = resamp_out; + } + + if (switch_core_file_write(fh, data, &len) != SWITCH_STATUS_SUCCESS) { break; } } @@ -609,28 +635,25 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_gentones(switch_core_session_t *sessi } for(;;) { - switch_status_t status = switch_core_session_read_frame(session, &read_frame, 1000, 0); - + switch_status_t status; + if (!switch_channel_ready(channel)) { status = SWITCH_STATUS_FALSE; break; } - if (switch_channel_test_flag(channel, CF_BREAK)) { switch_channel_clear_flag(channel, CF_BREAK); status = SWITCH_STATUS_BREAK; break; } + status = switch_core_session_read_frame(session, &read_frame, 1000, 0); + if (!SWITCH_READ_ACCEPTABLE(status)) { break; } - if (read_frame->datalen < 2 || switch_test_flag(read_frame, SFF_CNG)) { - continue; - } - if (args && (args->read_frame_callback)) { if (args->read_frame_callback(session, read_frame, args->user_data) != SWITCH_STATUS_SUCCESS) { break; diff --git a/src/switch_utils.c b/src/switch_utils.c index 521e65664b..23bbb3601d 100644 --- a/src/switch_utils.c +++ b/src/switch_utils.c @@ -35,6 +35,28 @@ #endif #include "private/switch_core_pvt.h" + +switch_size_t switch_fd_read_line(int fd, char *buf, switch_size_t len) +{ + char c, *p; + int cur; + switch_size_t total = 0; + + p = buf; + while (total + sizeof(c) < len && (cur = read(fd, &c, sizeof(c))) > 0) { + total += cur; + *p++ = c; + if (c == '\r' || c == '\n') { + break; + } + } + + *p++ = '\0'; + return total; +} + + + static const char switch_b64_table[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; #define B64BUFFLEN 1024 SWITCH_DECLARE(switch_status_t) switch_b64_encode(unsigned char *in, switch_size_t ilen, unsigned char *out, switch_size_t olen) @@ -85,7 +107,7 @@ static int write_buf(int fd, const char *buf) SWITCH_DECLARE(switch_bool_t) switch_simple_email(const char *to, const char *from, const char *headers, const char *body, const char *file) { char *bound = "XXXX_boundary_XXXX"; - char *mime_type = "audio/x-WAV"; + const char *mime_type = "audio/inline"; char filename[80], buf[B64BUFFLEN]; int fd = 0, ifd = 0; int x = 0, y = 0, bytes = 0, ilen = 0; @@ -127,6 +149,16 @@ SWITCH_DECLARE(switch_bool_t) switch_simple_email(const char *to, const char *fr if (file) { const char *filename = switch_cut_path(file); + const char *new_type; + char *ext; + + if ((ext = strrchr(filename, '.'))) { + ext++; + if ((new_type = switch_core_mime_ext2type(ext))) { + mime_type = new_type; + } + } + snprintf(buf, B64BUFFLEN, "\n\n--%s\nContent-Type: %s; name=\"%s\"\n" "Content-Transfer-Encoding: base64\n" @@ -188,7 +220,7 @@ SWITCH_DECLARE(switch_bool_t) switch_simple_email(const char *to, const char *fr switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to execute command: %s\n", buf); } - unlink(filename); + //unlink(filename); if (file) { diff --git a/src/switch_xml.cpp b/src/switch_xml.cpp index 48ad360182..827e0b6757 100644 --- a/src/switch_xml.cpp +++ b/src/switch_xml.cpp @@ -878,25 +878,6 @@ SWITCH_DECLARE(switch_xml_t) switch_xml_parse_fd(int fd) return &root->xml; } -static switch_size_t read_line(int fd, char *buf, switch_size_t len) -{ - char c, *p; - int cur; - switch_size_t total = 0; - - p = buf; - while (total + sizeof(c) < len && (cur = read(fd, &c, sizeof(c))) > 0) { - total += cur; - *p++ = c; - if (c == '\n') { - break; - } - } - - *p++ = '\0'; - return total; -} - static char *expand_vars(char *buf, char *ebuf, switch_size_t elen, switch_size_t *newlen) { char *var, *val; @@ -999,7 +980,7 @@ static int preprocess(const char *cwd, const char *file, int write_fd, int rleve return -1; } - while ((cur = read_line(read_fd, buf, sizeof(buf))) > 0) { + while ((cur = switch_fd_read_line(read_fd, buf, sizeof(buf))) > 0) { char *arg, *e; char *bp = expand_vars(buf, ebuf, sizeof(ebuf), &cur);