diff --git a/OpenVBX/controllers/audiofiles.php b/OpenVBX/controllers/audiofiles.php
index 3e38ac3d..fbd92237 100644
--- a/OpenVBX/controllers/audiofiles.php
+++ b/OpenVBX/controllers/audiofiles.php
@@ -243,8 +243,17 @@ function add_from_twilio_recording()
function prompt_for_recording_twiml()
{
- validate_rest_request();
-
+ if(!validate_rest_request()) {
+ $response = new TwimlResponse;
+ $response->say('Could not validate this request. Goodbye.', array(
+ 'voice' => $ci->vbx_settings->get('voice', $ci->tenant->id),
+ 'language' => $ci->vbx_settings->get('voice_language', $ci->tenant->id)
+ ));
+ $response->hangup();
+ $response->respond();
+ exit;
+ }
+
$response = new TwimlResponse;
$audioFile = VBX_Audio_File::get(array('recording_call_sid' => $this->input->get_post('CallSid')));
@@ -266,8 +275,17 @@ function prompt_for_recording_twiml()
function replay_recording_twiml()
{
- validate_rest_request();
-
+ if(!validate_rest_request()) {
+ $response = new TwimlResponse;
+ $response->say('Could not validate this request. Goodbye.', array(
+ 'voice' => $ci->vbx_settings->get('voice', $ci->tenant->id),
+ 'language' => $ci->vbx_settings->get('voice_language', $ci->tenant->id)
+ ));
+ $response->hangup();
+ $response->respond();
+ exit;
+ }
+
$response = new TwimlResponse;
if ($this->input->get_post('RecordingUrl'))
@@ -294,8 +312,17 @@ function replay_recording_twiml()
function accept_or_reject_recording_twiml()
{
- validate_rest_request();
-
+ if(!validate_rest_request()) {
+ $response = new TwimlResponse;
+ $response->say('Could not validate this request. Goodbye.', array(
+ 'voice' => $ci->vbx_settings->get('voice', $ci->tenant->id),
+ 'language' => $ci->vbx_settings->get('voice_language', $ci->tenant->id)
+ ));
+ $response->hangup();
+ $response->respond();
+ exit;
+ }
+
$response = new TwimlResponse;
$digits = clean_digits($this->input->get_post('Digits'));
$call_sid = $this->input->get_post('CallSid');
diff --git a/OpenVBX/controllers/numbers.php b/OpenVBX/controllers/numbers.php
index 4629ba4e..da3092f0 100644
--- a/OpenVBX/controllers/numbers.php
+++ b/OpenVBX/controllers/numbers.php
@@ -421,4 +421,4 @@ public function refresh_select() {
$this->respond('', 'dialer/numbers', $response);
}
-}
\ No newline at end of file
+}
diff --git a/OpenVBX/controllers/twiml.php b/OpenVBX/controllers/twiml.php
index e3a2261f..f10d455e 100644
--- a/OpenVBX/controllers/twiml.php
+++ b/OpenVBX/controllers/twiml.php
@@ -74,7 +74,12 @@ function index()
function start_sms($flow_id)
{
- validate_rest_request();
+ if(!validate_rest_request()) {
+ $response = new TwimlResponse;
+ $response->message('Could not validate this request. Goodbye.');
+ $response->respond();
+ exit;
+ }
log_message("info", "Calling SMS Flow $flow_id");
$body = $this->input->get_post('Body');
@@ -104,8 +109,17 @@ function start_sms($flow_id)
function start_voice($flow_id)
{
- validate_rest_request();
-
+ if(!validate_rest_request()) {
+ $response = new TwimlResponse;
+ $response->say('Could not validate this request. Goodbye.', array(
+ 'voice' => $ci->vbx_settings->get('voice', $ci->tenant->id),
+ 'language' => $ci->vbx_settings->get('voice_language', $ci->tenant->id)
+ ));
+ $response->hangup();
+ $response->respond();
+ exit;
+ }
+
log_message("info", "Calling Voice Flow $flow_id");
$this->flow_type = 'voice';
diff --git a/OpenVBX/helpers/token_helper.php b/OpenVBX/helpers/token_helper.php
new file mode 100644
index 00000000..366bfb0b
--- /dev/null
+++ b/OpenVBX/helpers/token_helper.php
@@ -0,0 +1,67 @@
+load->helper('format_helper');
+
+function token_replace($input, $reset = false) {
+ static $tokens = null;
+
+ if(!isset($tokens) || $reset){
+ $tokens = array();
+ $token_names = token_names();
+ foreach ($token_names as $token) {
+ if(isset($_REQUEST[$token])) {
+ $tokens['{' . $token . '}'] = $_REQUEST[$token];
+ switch ($token) {
+ case 'To':
+ case 'From':
+ $tokens['{' . $token . '_Formatted}'] = format_phone($_REQUEST[$token]);
+ break;
+ default:
+ }
+ }
+ }
+ }
+
+ return strtr($input, $tokens);
+}
+
+function token_list() {
+ $token_list = '';
+ foreach(token_names() as $token){
+ $token_list .= "
{{$token}}";
+ }
+ return "";
+}
+
+function token_names(){
+ return array(
+ 'CallSid',
+ 'AccountSid',
+ 'From',
+ 'To',
+ 'CallStatus',
+ 'ApiVersion',
+ 'Direction',
+ 'ForwardedFrom',
+ 'CallerName',
+ 'FromCity',
+ 'FromState',
+ 'FromZip',
+ 'FromCountry',
+ 'ToCity',
+ 'ToState',
+ 'ToZip',
+ 'ToCountry',
+ 'DialCallStatus',
+ 'DialCallSid',
+ 'DialCallDuration',
+ 'RecordingUrl',
+
+ 'MessageSid',
+ 'Body',
+ 'NumMedia',
+ 'MediaContentType1',
+ 'MediaUrl1',
+ );
+}
diff --git a/OpenVBX/helpers/twilio_helper.php b/OpenVBX/helpers/twilio_helper.php
index 092ef36f..5cd732db 100644
--- a/OpenVBX/helpers/twilio_helper.php
+++ b/OpenVBX/helpers/twilio_helper.php
@@ -61,23 +61,13 @@ function generate_capability_token($allow_incoming = true) {
* @param string $failure_message
* @return void
*/
- function validate_rest_request($failure_message = 'Could not validate this request. Goodbye.') {
+ function validate_rest_request() {
$ci =& get_instance();
if ($ci->tenant->type == VBX_Settings::AUTH_TYPE_CONNECT)
{
- return;
- }
-
- if (!OpenVBX::validateRequest()) {
- $response = new TwimlResponse;
- $response->say($failure_message, array(
- 'voice' => $ci->vbx_settings->get('voice', $ci->tenant->id),
- 'language' => $ci->vbx_settings->get('voice_language', $ci->tenant->id)
- ));
- $response->hangup();
- $response->respond();
- exit;
+ return true;
}
+ return OpenVBX::validateRequest();
}
}
diff --git a/OpenVBX/libraries/User_Controller.php b/OpenVBX/libraries/User_Controller.php
index a33076ae..9a44120e 100644
--- a/OpenVBX/libraries/User_Controller.php
+++ b/OpenVBX/libraries/User_Controller.php
@@ -52,6 +52,7 @@ public function __construct()
$this->load->model('vbx_rest_access');
$this->load->model('vbx_message');
$this->load->model('vbx_incoming_numbers');
+ $this->load->model('vbx_outgoing_caller_ids');
$this->load->model('vbx_device');
// When we're in testing mode, allow access to set Hiccup configuration
@@ -373,6 +374,8 @@ protected function get_twilio_numbers()
{
/* Retrieve twilio numbers w/o sandbox */
$numbers = $this->vbx_incoming_numbers->get_numbers();
+ $callerIds = $this->vbx_outgoing_caller_ids->get_caller_ids();
+ $numbers = array_merge($numbers, $callerIds);
}
catch(VBX_IncomingNumberException $e)
{
@@ -380,6 +383,12 @@ protected function get_twilio_numbers()
throw new User_ControllerException($e->getMessage());
/* Silent fail */
}
+ catch (VBX_OutgoingCallerIdException $e)
+ {
+ error_log($e->getMessage());
+ throw new User_ControllerException($e->getMessage());
+ /* Silent fail */
+ }
return $numbers;
}
diff --git a/OpenVBX/models/vbx_outgoing_caller_ids.php b/OpenVBX/models/vbx_outgoing_caller_ids.php
new file mode 100644
index 00000000..a70be8e0
--- /dev/null
+++ b/OpenVBX/models/vbx_outgoing_caller_ids.php
@@ -0,0 +1,88 @@
+api_cache->get($cache_key, __CLASS__, $ci->tenant->id))
+ {
+ return $cache;
+ }
+
+ $caller_ids = array();
+ try {
+ $account = OpenVBX::getAccount();
+ foreach ($account->outgoing_caller_ids as $caller_id)
+ {
+ // check that caller_id is a proper instance type
+ $caller_ids[] = $this->parseOutgoingCallerId($caller_id);
+ }
+ }
+ catch (Exception $e) {
+ $msg = 'Unable to fetch Numbers: ';
+ switch ($e->getCode())
+ {
+ case 20003:
+ $msg .= 'Authentication Failed.';
+ break;
+ default:
+ $msg .= $e->getMessage();
+ }
+ throw new VBX_OutgoingCallerIdException($msg, $e->getCode());
+ }
+
+ $ci->api_cache->set('outgoing-caller-ids', $caller_ids, __CLASS__, $ci->tenant->id);
+
+ return $caller_ids;
+ }
+
+ private function parseOutgoingCallerId($item)
+ {
+ $num = new stdClass();
+ $num->id = $item->sid;
+ $num->name = $item->friendly_name;
+ $num->phone = format_phone($item->phone_number);
+ $num->phone_number = $item->phone_number;
+ $num->capabilities = new stdClass();
+ $num->capabilities->voice = true;
+ $num->capabilities->sms = false;
+
+ return $num;
+ }
+
+ protected function clear_cache()
+ {
+ $ci =& get_instance();
+ $ci->api_cache->invalidate(__CLASS__, $ci->tenant->id);
+ }
+}
\ No newline at end of file
diff --git a/assets/c/applet.css b/assets/c/applet.css
index 23e1c97e..61857ff0 100755
--- a/assets/c/applet.css
+++ b/assets/c/applet.css
@@ -650,7 +650,7 @@
.radio-table .radio-table-row.on .content-cell { background-color: #e5f6ff; }
.radio-table .radio-table-row.off .content-cell { background-color: #eee; }
-.radio-table .radio-table-row.fist .content-cell {
+.radio-table .radio-table-row.first .content-cell {
-moz-border-radius-topright: 4px; /* FF1+ */
-webkit-border-top-right-radius: 4px; /* Saf3+, Chrome */
-khtml-border-top-right-radius: 4px; /* Konqueror */
diff --git a/plugins/sms/applets/sms/script.js b/plugins/sms/applets/sms/script.js
new file mode 100644
index 00000000..feff4bba
--- /dev/null
+++ b/plugins/sms/applets/sms/script.js
@@ -0,0 +1,10 @@
+$(document).ready(function(){
+ var app = $('.flow-instance.standard---sms');
+
+ $('.radio-table .radio-cell input', app).live('click', function(event) {
+ var table = $(event.target).closest('.radio-table');
+ var table_row = $(event.target).closest('.radio-table-row');
+ $('.radio-table-row', table).removeClass('on').addClass('off');
+ table_row.removeClass('off').addClass('on');
+ });
+});
\ No newline at end of file
diff --git a/plugins/sms/applets/sms/twiml.php b/plugins/sms/applets/sms/twiml.php
index 08728c81..b5ab0ddb 100644
--- a/plugins/sms/applets/sms/twiml.php
+++ b/plugins/sms/applets/sms/twiml.php
@@ -1,18 +1,72 @@
load->helper('format_helper');
+$ci->load->helper('token_helper');
+$ci->load->library('DialList');
+
$sms = AppletInstance::getValue('sms');
$next = AppletInstance::getDropZoneUrl('next');
+$message_whom_selector = AppletInstance::getValue('message-whom-selector', 'caller');
+$message_whom_user_or_group = AppletInstance::getUserGroupPickerValue('message-whom-user-or-group');
+$message_whom_number = AppletInstance::getValue('message-whom-number');
+$from_number = AppletInstance::getValue('from-number', null);
+
+switch($message_whom_selector) {
+ case 'user-or-group':
+ // create a dial list from the input state
+ $dial_list = DialList::get($message_whom_user_or_group);
+
+ while ($device = $dial_list->next())
+ {
+ if ($device instanceof VBX_Device && $device->sms)
+ {
+ if (strpos($device->value, 'client:') !== false)
+ {
+ $to_number = str_replace('client:', '', $device->value);
+ }
+ else
+ {
+ $to_number = $device->value;
+ }
+ break;
+ }
+ }
+ break;
+ case 'number':
+ $to_number = normalize_phone_to_E164($message_whom_number);
+ break;
+ case 'caller':
+ default:
+ $to_number = $_REQUEST['From'];
+}
+
+if($from_number == '') {
+ $from_number = $_REQUEST['From'];
+}
+else if($from_number == 'called') {
+ $from_number = $_REQUEST['To'];
+}
+
+$sms = token_replace($sms);
$response = new TwimlResponse;
+$message_opts = array(
+ 'to' => $to_number,
+ 'from' => $from_number,
+);
+
// Call flows still use the legacy TwiML
// for sending messages during calls.
if(AppletInstance::getFlowType() == 'voice')
{
- $response->sms($sms);
+ $response->sms($sms, $message_opts);
}
else
{
- $response->message($sms);
+ $response->message($sms, $message_opts);
}
if(!empty($next))
@@ -20,4 +74,4 @@
$response->redirect($next);
}
-$response->respond();
\ No newline at end of file
+$response->respond();
diff --git a/plugins/sms/applets/sms/ui.php b/plugins/sms/applets/sms/ui.php
index c39392f9..aeaf5dbe 100644
--- a/plugins/sms/applets/sms/ui.php
+++ b/plugins/sms/applets/sms/ui.php
@@ -1,14 +1,105 @@
+load->model('vbx_incoming_numbers');
+ $ci->load->model('vbx_outgoing_caller_ids');
+ $ci->load->helper('token_helper');
+
+ try {
+ $numbers = $ci->vbx_incoming_numbers->get_numbers();
+
+ }
+ catch (VBX_IncomingNumberException $e) {
+ log_message('Incoming numbers exception: '.$e->getMessage().' :: '.$e->getCode());
+ $numbers = array();
+ }
+
+ try {
+ $outgoingCallerIds = $ci->vbx_outgoing_caller_ids->get_caller_ids();
+ }
+ catch (VBX_OutgoingCallerIdException $e) {
+ log_message('Outgoing callerids exception: '.$e->getMessage().' :: '.$e->getCode());
+ $outgoingCallerIds = array();
+ }
+
+ $number_options = array(
+ '' => "Caller's Number",
+ 'called' => 'Called Number',
+ );
+
+ foreach($numbers as $number) {
+ $number_options['Incoming Numbers'][$number->phone_number] = $number->phone . ' <' . $number->name . '>';
+ }
+ foreach($outgoingCallerIds as $outgoingCallerId) {
+ $number_options['Verified Numbers'][$outgoingCallerId->phone_number] = $outgoingCallerId->phone . ' <' . $outgoingCallerId->name . '>';
+ }
+
+ $from_number = AppletInstance::getValue('from-number', null);
+ $message_whom_selector = AppletInstance::getValue('message-whom-selector', 'caller');
+
+?>
-
Send a text message to the caller if they're on the mobile phone.
+
Send a text message to the caller if they're on a mobile phone.
-
Send a text message to the sender.
+
Send a text message to the sender.
-
Note, not currently supported on Toll Free Numbers
+
+
+
Message Whom
+
+
+
+
From Number
+
+
+
+
+
+
Message
-
Next
After the message is sent, continue to the next applet
diff --git a/plugins/standard/applets/dial/TwimlDial.php b/plugins/standard/applets/dial/TwimlDial.php
index 4f0df900..ed9752dd 100644
--- a/plugins/standard/applets/dial/TwimlDial.php
+++ b/plugins/standard/applets/dial/TwimlDial.php
@@ -53,10 +53,14 @@ public function __construct($settings = array())
$this->version = AppletInstance::getValue('version', null);
$this->callerId = AppletInstance::getValue('callerId', null);
- if (empty($this->callerId) && !empty($_REQUEST['From']))
+ if (empty($this->callerId) && !empty($_REQUEST['From']))
{
$this->callerId = $_REQUEST['From'];
}
+ else if($this->callerId == 'called' && !empty($_REQUEST['To']))
+ {
+ $this->callerId = $_REQUEST['To'];
+ }
/* Get current instance */
$this->dial_whom_selector = AppletInstance::getValue('dial-whom-selector');
diff --git a/plugins/standard/applets/dial/ui.php b/plugins/standard/applets/dial/ui.php
index 1ee977b1..f8fcdf2d 100644
--- a/plugins/standard/applets/dial/ui.php
+++ b/plugins/standard/applets/dial/ui.php
@@ -1,15 +1,36 @@
load->model('vbx_incoming_numbers');
-
+ $ci->load->model('vbx_outgoing_caller_ids');
+
try {
$numbers = $ci->vbx_incoming_numbers->get_numbers();
}
catch (VBX_IncomingNumberException $e) {
- log_message('Incoming numbers exception: '.$e->getMessage.' :: '.$e->getCode());
+ log_message('Incoming numbers exception: '.$e->getMessage().' :: '.$e->getCode());
$numbers = array();
}
-
+
+ try {
+ $outgoingCallerIds = $ci->vbx_outgoing_caller_ids->get_caller_ids();
+ }
+ catch (VBX_OutgoingCallerIdException $e) {
+ log_message('Outgoing callerids exception: '.$e->getMessage().' :: '.$e->getCode());
+ $outgoingCallerIds = array();
+ }
+
+ $number_options = array(
+ '' => "Caller's Number",
+ 'called' => 'Called Number',
+ );
+
+ foreach($numbers as $number) {
+ $number_options['Incoming Numbers'][$number->phone_number] = $number->phone . ' <' . $number->name . '>';
+ }
+ foreach($outgoingCallerIds as $outgoingCallerId) {
+ $number_options['Verified Numbers'][$outgoingCallerId->phone_number] = $outgoingCallerId->phone . ' <' . $outgoingCallerId->name . '>';
+ }
+
$callerId = AppletInstance::getValue('callerId', null);
$version = AppletInstance::getValue('version', null);
@@ -69,12 +90,13 @@
Caller ID
diff --git a/system/helpers/form_helper.php b/system/helpers/form_helper.php
index 044c426e..826d5484 100644
--- a/system/helpers/form_helper.php
+++ b/system/helpers/form_helper.php
@@ -312,8 +312,7 @@ function form_dropdown($name = '', $options = array(), $selected = array(), $ext
$key = (string) $key;
$key = htmlspecialchars($key);
- $val = htmlspecialchars($val);
-
+
if (is_array($val))
{
$form .= '