Merge pull request #54 from radiorabe/feature/configurable-cors

Make CORS great again
This commit is contained in:
Robb 2017-03-10 21:44:26 -05:00 committed by GitHub
commit 77ebfa93d3
7 changed files with 66 additions and 48 deletions

View File

@ -3,12 +3,9 @@
class CORSHelper
{
public static function enableATProCrossOriginRequests(&$request, &$response)
public static function enableCrossOriginRequests(&$request, &$response)
{
//Allow AJAX requests from www.airtime.pro. We use this to automatically login users
//after they sign up from the microsite.
//Chrome sends the Origin header for all requests, so we whitelist the webserver's hostname as well.
$response = $response->setHeader('Access-Control-Allow-Origin', '*');
$origin = $request->getHeader('Origin');
if ((!(preg_match("/https?:\/\/localhost/", $origin) === 1)) && ($origin != "") &&
(!in_array($origin, self::getAllowedOrigins())))
@ -16,15 +13,20 @@ class CORSHelper
//Don't allow CORS from other domains to prevent XSS.
throw new Zend_Controller_Action_Exception('Forbidden', 403);
}
//Allow AJAX requests from configured websites. We use this to allow other pages to use LibreTimes API.
if ($origin) {
$response = $response->setHeader('Access-Control-Allow-Origin', $origin);
}
}
public static function getAllowedOrigins()
{
return array("http://www.airtime.pro",
"https://www.airtime.pro",
"https://account.sourcefabric.com",
"https://account.sourcefabric.com:5001",
$allowedCorsUrls = array_map(
function($v) { return trim($v); },
explode(PHP_EOL, Application_Model_Preference::GetAllowedCorsUrls())
);
return array_merge($allowedCorsUrls, array(
"http://" . $_SERVER['SERVER_NAME'],
"https://" . $_SERVER['SERVER_NAME']);
"https://" . $_SERVER['SERVER_NAME']));
}
}

View File

@ -209,7 +209,7 @@ class ApiController extends Zend_Controller_Action
$result["station_down"] = true;
}
echo isset($_GET['callback']) ? $_GET['callback'].'('.json_encode($result).')' : json_encode($result);
$this->returnJsonOrJsonp($request, $result);
}
/**
@ -295,15 +295,8 @@ class ApiController extends Zend_Controller_Action
// used by caller to determine if the airtime they are running or widgets in use is out of date.
$result['AIRTIME_API_VERSION'] = AIRTIME_API_VERSION;
header("Content-Type: application/json");
if (version_compare(phpversion(), '5.4.0', '<')) {
$js = json_encode($result);
} else {
$js = json_encode($result, JSON_PRETTY_PRINT);
}
// If a callback is not given, then just provide the raw JSON.
echo isset($_GET['callback']) ? $_GET['callback'].'('.$js.')' : $js;
$this->returnJsonOrJsonp($request, $result);
} else {
header('HTTP/1.0 401 Unauthorized');
print _('You are not allowed to access this resource. ');
@ -368,15 +361,8 @@ class ApiController extends Zend_Controller_Action
// used by caller to determine if the airtime they are running or widgets in use is out of date.
$result["station"]["AIRTIME_API_VERSION"] = AIRTIME_API_VERSION;
header("Content-Type: application/json");
if (version_compare(phpversion(), '5.4.0', '<')) {
$js = json_encode($result);
} else {
$js = json_encode($result, JSON_PRETTY_PRINT);
}
// If a callback is not given, then just provide the raw JSON.
echo isset($_GET['callback']) ? $_GET['callback'].'('.$js.')' : $js;
$this->returnJsonOrJsonp($request, $result);
} else {
header('HTTP/1.0 401 Unauthorized');
print _('You are not allowed to access this resource. ');
@ -443,15 +429,7 @@ class ApiController extends Zend_Controller_Action
//used by caller to determine if the airtime they are running or widgets in use is out of date.
$result['AIRTIME_API_VERSION'] = AIRTIME_API_VERSION;
header("Content-type: text/javascript");
if (version_compare(phpversion(), '5.4.0', '<')) {
$js = json_encode($result);
} else {
$js = json_encode($result, JSON_PRETTY_PRINT);
}
// If a callback is not given, then just provide the raw JSON.
echo isset($_GET['callback']) ? $_GET['callback'].'('.$js.')' : $js;
$this->returnJsonOrJsonp($request, $result);
} else {
header('HTTP/1.0 401 Unauthorized');
print _('You are not allowed to access this resource. ');
@ -534,15 +512,8 @@ class ApiController extends Zend_Controller_Action
// used by caller to determine if the airtime they are running or widgets in use is out of date.
$result['AIRTIME_API_VERSION'] = AIRTIME_API_VERSION;
header("Content-type: text/javascript");
if (version_compare(phpversion(), '5.4.0', '<')) {
$js = json_encode($result);
} else {
$js = json_encode($result, JSON_PRETTY_PRINT);
}
// If a callback is not given, then just provide the raw JSON.
echo isset($_GET['callback']) ? $_GET['callback'].'('.$js.')' : $js;
$this->returnJsonOrJsonp($request, $result);
} else {
header('HTTP/1.0 401 Unauthorized');
print _('You are not allowed to access this resource. ');
@ -1599,4 +1570,21 @@ class ApiController extends Zend_Controller_Action
}
echo("Recalculated $total shows.");
}
private final function returnJsonOrJsonp($request, $result) {
$callback = $request->getParam('callback');
$response = $this->getResponse();
$response->setHeader('Content-Type', 'application/json');
$body = $this->_helper->json->encodeJson($result, false);
if ($callback) {
$response->setHeader('Content-Type', 'application/javascript');
$body = sprintf('%s(%s)', $callback, $body);
}
$response->setBody($body);
// enable cors access from configured URLs
CORSHelper::enableCrossOriginRequests($request, $response);
}
}

View File

@ -24,7 +24,7 @@ class LoginController extends Zend_Controller_Action
$stationLocale = Application_Model_Preference::GetDefaultLocale();
//Enable AJAX requests from www.airtime.pro for the sign-in process.
CORSHelper::enableATProCrossOriginRequests($request, $response);
CORSHelper::enableCrossOriginRequests($request, $response);
Application_Model_Locale::configureLocalization($request->getcookie('airtime_locale', $stationLocale));

View File

@ -46,6 +46,7 @@ class PreferenceController extends Zend_Controller_Action
Application_Model_Preference::SetDefaultFadeIn($values["stationDefaultFadeIn"]);
Application_Model_Preference::SetDefaultFadeOut($values["stationDefaultFadeOut"]);
Application_Model_Preference::SetAllow3rdPartyApi($values["thirdPartyApi"]);
Application_Model_Preference::SetAllowedCorsUrls($values["allowedCorsUrls"]);
Application_Model_Preference::SetDefaultLocale($values["locale"]);
Application_Model_Preference::SetDefaultTimezone($values["timezone"]);
Application_Model_Preference::SetWeekStartDay($values["weekStartDay"]);

View File

@ -118,6 +118,13 @@ class Application_Form_GeneralPreferences extends Zend_Form_SubForm
));
$this->addElement($third_party_api);
$allowedCorsUrlsValue = Application_Model_Preference::GetAllowedCorsUrls();
$allowedCorsUrls = new Zend_Form_Element_Textarea('allowedCorsUrls');
$allowedCorsUrls->setLabel(_('Allowed CORS URLs'));
$allowedCorsUrls->setDescription(_('Remote URLs that are allowed to access this LibreTime instance in a browser. One URL per line.'));
$allowedCorsUrls->setValue($allowedCorsUrlsValue);
$this->addElement($allowedCorsUrls);
$locale = new Zend_Form_Element_Select("locale");
$locale->setLabel(_("Default Language"));
$locale->setMultiOptions(Application_Model_Locale::getLocales());

View File

@ -1645,4 +1645,23 @@ class Application_Model_Preference
public static function setBandwidthLimitUpdateTimer() {
self::setValue("bandwidth_limit_update_timer", microtime(true));
}
/**
* Getter for CORS URLs
*
* @return string
*/
public static function GetAllowedCorsUrls() {
return self::getValue('allowed_cors_urls');
}
/**
* Setter for CORS URLs
*
* @param string $value
* @return void
*/
public static function SetAllowedCorsUrls($value) {
self::setValue('allowed_cors_urls', $value);
}
}

View File

@ -32,6 +32,7 @@
<?php echo $this->element->getElement('stationDefaultCrossfadeDuration')->render() ?>
<?php echo $this->element->getElement('thirdPartyApi')->render() ?>
<?php echo $this->element->getElement('allowedCorsUrls')->render() ?>
<?php echo $this->element->getElement('radioPageLoginButton')->renderViewHelper() ?>
<?php echo $this->element->getElement('radioPageLoginButton')->renderLabel() ?>