- added beep.gsm
authorIordan Iordanov <iiordanov@gmail.com>
Sat, 9 Mar 2013 22:52:53 +0000 (22:52 +0000)
committerIordan Iordanov <iiordanov@gmail.com>
Sat, 9 Mar 2013 22:52:53 +0000 (22:52 +0000)
- now escaping special characters in pbx-asterisk

- changed location of voicemail temp stuff and log file

- changed pbx-send-voicemail to use base64 instead of uuencode

- added many missing dependencies

- now allowing ip addresses as well as hostnames for external host

- constrained # seconds to ring to positive integers

- specifying externrefresh in sip.conf template

- fixed voicemail (sending recordings, recording new greeting, instructions)

- Implemented callback

24 files changed:
applications/luci-pbx-voicemail/luasrc/model/cbi/pbx-voicemail.lua
applications/luci-pbx-voicemail/root/etc/pbx-voicemail/pbx-move-greeting [new file with mode: 0755]
applications/luci-pbx-voicemail/root/etc/pbx-voicemail/pbx-send-voicemail
applications/luci-pbx/luasrc/model/cbi/pbx-advanced.lua
applications/luci-pbx/luasrc/model/cbi/pbx-calls.lua
applications/luci-pbx/root/etc/init.d/pbx-asterisk
applications/luci-pbx/root/etc/pbx-asterisk/delayedcallback [new file with mode: 0755]
applications/luci-pbx/root/etc/pbx-asterisk/extensions.conf.TEMPLATE
applications/luci-pbx/root/etc/pbx-asterisk/extensions_callback-check.conf.TEMPLATE [new file with mode: 0644]
applications/luci-pbx/root/etc/pbx-asterisk/extensions_callback-check_footer.conf.TEMPLATE [new file with mode: 0644]
applications/luci-pbx/root/etc/pbx-asterisk/extensions_callback-check_header.conf.TEMPLATE [new file with mode: 0644]
applications/luci-pbx/root/etc/pbx-asterisk/extensions_callback_gtalk.conf.TEMPLATE [new file with mode: 0644]
applications/luci-pbx/root/etc/pbx-asterisk/extensions_callback_header.conf.TEMPLATE [new file with mode: 0644]
applications/luci-pbx/root/etc/pbx-asterisk/extensions_callback_sip.conf.TEMPLATE [new file with mode: 0644]
applications/luci-pbx/root/etc/pbx-asterisk/extensions_default.conf.TEMPLATE
applications/luci-pbx/root/etc/pbx-asterisk/extensions_disa-nopin.conf.TEMPLATE [new file with mode: 0644]
applications/luci-pbx/root/etc/pbx-asterisk/extensions_incoming_context_gtalk.conf.TEMPLATE
applications/luci-pbx/root/etc/pbx-asterisk/extensions_incoming_context_sip.conf.TEMPLATE
applications/luci-pbx/root/etc/pbx-asterisk/extensions_voicemail_enabled.conf.TEMPLATE
applications/luci-pbx/root/etc/pbx-asterisk/sip.conf.TEMPLATE
applications/luci-pbx/root/etc/pbx-asterisk/sounds/auth-incorrect.gsm [new file with mode: 0644]
applications/luci-pbx/root/etc/pbx-asterisk/sounds/beep.gsm [new file with mode: 0644]
applications/luci-pbx/root/etc/pbx-asterisk/sounds/vm-goodbye.gsm [new file with mode: 0644]
contrib/package/luci/Makefile

index 6232060..9ff2ed9 100644 (file)
@@ -64,20 +64,23 @@ savepath = s:option(Value, "global_save_path", translate("Local Storage Director
                               option only if you know what you are doing."))
 savepath.optional = true
 
-if     nixio.fs.access("/etc/pbx-voicemail/greeting.WAV")   then
+if     nixio.fs.access("/etc/pbx-voicemail/recordings/greeting.gsm")   then
    m1 = s:option(DummyValue, "_m1")
    m1:depends("enabled", "yes")
    m1.default = "NOTE: Found a voicemail greeting. To check or change your voicemail greeting, dial *789 \
-                 and the system will play your current message. You have 5 seconds to hangup, otherwise a \
-                 new recording will begin and your old message will be overwritten. Hang up or press # to \
-                 stop recording. When you press #, the system will play back the new recording."
+                 and the system will play back your current greeting. After that, a long beep will sound and \
+                 you can press * in order to record a new message. Hang up to avoid recording a message. \
+                 If you press *, a second long beep will sound, and you can record a new greeting. \
+                 Hang up or press # to stop recording. When # is pressed the system will play back the \
+                 new greeting."
 else
    m1 = s:option(DummyValue, "_m1")
    m1:depends("enabled", "yes")
    m1.default = "WARNING: Could not find voicemail greeting. Callers will hear only a beep before \
-                 recording starts. To record a greeting, dial *789 and record a greeting after the beep. \
+                 recording starts. To record a greeting, dial *789, and press * after the long beep. \
+                 If you press *, a second long beep will sound, and you can record a new greeting. \
                  Hang up or press # to stop recording. When # is pressed the system will play back the \
-                 recording."
+                 new greeting."
 end
 
 
diff --git a/applications/luci-pbx-voicemail/root/etc/pbx-voicemail/pbx-move-greeting b/applications/luci-pbx-voicemail/root/etc/pbx-voicemail/pbx-move-greeting
new file mode 100755 (executable)
index 0000000..21fe694
--- /dev/null
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+if [ -f "/tmp/voicemail/greeting.gsm" ]
+then
+    mv /tmp/voicemail/greeting.gsm /etc/pbx-voicemail/recordings/
+fi
index adfded2..ba639d0 100755 (executable)
 #
 #
 # Thanks to http://www.zedwood.com for providing an excellent example of how to
-# properly assemble an email message with a uuencoded attachment.
+# properly assemble an email message with a base64 encoded attachment.
 #
 
-LOGFILE=/tmp/last_sent_voicemail.log
+LOGFILE=/tmp/voicemail/last_sent_voicemail.log
 
 # Redirect standard error and standard output to a log file.
 rm  -f "$LOGFILE"
@@ -58,8 +58,8 @@ REPLY="do-not-reply@pbx"
 SUBJECT="Voicemail from $CALLERID, $DATE, $TIME"
 MSGBODY="$CALLERID has left voicemail for you on $DATE at $TIME."
 MIMETYPE="audio/wav"
-TMP1="/tmp/tmpemail1.$$";
-TMP2="/tmp/tmpemail2.$$";
+TMP1="/tmp/voicemail/tmpemail1.$$";
+TMP2="/tmp/voicemail/tmpemail2.$$";
 BOUNDARY="`date +%s | md5sum | awk '{print $1}'`"
 FILENAME="voicemail-$DATE-$TIME.WAV"
 
@@ -97,7 +97,7 @@ append_to_file $TMP2 ""
 
 # Cat everything together and pass to msmtprc to send out.
 ( cat $TMP1
-  cat "$ATTACHMENT" | uuencode --base64 /dev/stdout | sed -e '1,1d' -e '$d'
+  cat "$ATTACHMENT" | base64
   cat $TMP2 ) | msmtp -t -C /etc/pbx-msmtprc
 
 # Clean up email temp files.
index 4f10340..5d4f135 100644 (file)
@@ -250,6 +250,7 @@ s:tab("qos",  translate("QoS Settings"),
 ringtime = s:taboption("general", Value, "ringtime", translate("Number of Seconds to Ring"),
                  translate("Set the number of seconds to ring users upon incoming calls before hanging up \
                  or going to voicemail, if the voicemail is installed and enabled."))
+ringtime.datatype = "port"
 ringtime.default = 30
 
 ua = s:taboption("general", Value, "useragent", translate("User Agent String"),
@@ -259,17 +260,18 @@ ua = s:taboption("general", Value, "useragent", translate("User Agent String"),
 ua.default = appname
 
 h = s:taboption("remote_usage", Value, "externhost", translate("Domain/IP Address/Dynamic Domain"),
-                translate("You can enter your domain name, external IP address, or dynamic domain name here \
-                Please keep in mind that if your IP address is dynamic and it changes your configuration \
-                will become invalid. Hence, it's recommended to set up Dynamic DNS in this case."))
-h.datatype = "hostname"
+                translate("You can enter your domain name, external IP address, or dynamic domain name here. \
+                The best thing to input is a static IP address. If your IP address is dynamic and it changes, \
+                your configuration will become invalid. Hence, it's recommended to set up Dynamic DNS in this case. \
+                and enter your Dynamic DNS hostname here. You can configure Dynamic DNS with the luci-app-ddns package."))
+h.datatype = "host"
 
 p = s:taboption("remote_usage", Value, "bindport", translate("External SIP Port"),
                 translate("Pick a random port number between 6500 and 9500 for the service to listen on. \
                 Do not pick the standard 5060, because it is often subject to brute-force attacks. \
-                When finished, (1) click \"Save and Apply\", and (2) click the \"Restart VoIP Service\" \
-                button above. Finally, (3) look in the \"SIP Device/Softphone Accounts\" section for \
-                updated Server and Port settings for your SIP Devices/Softphones."))
+                When finished, (1) click \"Save and Apply\", and (2) look in the \
+                \"SIP Device/Softphone Accounts\" section for updated Server and Port settings \
+                for your SIP Devices/Softphones."))
 p.datatype = "port"
 
 p = s:taboption("remote_usage", Value, "rtpstart", translate("RTP Port Range Start"),
index d4f21cd..ca373d6 100644 (file)
@@ -150,7 +150,7 @@ for k,v in pairs(validoutaccounts) do
    patterns = s:option(DynamicList, k, v)
    
    -- If the saved field is empty, we return a string
-   -- telling the user that this account would dial any exten.
+   -- telling the user that this provider would dial any exten.
    function patterns.cfgvalue(self, section)
       value = self.map:get(section, self.option)
       
@@ -200,8 +200,8 @@ s.anonymous = true
 for k,v in pairs(validinaccounts) do
    users = s:option(DynamicList, k, v)
    
-   -- If the saved field is empty, we return a string
-   -- telling the user that this account would dial any exten.
+   -- If the saved field is empty, we return a string telling the user that
+   -- this provider would ring all users configured for incoming calls.
    function users.cfgvalue(self, section)
       value = self.map:get(section, self.option)
       
@@ -253,8 +253,8 @@ s.anonymous = true
 for k,v in pairs(validoutusers) do
    providers = s:option(DynamicList, k, k)
 
-   -- If the saved field is empty, we return a string
-   -- telling the user that this account would dial any exten.
+   -- If the saved field is empty, we return a string telling the user
+   -- that this user uses all providers enavled for outgoing calls.
    function providers.cfgvalue(self, section)
       value = self.map:get(section, self.option)
       
@@ -289,11 +289,64 @@ end
 ----------------------------------------------------------------------------------------------------
 s = m:section(TypedSection, "callthrough_numbers", translate("Call-through Numbers"),
         translate("Designate numbers that are allowed to call through this system and which user's \
-                  privileges it will have."))
+                  privileges they will have."))
+s.anonymous = true
+s.addremove = true
+
+num = s:option(DynamicList, "callthrough_number_list", translate("Call-through Numbers"),
+        translate("Specify numbers individually here. Press enter to add more numbers. \
+        You will have to experiment with what country and area codes you need to add \
+        to the number."))
+num.datatype = "uinteger"
+
+p = s:option(ListValue, "enabled", translate("Enabled"))
+p:value("yes", translate("Yes"))
+p:value("no",  translate("No"))
+p.default = "yes"
+
+user = s:option(Value, "defaultuser",  translate("User Name"),
+         translate("The number(s) specified above will be able to dial out with this user's providers. \
+                   Invalid usernames, including users not enabled for outgoing calls, are dropped silently. \
+                   Please verify that the entry was accepted."))
+function user.write(self, section, value)
+   trimuser = luci.util.trim(value)
+   if allvalidusers[trimuser] == true then
+      Value.write(self, section, trimuser)
+   end
+end
+
+pwd = s:option(Value, "pin", translate("PIN"),
+               translate("Your PIN disappears when saved for your protection. It will be changed \
+                         only when you enter a value different from the saved one. Leaving the PIN \
+                         empty is possible, but please beware of the security implications."))
+pwd.password = true
+pwd.rmempty = false
+
+-- We skip reading off the saved value and return nothing.
+function pwd.cfgvalue(self, section)
+    return "" 
+end
+
+-- We check the entered value against the saved one, and only write if the entered value is
+-- something other than the empty string, and it differes from the saved value.
+function pwd.write(self, section, value)
+    local orig_pwd = m:get(section, self.option)
+    if value and #value > 0 and orig_pwd ~= value then
+        Value.write(self, section, value)
+    end
+end
+
+----------------------------------------------------------------------------------------------------
+s = m:section(TypedSection, "callback_numbers", translate("Call-back Numbers"),
+        translate("Designate numbers to whom the system will hang up and call back, which provider will \
+                   be used to call them, and which user's privileges will be granted to them."))
 s.anonymous = true
 s.addremove = true
 
-num = s:option(DynamicList, "callthrough_number_list", translate("Call-through Numbers"))
+num = s:option(DynamicList, "callback_number_list", translate("Call-back Numbers"),
+        translate("Specify numbers individually here. Press enter to add more numbers. \
+        You will have to experiment with what country and area codes you need to add \
+        to the number."))
 num.datatype = "uinteger"
 
 p = s:option(ListValue, "enabled", translate("Enabled"))
@@ -301,6 +354,13 @@ p:value("yes", translate("Yes"))
 p:value("no",  translate("No"))
 p.default = "yes"
 
+delay = s:option(Value, "callback_hangup_delay", translate("Hang-up Delay"),
+            translate("How long to wait before hanging up. If the provider you use to dial automatically forwards \
+            to voicemail, you can set this value to a delay that will allow you to hang up before your call gets \
+            forwarded and you get billed for it."))
+delay.datatype = "uinteger"
+delay.default = 0
+
 user = s:option(Value, "defaultuser",  translate("User Name"),
          translate("The number(s) specified above will be able to dial out with this user's providers. \
                    Invalid usernames, including users not enabled for outgoing calls, are dropped silently. \
@@ -333,6 +393,17 @@ function pwd.write(self, section, value)
     end
 end
 
+provider = s:option(Value, "callback_provider",  translate("Call-back Provider"),
+         translate("Enter a VoIP provider to use for call-back in the format username@some.host.name, as listed in \
+         \"Outgoing Calls\" above. It's easiest to copy and paste the providers from above. Invalid entries, including \
+         providers not enabled for outgoing calls, will be rejected silently."))
+function provider.write(self, section, value)
+    cooked = string.gsub(luci.util.trim(value), "%W", "_")
+    if validoutaccounts[cooked] ~= nil then
+        Value.write(self, section, value)
+    end
+end
+
 ----------------------------------------------------------------------------------------------------
 s = m:section(NamedSection, "blacklisting", "call_routing", translate("Blacklisted Numbers"),
               translate("Enter phone numbers that you want to decline calls from automatically. \
index 99663a9..e05ae11 100755 (executable)
@@ -54,6 +54,14 @@ TMPL_EXTCTHRUCHECK=$TEMPLATEDIR/extensions_disa-check.conf.TEMPLATE
 TMPL_EXTCTHRUCHECKFTR=$TEMPLATEDIR/extensions_disa-check_footer.conf.TEMPLATE
 TMPL_EXTCTHRUHDR=$TEMPLATEDIR/extensions_disa_header.conf.TEMPLATE
 TMPL_EXTCTHRU=$TEMPLATEDIR/extensions_disa.conf.TEMPLATE
+TMPL_EXTCTHRUNOPIN=$TEMPLATEDIR/extensions_disa-nopin.conf.TEMPLATE
+
+TMPL_EXTCBACKCHECKHDR=$TEMPLATEDIR/extensions_callback-check_header.conf.TEMPLATE
+TMPL_EXTCBACKCHECK=$TEMPLATEDIR/extensions_callback-check.conf.TEMPLATE
+TMPL_EXTCBACKCHECKFTR=$TEMPLATEDIR/extensions_callback-check_footer.conf.TEMPLATE
+TMPL_EXTCBACKHDR=$TEMPLATEDIR/extensions_callback_header.conf.TEMPLATE
+TMPL_EXTCBACKSIP=$TEMPLATEDIR/extensions_callback_sip.conf.TEMPLATE
+TMPL_EXTCBACKGTALK=$TEMPLATEDIR/extensions_callback_gtalk.conf.TEMPLATE
 
 TMPL_EXTENSIONS=$TEMPLATEDIR/extensions.conf.TEMPLATE
 
@@ -114,6 +122,18 @@ localusers_can_dial=""
 # which will be used to dial out by default (whose outgoing contexts will
 # be included in users' contexts by default.
 outbound_providers=""
+sip_outbound_providers=""
+gtalk_outbound_providers=""
+
+# Function which escapes non-alpha-numeric characters in a string
+escape_non_alpha() {
+    echo $@ | sed 's/\([^a-zA-Z0-9]\)/\\\1/g'
+}
+
+# Function which replaces non-alpha-numeric characters with an underscore
+sub_underscore_for_non_alpha() {
+    echo $@ | sed 's/[^a-zA-Z0-9]/_/g'
+}
 
 # Copies the template files which we don't edit.
 copy_unedited_templates_over()
@@ -149,6 +169,7 @@ pbx_create_extensions_config()
     rm -f $WORKDIR/outextgtalk.TMP
     mv  $WORKDIR/blacklist.TMP                       $WORKDIR/extensions_blacklist.conf
     mv  $WORKDIR/userext.TMP                         $WORKDIR/extensions_user.conf
+
     cp  $TMPL_EXTCTHRUHDR                            $WORKDIR/extensions_callthrough.conf
     cat $WORKDIR/callthrough.TMP                  >> $WORKDIR/extensions_callthrough.conf 2>/dev/null
     rm -f $WORKDIR/callthrough.TMP
@@ -156,6 +177,15 @@ pbx_create_extensions_config()
     cat $WORKDIR/callthroughcheck.TMP             >> $WORKDIR/extensions_callthrough.conf 2>/dev/null
     rm -f $WORKDIR/callthroughcheck.TMP
     cat $TMPL_EXTCTHRUCHECKFTR                    >> $WORKDIR/extensions_callthrough.conf 2>/dev/null
+
+    cp  $TMPL_EXTCBACKHDR                            $WORKDIR/extensions_callback.conf
+    cat $WORKDIR/callback.TMP                     >> $WORKDIR/extensions_callback.conf 2>/dev/null
+    rm -f $WORKDIR/callback.TMP
+    cat $TMPL_EXTCBACKCHECKHDR                    >> $WORKDIR/extensions_callback.conf 2>/dev/null
+    cat $WORKDIR/callbackcheck.TMP                >> $WORKDIR/extensions_callback.conf 2>/dev/null
+    rm -f $WORKDIR/callbackcheck.TMP
+    cat $TMPL_EXTCBACKCHECKFTR                    >> $WORKDIR/extensions_callback.conf 2>/dev/null
+
     rm -f $WORKDIR/outext-*.TMP
     rm -f $WORKDIR/localext.TMP
     sed "s/|LOCALUSERS|/$localusers_to_ring/g" $TMPL_EXTDEFAULT \
@@ -246,13 +276,17 @@ pbx_add_user()
 {
     local fullname
     local defaultuser
+    local rawdefaultuser
     local secret
     local ring
     local can_call
 
     config_get fullname    $1 fullname
-    config_get defaultuser $1 defaultuser
+    fullname=`escape_non_alpha $fullname`
+    config_get rawdefaultuser $1 defaultuser
+    defaultuser=`escape_non_alpha $rawdefaultuser`
     config_get secret      $1 secret
+    secret=`escape_non_alpha $secret`
     config_get ring        $1 ring
     config_get can_call    $1 can_call
 
@@ -263,7 +297,7 @@ pbx_add_user()
 
     if [ "$can_call" = "yes" ] ; then
         # Add user to list of all users that are allowed to make calls.
-        localusers_can_dial="$localusers_can_dial $defaultuser"
+        localusers_can_dial="$localusers_can_dial $rawdefaultuser"
         sed -i "s/|CONTEXTNAME|/$defaultuser/g"     $WORKDIR/sip_user.tmp
     else
         sed -i "s/|CONTEXTNAME|/$HANGUPCNTXT/g"     $WORKDIR/sip_user.tmp
@@ -307,13 +341,18 @@ pbx_add_jabber()
     local statusmessage
 
     config_get username $1 username
+    username=`escape_non_alpha $username`
     config_get secret $1 secret
+    secret=`escape_non_alpha $secret`
+    #TODO: Is this really necessary here? Numprefix is retrieved below.
     config_get numprefix $1 numprefix
     config_get register $1 register
     config_get make_outgoing_calls $1 make_outgoing_calls
     config_get name $1 name
     config_get status $1 status
+    status=`escape_non_alpha $status`
     config_get statusmessage $1 statusmessage
+    statusmessage=`escape_non_alpha $statusmessage`
 
     [ -z "$username" -o -z "$secret" ] && return
 
@@ -338,7 +377,7 @@ pbx_add_jabber()
             # messes entered by users.
             set $users_to_ring
             users_to_ring="SIP\/$1" && shift
-            for u in $@ ; do users_to_ring=$users_to_ring\\\&SIP\\\/$u ; done
+            for u in $@ ; do u=`escape_non_alpha $u` ; users_to_ring=$users_to_ring\\\&SIP\\\/$u ; done
         fi
 
         # Now, we add this account to the gtalk incoming context.
@@ -361,6 +400,7 @@ pbx_add_jabber()
         [ -z "$numprefix" ]  && numprefix="X"
 
         for p in $numprefix ; do
+            p=`escape_non_alpha $p`
             sed "s/|NUMPREFIX|/$p/g" $TMPL_EXTOUTGTALK |\
                             sed "s/|NAME|/$name/g"            >> $WORKDIR/outext-$name.TMP
         done
@@ -371,6 +411,13 @@ pbx_add_jabber()
         else
             outbound_providers="$outbound_providers $name"
         fi
+
+        # Add this provider to the list of enabled gtalk outbound providers.
+        if [ -z "$gtalk_outbound_providers" ] ; then
+            gtalk_outbound_providers="$name"
+        else
+            gtalk_outbound_providers="$gtalk_outbound_providers $name"
+        fi
     fi
 
     rm -f $WORKDIR/jabber.tmp
@@ -394,11 +441,16 @@ pbx_add_peer()
     local outboundproxy
 
     config_get defaultuser $1 defaultuser
+    defaultuser=`escape_non_alpha $defaultuser`
     config_get secret $1 secret
+    secret=`escape_non_alpha $secret`
     config_get host $1 host
+    host=`escape_non_alpha $host`
     config_get port $1 port
     config_get outbountproxy $1 outboundproxy
+    outbountproxy=`escape_non_alpha $outbountproxy`
     config_get fromdomain $1 fromdomain
+    fromdomain=`escape_non_alpha $fromdomain`
     config_get register $1 register
     config_get numprefix $1 numprefix
     config_get make_outgoing_calls $1 make_outgoing_calls
@@ -453,6 +505,7 @@ pbx_add_peer()
         # If no prefixes are specified, then we use "X" which matches any prefix.
         [ -z "$numprefix" ]  && numprefix="X"
         for p in $numprefix ; do
+            p=`escape_non_alpha $p`
             sed "s/|NUMPREFIX|/$p/g" $TMPL_EXTOUTSIP |\
                             sed "s/|NAME|/$name/g"              >> $WORKDIR/outext-$name.TMP
         done
@@ -463,6 +516,13 @@ pbx_add_peer()
         else
             outbound_providers="$outbound_providers $name"
         fi
+
+        # Add this provider to the list of enabled sip outbound providers.
+        if [ -z "$sip_outbound_providers" ] ; then
+            sip_outbound_providers="$name"
+        else
+            sip_outbound_providers="$sip_outbound_providers $name"
+        fi
     fi
 
     rm -f $WORKDIR/sip_peer.tmp
@@ -477,6 +537,7 @@ pbx_create_user_contexts()
     local providers
 
     for u in $localusers_can_dial ; do
+        u=`escape_non_alpha $u`
         sed "s/|DEFAULTUSER|/$u/g" $TMPL_EXTUSERCNTXTHDR                >> $WORKDIR/userext.TMP
         cat $WORKDIR/localext.TMP                                       >> $WORKDIR/userext.TMP
         providers="`uci -q get ${MODULENAME}-calls.providers_user_can_use.$u`"
@@ -504,6 +565,7 @@ pbx_add_blacklist()
     # to the context for a check against the list anyway.
     cp $TMPL_EXTBLKLISTHDR                                   $WORKDIR/blacklist.TMP
     for n in $blacklist1 $blacklist2 ; do
+        n=`escape_non_alpha $n`
         sed "s/|BLACKLISTITEM|/$n/g" $TMPL_EXTBLKLIST >> $WORKDIR/blacklist.TMP 
     done
     cat $TMPL_EXTBLKLISTFTR                               >> $WORKDIR/blacklist.TMP
@@ -517,10 +579,13 @@ pbx_add_callthrough()
     local defaultuser
     local pin
     local enabled
+    local F
 
     config_get callthrough_number_list $1 callthrough_number_list
     config_get defaultuser $1 defaultuser
+    defaultuser=`escape_non_alpha $defaultuser`
     config_get pin $1 pin
+    pin=`escape_non_alpha $pin`
     config_get enabled $1 enabled
 
     [ "$enabled" = "no" ]   && return
@@ -529,12 +594,66 @@ pbx_add_callthrough()
     for callthrough_number in $callthrough_number_list ; do
         sed "s/|NUMBER|/$callthrough_number/g" $TMPL_EXTCTHRUCHECK >> $WORKDIR/callthroughcheck.TMP
 
-        sed "s/|NUMBER|/$callthrough_number/g" $TMPL_EXTCTHRU |\
-                    sed "s/|DEFAULTUSER|/$defaultuser/"               |\
-                        sed "s/|PIN|/$pin/"                                >> $WORKDIR/callthrough.TMP
+       if [ -n "$pin" ] ; then F=$TMPL_EXTCTHRU ; else F=$TMPL_EXTCTHRUNOPIN ; fi
+        sed "s/|NUMBER|/$callthrough_number/g" $F             |\
+                    sed "s/|DEFAULTUSER|/$defaultuser/"       |\
+                        sed "s/|PIN|/$pin/"                        >> $WORKDIR/callthrough.TMP
     done
 }
 
+
+# Creates the callback context which allows specified numbers to get
+# a callback into the PBX and dial out as the configured user.
+pbx_add_callback()
+{
+    local callback_number_list
+    local defaultuser
+    local pin
+    local enabled
+    local callback_provider
+    local callback_hangup_delay
+    local FB
+    local FT
+
+    config_get callback_number_list $1 callback_number_list
+    config_get defaultuser $1 defaultuser
+    defaultuser=`escape_non_alpha $defaultuser`
+    config_get pin $1 pin
+    pin=`escape_non_alpha $pin`
+    config_get enabled $1 enabled
+    config_get callback_provider $1 callback_provider
+    callback_provider=`sub_underscore_for_non_alpha $callback_provider`
+    config_get callback_hangup_delay $1 callback_hangup_delay
+
+    [ "$enabled" = "no" ]   && return
+    [ "$defaultuser" = "" ] && return
+
+    # If the provider is a SIP provider, set the file to use to $TMPL_EXTCBACKSIP
+    # otherwise, set it to $TMPL_EXTCBACKGTALK
+    if echo $sip_outbound_providers | grep -q $callback_provider 2>/dev/null
+    then
+        FB=$TMPL_EXTCBACKSIP
+    else
+        FB=$TMPL_EXTCBACKGTALK
+    fi
+
+    for callback_number in $callback_number_list ; do
+        sed "s/|NUMBER|/$callback_number/g" $TMPL_EXTCBACKCHECK    >> $WORKDIR/callbackcheck.TMP
+
+        sed "s/|NUMBER|/$callback_number/g" $FB            |\
+            sed "s/|CALLBACKPROVIDER|/$callback_provider/" |\
+                sed "s/|CALLBACKHUPDELAY|/$callback_hangup_delay/" >> $WORKDIR/callback.TMP
+
+        # Perhaps a bit confusingly, we create "callthrough" configuration for callback
+        # numbers, because we use the same DISA construct as for callthrough.
+        if [ -n "$pin" ] ; then FT=$TMPL_EXTCTHRU ; else FT=$TMPL_EXTCTHRUNOPIN ; fi
+        sed "s/|NUMBER|/$callback_number/g" $FT            |\
+            sed "s/|DEFAULTUSER|/$defaultuser/"            |\
+                sed "s/|PIN|/$pin/"                                >> $WORKDIR/callthrough.TMP
+    done
+}
+
+
 # Creates sip.conf from its template.
 pbx_cook_sip_template()
 {
@@ -543,6 +662,7 @@ pbx_cook_sip_template()
     local bindport
 
     config_get useragent advanced useragent
+    useragent=`escape_non_alpha $useragent`
     config_get externhost advanced externhost
     config_get bindport advanced bindport
 
@@ -628,7 +748,9 @@ pbx_configure_voicemail()
     config_get smtp_server            voicemail_smtp   smtp_server
     config_get smtp_port              voicemail_smtp   smtp_port
     config_get smtp_user              voicemail_smtp   smtp_user
+    smtp_user=`escape_non_alpha $smtp_user`
     config_get smtp_password          voicemail_smtp   smtp_password
+    smtp_password=`escape_non_alpha $smtp_password`
 
     sed "s/|AUTH|/$smtp_auth/"   $TMPL_MSMTPDEFAULT |\
              sed "s/|TLS|/$smtp_tls/"               >  $WORKDIR/pbx-msmtprc
@@ -644,12 +766,25 @@ pbx_configure_voicemail()
     cat $TMPL_MSMTPACCTDFLT                         >> $WORKDIR/pbx-msmtprc
 
     [ ! -f /etc/pbx-msmtprc ] && cp $WORKDIR/pbx-msmtprc /etc/pbx-msmtprc
-    diff -q  $WORKDIR/pbx-msmtprc /etc/pbx-msmtprc 1>/dev/null \
+    cmp -s  $WORKDIR/pbx-msmtprc /etc/pbx-msmtprc 1>/dev/null \
                                 || mv $WORKDIR/pbx-msmtprc /etc/pbx-msmtprc
     chmod 600                                              /etc/pbx-msmtprc
+    chown nobody                                           /etc/pbx-msmtprc
 
     # Copy over the extensions file which has voicemail enabled.
     cp $TMPL_EXTVMENABLED                $WORKDIR/extensions_voicemail.conf
+
+    # Create the voicemail directory in /tmp
+    mkdir -p     /tmp/voicemail
+    chown nobody /tmp/voicemail
+
+    # Create the recordings directory
+    mkdir -p     /etc/pbx-voicemail/recordings
+    chown nobody /etc/pbx-voicemail/recordings
+
+    # Working around a bug in OpenWRT 12.09-rc1
+    # TODO: REMOVE AS SOON AS POSSIBLE
+    chmod ugo+w /tmp
 }
 
 
@@ -670,12 +805,13 @@ start() {
     config_load ${MODULENAME}-voip
     config_foreach pbx_add_peer voip_provider
 
-    # Create the user contexts, and phone blacklist.
+    # Create the user contexts, callthroug/back, and phone blacklist.
     config_unset
     config_load ${MODULENAME}-calls
     pbx_create_user_contexts
     pbx_add_blacklist
     config_foreach pbx_add_callthrough callthrough_numbers
+    config_foreach pbx_add_callback callback_numbers
 
     # Prepare sip.conf using settings from the "advanced" section.
     config_unset
diff --git a/applications/luci-pbx/root/etc/pbx-asterisk/delayedcallback b/applications/luci-pbx/root/etc/pbx-asterisk/delayedcallback
new file mode 100755 (executable)
index 0000000..903efe9
--- /dev/null
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+# Check if there are more than one instance of this command
+# with the same command line running at the same time for some
+# reason, then quit. We are checking for the same
+# commandline in order to permit two different callback
+# attempts simultaneously.
+
+if ! grep -q "$@" /dev/shm/delayedcallback.[0-9]* 2>/dev/null
+then
+  echo "$@" > /dev/shm/delayedcallback.$$
+  sleep 25
+  asterisk -r -x "$1 $2 \"$3\" $4 $5 $6"
+  rm /dev/shm/delayedcallback.$$
+#  echo "`date` $@": >> /dev/shm/delayedcallback.log
+#else
+#  echo "`date` ERROR: There appears to be a callback attempt in progress to: $@" >> /dev/shm/delayedcallback.err
+fi
index 534945c..c8966ed 100644 (file)
@@ -21,4 +21,5 @@ exten   => _[!-~].,1,Dial(SIP/${EXTEN},60,r)
 #include extensions_incoming_gtalk.conf
 #include extensions_blacklist.conf
 #include extensions_callthrough.conf
+#include extensions_callback.conf
 #include extensions_user.conf
diff --git a/applications/luci-pbx/root/etc/pbx-asterisk/extensions_callback-check.conf.TEMPLATE b/applications/luci-pbx/root/etc/pbx-asterisk/extensions_callback-check.conf.TEMPLATE
new file mode 100644 (file)
index 0000000..06b1a4b
--- /dev/null
@@ -0,0 +1 @@
+exten => s,n,Gotoif($[ "${CALLERID(NUM)}" =~ ".*|NUMBER|" ]?context-user-callback,|NUMBER|,1)
diff --git a/applications/luci-pbx/root/etc/pbx-asterisk/extensions_callback-check_footer.conf.TEMPLATE b/applications/luci-pbx/root/etc/pbx-asterisk/extensions_callback-check_footer.conf.TEMPLATE
new file mode 100644 (file)
index 0000000..282fe9e
--- /dev/null
@@ -0,0 +1,2 @@
+exten => s,n,Goto(${SOURCECONTEXT},${SOURCEEXTEN},donecallback)
+
diff --git a/applications/luci-pbx/root/etc/pbx-asterisk/extensions_callback-check_header.conf.TEMPLATE b/applications/luci-pbx/root/etc/pbx-asterisk/extensions_callback-check_header.conf.TEMPLATE
new file mode 100644 (file)
index 0000000..be289c4
--- /dev/null
@@ -0,0 +1,3 @@
+
+[callback-check-call-context]
+exten => s,1,Noop()
diff --git a/applications/luci-pbx/root/etc/pbx-asterisk/extensions_callback_gtalk.conf.TEMPLATE b/applications/luci-pbx/root/etc/pbx-asterisk/extensions_callback_gtalk.conf.TEMPLATE
new file mode 100644 (file)
index 0000000..43eec78
--- /dev/null
@@ -0,0 +1,4 @@
+exten => |NUMBER|,1,System(/etc/pbx-asterisk/delayedcallback "channel originate Gtalk/gtalk-|CALLBACKPROVIDER|/|NUMBER|@voice.google.com extension |NUMBER|@disa-call-context" &)
+exten => |NUMBER|,n,Wait(|CALLBACKHUPDELAY|)
+exten => |NUMBER|,n,Hangup()
+
diff --git a/applications/luci-pbx/root/etc/pbx-asterisk/extensions_callback_header.conf.TEMPLATE b/applications/luci-pbx/root/etc/pbx-asterisk/extensions_callback_header.conf.TEMPLATE
new file mode 100644 (file)
index 0000000..0b8fb4c
--- /dev/null
@@ -0,0 +1 @@
+[context-user-callback]
diff --git a/applications/luci-pbx/root/etc/pbx-asterisk/extensions_callback_sip.conf.TEMPLATE b/applications/luci-pbx/root/etc/pbx-asterisk/extensions_callback_sip.conf.TEMPLATE
new file mode 100644 (file)
index 0000000..300e9fa
--- /dev/null
@@ -0,0 +1,4 @@
+exten => |NUMBER|,1,System(/etc/pbx-asterisk/delayedcallback "channel originate SIP/|NUMBER|@peer-|CALLBACKPROVIDER| extension |NUMBER|@disa-call-context" &)
+exten => |NUMBER|,n,Wait(|CALLBACKHUPDELAY|)
+exten => |NUMBER|,n,Hangup()
+
index 8d37ddc..35836e2 100644 (file)
@@ -4,6 +4,8 @@ exten => s,n,Set(SOURCECONTEXT=default-incoming-call-context)
 exten => s,n,Set(SOURCEEXTEN=s)
 exten => s,n,Goto(blacklist-call-context,s,1)
 exten => s,n(doneblacklist),NoOp()
+exten => s,n,Goto(callback-check-call-context,s,1)
+exten => s,n(donecallback),NoOp()
 exten => s,n,Goto(disa-check-call-context,s,1)
 exten => s,n(donedisacheck),Dial(|LOCALUSERS|,${RINGTIME},r)
 exten => s,n,Goto(context-voicemail,s,1)
diff --git a/applications/luci-pbx/root/etc/pbx-asterisk/extensions_disa-nopin.conf.TEMPLATE b/applications/luci-pbx/root/etc/pbx-asterisk/extensions_disa-nopin.conf.TEMPLATE
new file mode 100644 (file)
index 0000000..74e48de
--- /dev/null
@@ -0,0 +1,5 @@
+exten => |NUMBER|,1,Noop()
+exten => |NUMBER|,n,Set(TIMEOUT(digit)=15)
+exten => |NUMBER|,n,Set(TIMEOUT(response)=40)
+exten => |NUMBER|,n,DISA(no-password,context-user-|DEFAULTUSER|)
+
index f0ca372..3f9cf4c 100644 (file)
@@ -7,6 +7,8 @@ same => n,Set(SOURCECONTEXT=context-incoming-gtalk)
 same => n,Set(SOURCEEXTEN=|USERNAME|)
 same => n,Goto(blacklist-call-context,s,1)
 same => n(doneblacklist),NoOp()
+same => n,Goto(callback-check-call-context,s,1)
+same => n(donecallback),NoOp()
 same => n,Goto(disa-check-call-context,s,1)
 same => n(donedisacheck),Dial(|LOCALUSERS|,${RINGTIME},D(:w11111111))
 same => n,Goto(context-voicemail,s,1)
index 1956007..b2c3716 100644 (file)
@@ -5,6 +5,8 @@ exten => s,n,Set(SOURCECONTEXT=context-incoming-|NAME|)
 exten => s,n,Set(SOURCEEXTEN=s)
 exten => s,n,Goto(blacklist-call-context,s,1)
 exten => s,n(doneblacklist),NoOp()
+exten => s,n,Goto(callback-check-call-context,s,1)
+exten => s,n(donecallback),NoOp()
 exten => s,n,Goto(disa-check-call-context,s,1)
 exten => s,n(donedisacheck),Dial(|LOCALUSERS|,${RINGTIME},r)
 exten => s,n,Goto(context-voicemail,s,1)
index e4b34b5..4edd9cb 100644 (file)
@@ -1,15 +1,27 @@
 [context-voicemail-record-greeting]
-exten =>     *789,1,Wait(2)
-exten =>     *789,n,Playback(/etc/pbx-voicemail/greeting)
-exten =>     *789,n,Wait(5)
-exten =>     *789,n,Record(/etc/pbx-voicemail/greeting:WAV,20,90,k)
-exten =>     *789,n,Wait(2)
-exten =>     *789,n,Playback(/etc/pbx-voicemail/greeting)
+exten =>     *789,1,Wait(1)
+exten =>     *789,n,Playback(/etc/pbx-voicemail/recordings/greeting)
+exten =>     *789,n,Wait(1)
+exten =>     *789,n,Playback(beep)
+exten =>     *789,n,Playback(beep)
+exten =>     *789,n,WaitExten(30)
+
+exten =>     t,1,Playback(vm-goodbye)
+exten =>     t,n,Wait(2)
+exten =>     t,n,Hangup()
+
+exten =>     *,1,Playback(beep)
+exten =>     *,n,Playback(beep)
+exten =>     *,n,Record(/tmp/voicemail/greeting:gsm,20,120,k)
+exten =>     *,n,Wait(1)
+exten =>     *,n,Playback(/tmp/voicemail/greeting)
+
+exten =>     h,1,System(/etc/pbx-voicemail/pbx-move-greeting &)
 
 [context-voicemail]
 exten =>     s,1,Wait(2)
-exten =>     s,2,Playback(/etc/pbx-voicemail/greeting)
+exten =>     s,2,Playback(/etc/pbx-voicemail/recordings/greeting)
 exten =>     s,3,Wait(2)
-exten =>     s,n,Record(/tmp/voicemail%d:WAV,20,180,k)
+exten =>     s,n,Record(/tmp/voicemail/voicemail%d:WAV,20,180,k)
 
 exten =>     h,1,System(/etc/pbx-voicemail/pbx-send-voicemail '${RECORDED_FILE}.WAV' '${CALLERID(all)}' &)
index 6069554..8f3b112 100644 (file)
@@ -1,4 +1,5 @@
 [general]
+transport=udp
 context=default-incoming-call-context
 allowoverlap=yes
 allowtransfer=yes
@@ -28,6 +29,7 @@ directmedia=no
 sipdebug=no
 bindport=|BINDPORT|
 externhost=|EXTERNHOST|
+externrefresh=60
 
 #include sip_registrations.conf
 
diff --git a/applications/luci-pbx/root/etc/pbx-asterisk/sounds/auth-incorrect.gsm b/applications/luci-pbx/root/etc/pbx-asterisk/sounds/auth-incorrect.gsm
new file mode 100644 (file)
index 0000000..12fec25
Binary files /dev/null and b/applications/luci-pbx/root/etc/pbx-asterisk/sounds/auth-incorrect.gsm differ
diff --git a/applications/luci-pbx/root/etc/pbx-asterisk/sounds/beep.gsm b/applications/luci-pbx/root/etc/pbx-asterisk/sounds/beep.gsm
new file mode 100644 (file)
index 0000000..d38eda9
Binary files /dev/null and b/applications/luci-pbx/root/etc/pbx-asterisk/sounds/beep.gsm differ
diff --git a/applications/luci-pbx/root/etc/pbx-asterisk/sounds/vm-goodbye.gsm b/applications/luci-pbx/root/etc/pbx-asterisk/sounds/vm-goodbye.gsm
new file mode 100644 (file)
index 0000000..735b281
Binary files /dev/null and b/applications/luci-pbx/root/etc/pbx-asterisk/sounds/vm-goodbye.gsm differ
index 353e69e..63b1196 100644 (file)
@@ -448,10 +448,16 @@ $(eval $(call application,pbx,LuCI PBX Administration,\
        +PACKAGE_luci-app-pbx:asterisk18-codec-a-mu \
        +PACKAGE_luci-app-pbx:asterisk18-codec-alaw \
        +PACKAGE_luci-app-pbx:asterisk18-func-cut \
-       +PACKAGE_luci-app-pbx:asterisk18-res-clioriginate))
+       +PACKAGE_luci-app-pbx:asterisk18-res-clioriginate \
+       +PACKAGE_luci-app-pbx:asterisk18-func-channel \
+       +PACKAGE_luci-app-pbx:asterisk18-chan-local \
+       +PACKAGE_luci-app-pbx:asterisk18-app-record \
+       +PACKAGE_luci-app-pbx:asterisk18-app-senddtmf \
+       +PACKAGE_luci-app-pbx:asterisk18-res-crypto))
 
 $(eval $(call application,pbx-voicemail,LuCI PBX Administration Voicemail Support,\
-       luci-app-pbx +PACKAGE_luci-app-pbx-voicemail:msmtp))
+       luci-app-pbx +PACKAGE_luci-app-pbx-voicemail:msmtp \
+       +PACKAGE_luci-app-pbx-voicemail:coreutils-base64))
 
 $(eval $(call application,ltqtapi,Lantiq voip))