Merge branch 'saas' into cc-5709-airtime-analyzer-cloud-storage-saas

Conflicts:
	.gitignore
	airtime_mvc/application/configs/airtime-conf.php
	airtime_mvc/application/configs/classmap-airtime-conf.php
	airtime_mvc/application/models/RabbitMq.php
	airtime_mvc/application/models/Schedule.php
	airtime_mvc/application/models/StoredFile.php
	airtime_mvc/application/models/airtime/map/CcShowInstancesTableMap.php
	airtime_mvc/application/models/airtime/map/CcShowTableMap.php
	airtime_mvc/application/models/airtime/om/BaseCcShow.php
	airtime_mvc/application/models/airtime/om/BaseCcShowInstances.php
	airtime_mvc/application/models/airtime/om/BaseCcShowInstancesPeer.php
	airtime_mvc/application/models/airtime/om/BaseCcShowInstancesQuery.php
	airtime_mvc/application/models/airtime/om/BaseCcShowPeer.php
	airtime_mvc/application/models/airtime/om/BaseCcShowQuery.php
	airtime_mvc/application/modules/rest/Bootstrap.php
	airtime_mvc/application/modules/rest/controllers/MediaController.php
	airtime_mvc/build/sql/schema.sql
	airtime_mvc/public/index.php
This commit is contained in:
drigato 2014-11-03 12:29:58 -05:00
commit 0a45de7fba
163 changed files with 67857 additions and 56085 deletions

10
.gitignore vendored
View File

@ -3,4 +3,12 @@
vendor/*
composer.phar
composer.lock
*~$
*log.*
**/airtime_analyzer.egg-info/*
**/build/*
**/dist/*
*~
/airtime_mvc/tests/test_results.xml
/tests/results.html
/tests/*.jar

View File

@ -18,6 +18,8 @@ require_once "Auth.php";
require_once __DIR__.'/forms/helpers/ValidationTypes.php';
require_once __DIR__.'/controllers/plugins/RabbitMqPlugin.php';
require_once __DIR__.'/controllers/plugins/Maintenance.php';
require_once __DIR__.'/modules/rest/controllers/ShowController.php';
require_once __DIR__.'/modules/rest/controllers/MediaController.php';
require_once (APPLICATION_PATH."/logging/Logging.php");
Logging::setLogPath('/var/log/airtime/zendphp.log');
@ -135,21 +137,26 @@ class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
} else {
$userType = "";
}
$view->headScript()->appendScript("var userType = '$userType';");
if (array_key_exists('REQUEST_URI', $_SERVER)) { //Doesn't exist for unit tests
if (strpos($_SERVER['REQUEST_URI'], $baseUrl.'Dashboard/stream-player') === false
&& strpos($_SERVER['REQUEST_URI'], $baseUrl.'audiopreview/audio-preview') === false
&& strpos($_SERVER['REQUEST_URI'], $baseUrl.'audiopreview/playlist-preview') === false
&& strpos($_SERVER['REQUEST_URI'], $baseUrl.'audiopreview/block-preview') === false) {
if (Application_Model_Preference::GetLiveChatEnabled()) {
$client_id = Application_Model_Preference::GetClientId();
$view->headScript()->appendScript("var livechat_client_id = '$client_id';");
$view->headScript()->appendFile($baseUrl . 'js/airtime/common/livechat.js?'.$CC_CONFIG['airtime_version'], 'text/javascript');
}
}
}
/*
if (isset($CC_CONFIG['demo']) && $CC_CONFIG['demo'] == 1) {
$view->headScript()->appendFile($baseUrl.'js/libs/google-analytics.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
}
if (Application_Model_Preference::GetPlanLevel() != "disabled"
&& !($_SERVER['REQUEST_URI'] == $baseUrl.'Dashboard/stream-player' ||
strncmp($_SERVER['REQUEST_URI'], $baseUrl.'audiopreview/audio-preview', strlen($baseUrl.'audiopreview/audio-preview'))==0)) {
$client_id = Application_Model_Preference::GetClientId();
$view->headScript()->appendScript("var livechat_client_id = '$client_id';");
$view->headScript()->appendFile($baseUrl . 'js/airtime/common/livechat.js?'.$CC_CONFIG['airtime_version'], 'text/javascript');
}
}*/
}
protected function _initViewHelpers()

View File

@ -0,0 +1,27 @@
<?php
class CORSHelper
{
public static function enableATProCrossOriginRequests(&$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,
array("http://www.airtime.pro",
"https://www.airtime.pro",
"https://account.sourcefabric.com",
"http://" . $_SERVER['SERVER_NAME'],
"https://" . $_SERVER['SERVER_NAME']
))
))
{
//Don't allow CORS from other domains to prevent XSS.
throw new Zend_Controller_Action_Exception('Forbidden', 403);
}
}
}

View File

@ -7,13 +7,15 @@ $ccAcl = new Zend_Acl();
$ccAcl->addRole(new Zend_Acl_Role('G'))
->addRole(new Zend_Acl_Role('H'), 'G')
->addRole(new Zend_Acl_Role('P'), 'H')
->addRole(new Zend_Acl_Role('A'), 'P');
->addRole(new Zend_Acl_Role('A'), 'P')
->addRole(new Zend_Acl_Role('S'), 'A');
$ccAcl->add(new Zend_Acl_Resource('library'))
->add(new Zend_Acl_Resource('index'))
->add(new Zend_Acl_Resource('user'))
->add(new Zend_Acl_Resource('error'))
->add(new Zend_Acl_Resource('login'))
->add(new Zend_Acl_Resource('whmcs-login'))
->add(new Zend_Acl_Resource('playlist'))
->add(new Zend_Acl_Resource('plupload'))
->add(new Zend_Acl_Resource('schedule'))
@ -29,11 +31,13 @@ $ccAcl->add(new Zend_Acl_Resource('library'))
->add(new Zend_Acl_Resource('audiopreview'))
->add(new Zend_Acl_Resource('webstream'))
->add(new Zend_Acl_Resource('locale'))
->add(new Zend_Acl_Resource('upgrade'));
->add(new Zend_Acl_Resource('upgrade'))
->add(new Zend_Acl_Resource('billing'));
/** Creating permissions */
$ccAcl->allow('G', 'index')
->allow('G', 'login')
->allow('G', 'whmcs-login')
->allow('G', 'error')
->allow('G', 'user', 'edit-user')
->allow('G', 'showbuilder')
@ -54,7 +58,8 @@ $ccAcl->allow('G', 'index')
->allow('A', 'listenerstat')
->allow('A', 'user')
->allow('A', 'systemstatus')
->allow('A', 'preference');
->allow('A', 'preference')
->allow('S', 'billing');
$aclPlugin = new Zend_Controller_Plugin_Acl($ccAcl);

View File

@ -8,6 +8,7 @@ resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"
resources.frontController.params.displayExceptions = 0
resources.frontController.moduleDirectory = APPLICATION_PATH "/modules"
resources.frontController.plugins.putHandler = "Zend_Controller_Plugin_PutHandler"
resources.modules[] = ""
;load everything in the modules directory including models
resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts/"
resources.modules[] = ""

View File

@ -41,6 +41,7 @@ define('UI_MDATA_VALUE_FORMAT_STREAM' , 'live stream');
//User types
define('UTYPE_HOST' , 'H');
define('UTYPE_ADMIN' , 'A');
define('UTYPE_SUPERADMIN' , 'S');
define('UTYPE_GUEST' , 'G');
define('UTYPE_PROGRAM_MANAGER' , 'P');
@ -63,3 +64,9 @@ define('UI_BLOCK_SESSNAME', 'BLOCK');*/
define('SOUNDCLOUD_NOT_UPLOADED_YET' , -1);
define('SOUNDCLOUD_PROGRESS' , -2);
define('SOUNDCLOUD_ERROR' , -3);
//WHMCS integration
define("WHMCS_API_URL", "https://account.sourcefabric.com/includes/api.php");
define("SUBDOMAIN_WHMCS_CUSTOM_FIELD_NAME", "Choose your domain");

View File

@ -134,6 +134,34 @@ $pages = array(
'resource' => 'dashboard'
)
)
),
array(
'label' => _('Billing'),
'uri' => '#',
'resource' => 'billing',
'pages' => array(
array(
'label' => _('Account Details'),
'module' => 'default',
'controller' => 'billing',
'action' => 'client',
'resource' => 'billing'
),
array(
'label' => _('Account Plans'),
'module' => 'default',
'controller' => 'billing',
'action' => 'upgrade',
'resource' => 'billing'
),
array(
'label' => _('View Invoices'),
'module' => 'default',
'controller' => 'billing',
'action' => 'invoices',
'resource' => 'billing'
)
)
)
);

View File

@ -6,7 +6,7 @@ class ApiController extends Zend_Controller_Action
public function init()
{
$ignoreAuth = array("live-info", "live-info-v2", "week-info",
"station-metadata", "station-logo");
"station-metadata", "station-logo", "show-logo");
$params = $this->getRequest()->getParams();
if (!in_array($params['action'], $ignoreAuth)) {
@ -218,7 +218,7 @@ class ApiController extends Zend_Controller_Action
echo isset($_GET['callback']) ? $_GET['callback'].'('.json_encode($result).')' : json_encode($result);
}
/**
* Retrieve the currently playing show as well as upcoming shows.
* Number of shows returned and the time interval in which to
@ -295,6 +295,8 @@ class ApiController extends Zend_Controller_Action
$result["schedulerTime"] = Application_Common_DateHelper::UTCStringToTimezoneString($result["schedulerTime"], $timezone);
$result["timezone"] = $upcase ? strtoupper($timezone) : $timezone;
$result["timezoneOffset"] = Application_Common_DateHelper::getTimezoneOffset($timezone);
// convert image paths to point to api endpoints
$this->findAndConvertPaths($result);
// 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;
@ -313,7 +315,7 @@ class ApiController extends Zend_Controller_Action
exit;
}
}
/**
* Retrieve the currently playing show as well as upcoming shows.
* Number of shows returned and the time interval in which to
@ -333,18 +335,18 @@ class ApiController extends Zend_Controller_Action
// disable the view and the layout
$this->view->layout()->disableLayout();
$this->_helper->viewRenderer->setNoRender(true);
$request = $this->getRequest();
$utcTimeNow = gmdate("Y-m-d H:i:s");
$utcTimeEnd = ""; // if empty, getNextShows will use interval instead of end of day
// default to the station timezone
$timezone = Application_Model_Preference::GetDefaultTimezone();
$userDefinedTimezone = strtolower($request->getParam('timezone'));
$upcase = false; // only upcase the timezone abbreviations
$this->checkTimezone($userDefinedTimezone, $timezone, $upcase);
$daysToRetrieve = $request->getParam('days');
$showsToRetrieve = $request->getParam('shows');
if ($daysToRetrieve == "" || !is_numeric($daysToRetrieve)) {
@ -353,25 +355,27 @@ class ApiController extends Zend_Controller_Action
if ($showsToRetrieve == "" || !is_numeric($showsToRetrieve)) {
$showsToRetrieve = "5";
}
// set the end time to the day's start n days from now.
// days=1 will return shows until the end of the current day,
// days=2 will return shows until the end of tomorrow, etc.
$end = Application_Common_DateHelper::getEndDateTime($timezone, $daysToRetrieve);
$end->setTimezone(new DateTimeZone("UTC"));
$utcTimeEnd = $end->format("Y-m-d H:i:s");
$result = Application_Model_Schedule::GetPlayOrderRange($utcTimeEnd, $showsToRetrieve);
// XSS exploit prevention
$this->convertSpecialChars($result, array("name", "url"));
// apply user-defined timezone, or default to station
$this->applyLiveTimezoneAdjustments($result, $timezone, $upcase);
// convert image paths to point to api endpoints
$this->findAndConvertPaths($result);
// 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 {
@ -387,15 +391,15 @@ class ApiController extends Zend_Controller_Action
}
/**
* Check that the value for the timezone the user gave is valid.
* If it is, override the default (station) timezone.
* Check that the value for the timezone the user gave is valid.
* If it is, override the default (station) timezone.
* If it's an abbreviation (pst, edt) we upcase the output.
*
*
* @param string $userDefinedTimezone the requested timezone value
* @param string $timezone the default timezone
* @param boolean $upcase whether the timezone output should be upcased
*/
private function checkTimezone($userDefinedTimezone, &$timezone, &$upcase)
private function checkTimezone($userDefinedTimezone, &$timezone, &$upcase)
{
$delimiter = "/";
// if the user passes in a timezone in standard form ("Continent/City")
@ -413,26 +417,26 @@ class ApiController extends Zend_Controller_Action
}
/**
* If the user passed in a timezone parameter, adjust timezone-dependent
* If the user passed in a timezone parameter, adjust timezone-dependent
* variables in the result to reflect the given timezone.
*
*
* @param object $result reference to the object to send back to the user
* @param string $timezone the user's timezone parameter value
* @param boolean $upcase whether the timezone output should be upcased
*/
private function applyLiveTimezoneAdjustments(&$result, $timezone, $upcase)
private function applyLiveTimezoneAdjustments(&$result, $timezone, $upcase)
{
Application_Common_DateHelper::convertTimestampsToTimezone(
$result,
array("starts", "ends", "start_timestamp","end_timestamp"),
$timezone
$result,
array("starts", "ends", "start_timestamp","end_timestamp"),
$timezone
);
//Convert the UTC scheduler time ("now") to the user-defined timezone.
$result["station"]["schedulerTime"] = Application_Common_DateHelper::UTCStringToTimezoneString($result["station"]["schedulerTime"], $timezone);
$result["station"]["timezone"] = $upcase ? strtoupper($timezone) : $timezone;
//Convert the UTC scheduler time ("now") to the user-defined timezone.
$result["station"]["schedulerTime"] = Application_Common_DateHelper::UTCStringToTimezoneString($result["station"]["schedulerTime"], $timezone);
$result["station"]["timezone"] = $upcase ? strtoupper($timezone) : $timezone;
}
public function weekInfoAction()
{
if (Application_Model_Preference::GetAllow3rdPartyApi()) {
@ -461,7 +465,6 @@ class ApiController extends Zend_Controller_Action
$weekStartDateTime->setTimezone($utcTimezone);
$utcDayStart = $weekStartDateTime->format("Y-m-d H:i:s");
for ($i = 0; $i < 14; $i++) {
//have to be in station timezone when adding 1 day for daylight savings.
$weekStartDateTime->setTimezone(new DateTimeZone($timezone));
$weekStartDateTime->add(new DateInterval('P1D'));
@ -485,12 +488,132 @@ class ApiController extends Zend_Controller_Action
// XSS exploit prevention
$this->convertSpecialChars($result, array("name", "url"));
// convert image paths to point to api endpoints
$this->findAndConvertPaths($result);
//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");
$js = json_encode($result, JSON_PRETTY_PRINT);
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;
} else {
header('HTTP/1.0 401 Unauthorized');
print _('You are not allowed to access this resource. ');
exit;
}
}
/**
* Go through a given array and sanitize any potentially exploitable fields
* by passing them through htmlspecialchars
*
* @param unknown $arr the array to sanitize
* @param unknown $keys indexes of values to be sanitized
*/
private function convertSpecialChars(&$arr, $keys)
{
foreach ($arr as &$a) {
if (is_array($a)) {
foreach ($keys as &$key) {
if (array_key_exists($key, $a)) {
$a[$key] = htmlspecialchars($a[$key]);
}
}
$this->convertSpecialChars($a, $keys);
}
}
}
/**
* Recursively find image_path keys in the various $result subarrays,
* and convert them to point to the show-logo endpoint
*
* @param unknown $arr the array to search
*/
private function findAndConvertPaths(&$arr)
{
$CC_CONFIG = Config::getConfig();
$baseDir = Application_Common_OsPath::formatDirectoryWithDirectorySeparators($CC_CONFIG['baseDir']);
foreach ($arr as &$a) {
if (is_array($a)) {
if (array_key_exists("image_path", $a)) {
$a["image_path"] = $a["image_path"] && $a["image_path"] !== '' ?
"http://".$_SERVER['HTTP_HOST'].$baseDir."api/show-logo?id=".$a["id"] : '';
} else {
$this->findAndConvertPaths($a);
}
}
}
}
/**
* API endpoint to display the show logo
*/
public function showLogoAction()
{
if (Application_Model_Preference::GetAllow3rdPartyApi()) {
$request = $this->getRequest();
$showId = $request->getParam('id');
// if no id is passed, just die - redirects to a 404
if (!$showId || $showId === '') {
return;
}
$show = CcShowQuery::create()->findPk($showId);
// disable the view and the layout
$this->view->layout()->disableLayout();
$this->_helper->viewRenderer->setNoRender(true);
$path = $show->getDbImagePath();
$mime_type = mime_content_type($path);
header("Content-type: " . $mime_type);
$this->smartReadFile($path, $mime_type);
} else {
header('HTTP/1.0 401 Unauthorized');
print _('You are not allowed to access this resource. ');
exit;
}
}
/**
* API endpoint to provide station metadata
*/
public function stationMetadataAction()
{
if (Application_Model_Preference::GetAllow3rdPartyApi()) {
// disable the view and the layout
$this->view->layout()->disableLayout();
$this->_helper->viewRenderer->setNoRender(true);
$CC_CONFIG = Config::getConfig();
$baseDir = Application_Common_OsPath::formatDirectoryWithDirectorySeparators($CC_CONFIG['baseDir']);
$path = 'http://'.$_SERVER['HTTP_HOST'].$baseDir."api/station-logo";
$result["name"] = Application_Model_Preference::GetStationName();
$result["logo"] = $path;
$result["description"] = Application_Model_Preference::GetStationDescription();
$result["timezone"] = Application_Model_Preference::GetDefaultTimezone();
$result["locale"] = Application_Model_Preference::GetDefaultLocale();
// 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;
} else {
@ -500,6 +623,39 @@ class ApiController extends Zend_Controller_Action
}
}
/**
* API endpoint to display the current station logo
*/
public function stationLogoAction()
{
if (Application_Model_Preference::GetAllow3rdPartyApi()) {
// disable the view and the layout
$this->view->layout()->disableLayout();
$this->_helper->viewRenderer->setNoRender(true);
$logo = Application_Model_Preference::GetStationLogo();
// if there's no logo, just die - redirects to a 404
if (!$logo || $logo === '') {
return;
}
// we're passing this as an image instead of using it in a data uri, so decode it
$blob = base64_decode($logo);
// use finfo to get the mimetype from the decoded blob
$f = finfo_open();
$mime_type = finfo_buffer($f, $blob, FILEINFO_MIME_TYPE);
finfo_close($f);
header("Content-type: " . $mime_type);
echo $blob;
} else {
header('HTTP/1.0 401 Unauthorized');
print _('You are not allowed to access this resource. ');
exit;
}
}
public function scheduleAction()
{
$this->view->layout()->disableLayout();
@ -515,6 +671,13 @@ class ApiController extends Zend_Controller_Action
public function notifyMediaItemStartPlayAction()
{
$media_id = $this->_getParam("media_id");
// We send a fake media id when playing on-demand ads;
// in this case, simply return
if ($media_id === '0' || $media_id === '-1') {
return;
}
Logging::debug("Received notification of new media item start: $media_id");
Application_Model_Schedule::UpdateMediaPlayedStatus($media_id);
@ -549,94 +712,6 @@ class ApiController extends Zend_Controller_Action
$this->_helper->json->sendJson(array("status"=>1, "message"=>""));
}
/**
* Go through a given array and sanitize any potentially exploitable fields
* by passing them through htmlspecialchars
*
* @param unknown $arr the array to sanitize
* @param unknown $keys indexes of values to be sanitized
*/
private function convertSpecialChars(&$arr, $keys)
{
foreach ($arr as &$a) {
if (is_array($a)) {
foreach ($keys as &$key) {
if (array_key_exists($key, $a)) {
$a[$key] = htmlspecialchars($a[$key]);
}
}
$this->convertSpecialChars($a, $keys);
}
}
}
/**
* API endpoint to provide station metadata
*/
public function stationMetadataAction()
{
if (Application_Model_Preference::GetAllow3rdPartyApi()) {
// disable the view and the layout
$this->view->layout()->disableLayout();
$this->_helper->viewRenderer->setNoRender(true);
$CC_CONFIG = Config::getConfig();
$baseDir = Application_Common_OsPath::formatDirectoryWithDirectorySeparators($CC_CONFIG['baseDir']);
$path = 'http://'.$_SERVER['HTTP_HOST'].$baseDir."api/station-logo";
$result["name"] = Application_Model_Preference::GetStationName();
$result["logo"] = $path;
$result["description"] = Application_Model_Preference::GetStationDescription();
$result["timezone"] = Application_Model_Preference::GetDefaultTimezone();
$result["locale"] = Application_Model_Preference::GetDefaultLocale();
// 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");
$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;
} else {
header('HTTP/1.0 401 Unauthorized');
print _('You are not allowed to access this resource. ');
exit;
}
}
/**
* API endpoint to display the current station logo
*/
public function stationLogoAction()
{
if (Application_Model_Preference::GetAllow3rdPartyApi()) {
// disable the view and the layout
$this->view->layout()->disableLayout();
$this->_helper->viewRenderer->setNoRender(true);
$logo = Application_Model_Preference::GetStationLogo();
// if there's no logo, just die - redirects to a 404
if (!$logo || $logo === '') {
return;
}
// we're passing this as an image instead of using it in a data uri, so decode it
$blob = base64_decode($logo);
// use finfo to get the mimetype from the decoded blob
$f = finfo_open();
$mime_type = finfo_buffer($f, $blob, FILEINFO_MIME_TYPE);
finfo_close($f);
header("Content-type: " . $mime_type);
echo $blob;
} else {
header('HTTP/1.0 401 Unauthorized');
print _('You are not allowed to access this resource. ');
exit;
}
}
public function recordedShowsAction()
{
$utcTimezone = new DateTimeZone("UTC");
@ -966,6 +1041,28 @@ class ApiController extends Zend_Controller_Action
Logging::info("Registered Component: ".$component."@".$remoteAddr);
Application_Model_ServiceRegister::Register($component, $remoteAddr);
//send ip, subdomain
if ($component == "pypo"){
$split = explode('.', $_SERVER['SERVER_NAME']);
$subdomain = array();
foreach ($split as $value) {
if ($value == 'airtime') {
break;
} else {
$subdomain[] = $value;
}
}
if (count($subdomain) > 0){
$subDomain = implode('.',$subdomain);
$md = array();
$md["sub_domain"] = $subDomain;
$md["pypo_ip"] = $remoteAddr;
Application_Model_RabbitMq::SendMessageToHaproxyConfigDaemon($md);
}
}
}
public function updateLiquidsoapStatusAction()
@ -1123,8 +1220,8 @@ class ApiController extends Zend_Controller_Action
//check against show dj auth
$showInfo = Application_Model_Show::getCurrentShow();
// there is current playing show
if (isset($showInfo[0]['id'])) {
$current_show_id = $showInfo[0]['id'];
if (isset($showInfo['id'])) {
$current_show_id = $showInfo['id'];
$CcShow = CcShowQuery::create()->findPK($current_show_id);
// get custom pass info from the show

View File

@ -0,0 +1,601 @@
<?php
define('VAT_RATE', 19.00);
class BillingController extends Zend_Controller_Action {
public function init()
{
//Two of the actions in this controller return JSON because they're used for AJAX:
$ajaxContext = $this->_helper->getHelper('AjaxContext');
$ajaxContext->addActionContext('vat-validator', 'json')
->addActionContext('is-country-in-eu', 'json')
->initContext();
}
public function indexAction()
{
$this->_redirect('billing/upgrade');
}
public function upgradeAction()
{
$CC_CONFIG = Config::getConfig();
$baseUrl = Application_Common_OsPath::getBaseDir();
$this->view->headLink()->appendStylesheet($baseUrl.'css/billing.css?'.$CC_CONFIG['airtime_version']);
BillingController::ensureClientIdIsValid();
$request = $this->getRequest();
$form = new Application_Form_BillingUpgradeDowngrade();
if ($request->isPost()) {
$formData = $request->getPost();
if ($form->isValid($formData)) {
$credentials = self::getAPICredentials();
//Check if VAT should be applied or not to this invoice.
if (in_array("7", $formData["customfields"])) {
$apply_vat = BillingController::checkIfVatShouldBeApplied($formData["customfields"]["7"], $formData["country"]);
} else {
$apply_vat = false;
}
$placeAnUpgradeOrder = true;
$currentPlanProduct = BillingController::getClientCurrentAirtimeProduct();
$currentPlanProductId = $currentPlanProduct["pid"];
$currentPlanProductBillingCycle = strtolower($currentPlanProduct["billingcycle"]);
//If there's been no change in the plan or the billing cycle, we should not
//place an upgrade order. WHMCS doesn't allow this in its web interface,
//and it freaks out and does the wrong thing if we do it via the API
//so we have to do avoid that.
if (($currentPlanProductId == $formData["newproductid"]) &&
($currentPlanProductBillingCycle == $formData["newproductbillingcycle"]))
{
$placeAnUpgradeOrder = false;
}
$postfields = array();
$postfields["username"] = $credentials["username"];
$postfields["password"] = md5($credentials["password"]);
$postfields["action"] = "upgradeproduct";
$postfields["clientid"] = Application_Model_Preference::GetClientId();
$postfields["serviceid"] = self::getClientInstanceId();
$postfields["type"] = "product";
$postfields["newproductid"] = $formData["newproductid"];
$postfields["newproductbillingcycle"] = $formData["newproductbillingcycle"];
$postfields["paymentmethod"] = $formData["paymentmethod"];
$postfields["responsetype"] = "json";
$upgrade_query_string = "";
foreach ($postfields AS $k=>$v) $upgrade_query_string .= "$k=".urlencode($v)."&";
//update client info
$clientfields = array();
$clientfields["username"] = $credentials["username"];
$clientfields["password"] = md5($credentials["password"]);
$clientfields["action"] = "updateclient";
$clientfields["clientid"] = Application_Model_Preference::GetClientId();
$clientfields["customfields"] = base64_encode(serialize($formData["customfields"]));
unset($formData["customfields"]);
$clientfields["responsetype"] = "json";
unset($formData["newproductid"]);
unset($formData["newproductbillingcycle"]);
unset($formData["paymentmethod"]);
unset($formData["action"]);
$clientfields = array_merge($clientfields, $formData);
unset($clientfields["password2verify"]);
unset($clientfields["submit"]);
$client_query_string = "";
foreach ($clientfields AS $k=>$v) $client_query_string .= "$k=".urlencode($v)."&";
//Update the client details in WHMCS first
$result = $this->makeRequest($credentials["url"], $client_query_string);
Logging::info($result);
if ($result["result"] == "error") {
$this->setErrorMessage();
$this->view->form = $form;
return;
}
//If there were no changes to the plan or billing cycle, we just redirect you to the
//invoices screen and show a message.
if (!$placeAnUpgradeOrder)
{
$this->_redirect('billing/invoices?planupdated');
return;
}
//Then place an upgrade order in WHMCS
$result = $this->makeRequest($credentials["url"], $upgrade_query_string);
if ($result["result"] == "error") {
Logging::info($_SERVER['HTTP_HOST']." - Account upgrade failed. - ".$result["message"]);
$this->setErrorMessage();
$this->view->form = $form;
} else {
Logging::info($_SERVER['HTTP_HOST']. "Account plan upgrade request:");
Logging::info($result);
// Disable the view and the layout here, squashes an error.
$this->view->layout()->disableLayout();
$this->_helper->viewRenderer->setNoRender(true);
if ($apply_vat) {
$this->addVatToInvoice($result["invoiceid"]);
}
self::viewInvoice($result["invoiceid"]);
}
} else {
$this->view->form = $form;
}
} else {
$this->view->form = $form;
}
}
public function isCountryInEuAction()
{
// Disable the view and the layout
$this->view->layout()->disableLayout();
$this->_helper->viewRenderer->setNoRender(true);
$request = $this->getRequest();
if (!$request->isPost()) {
throw new Exception("Must POST data to isCountryInEuAction.");
}
$formData = $request->getPost();
//Set the return JSON value
$this->_helper->json(array("result"=>BillingController::isCountryInEU($formData["country"])));
}
public function vatValidatorAction()
{
// Disable the view and the layout
$this->view->layout()->disableLayout();
$this->_helper->viewRenderer->setNoRender(true);
$request = $this->getRequest();
if (!$request->isPost()) {
throw new Exception("Must POST data to vatValidatorAction.");
}
$formData = $request->getPost();
$vatNumber = trim($formData["vatnumber"]);
if (empty($vatNumber)) {
$this->_helper->json(array("result"=>false));
}
//Set the return JSON value
$this->_helper->json(array("result"=>BillingController::checkIfVatShouldBeApplied($vatNumber, $formData["country"])));
}
/**
* @return True if VAT should be applied to the order, false otherwise.
*/
private static function checkIfVatShouldBeApplied($vatNumber, $countryCode)
{
if ($countryCode === 'UK') {
$countryCode = 'GB'; //VIES database has it as GB
}
//We don't charge you VAT if you're not in the EU
if (!BillingController::isCountryInEU($countryCode))
{
return false;
}
//So by here, we know you're in the EU.
//No VAT number? Then we charge you VAT.
if (empty($vatNumber)) {
return true;
}
//Check if VAT number is valid
return BillingController::validateVATNumber($vatNumber, $countryCode);
}
private static function isCountryInEU($countryCode)
{
$euCountryCodes = array('BE', 'BG', 'CZ', 'DK', 'DE', 'EE', 'IE', 'EL', 'ES', 'FR',
'HR', 'IT', 'CY', 'LV', 'LT', 'LU', 'HU', 'MT', 'NL', 'AT',
'PL', 'PT', 'RO', 'SI', 'SK', 'FI', 'SE', 'UK', 'GB');
if (!in_array($countryCode, $euCountryCodes)) {
return false;
}
return true;
}
/**
* Check if an EU VAT number is valid, using the EU VIES validation web API.
*
* @param string $vatNumber - A VAT identifier (number), with or without the two letter country code at the
* start (either one works) .
* @param string $countryCode - A two letter country code
* @return boolean true if the VAT number is valid, false otherwise.
*/
private static function validateVATNumber($vatNumber, $countryCode)
{
$vatNumber = str_replace(array(' ', '.', '-', ',', ', '), '', trim($vatNumber));
//If the first two letters are a country code, use that as the country code and remove those letters.
$firstTwoCharacters = substr($vatNumber, 0, 2);
if (preg_match("/[a-zA-Z][a-zA-Z]/", $firstTwoCharacters) === 1) {
$countryCode = strtoupper($firstTwoCharacters); //The country code from the VAT number overrides your country.
$vatNumber = substr($vatNumber, 2);
}
$client = new SoapClient("http://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl");
if($client){
$params = array('countryCode' => $countryCode, 'vatNumber' => $vatNumber);
try{
$r = $client->checkVat($params);
if($r->valid == true){
// VAT-ID is valid
return true;
} else {
// VAT-ID is NOT valid
return false;
}
} catch(SoapFault $e) {
Logging::error('VIES EU VAT validation error: '.$e->faultstring);
if ($e->faultstring == "INVALID_INPUT") {
return false;
}
//If there was another error with the VAT validation service, we allow
//the VAT number to pass. (eg. SERVER_BUSY, MS_UNAVAILABLE, TIMEOUT, SERVICE_UNAVAILABLE)
return true;
}
} else {
// Connection to host not possible, europe.eu down?
Logging::error('VIES EU VAT validation error: Host unreachable');
//If there was an error with the VAT validation service, we allow
//the VAT number to pass.
return true;
}
return false;
}
private function addVatToInvoice($invoice_id)
{
$credentials = self::getAPICredentials();
//First we need to get the invoice details: sub total, and total
//so we can calcuate the amount of VAT to add
$invoicefields = array();
$invoicefields["username"] = $credentials["username"];
$invoicefields["password"] = md5($credentials["password"]);
$invoicefields["action"] = "getinvoice";
$invoicefields["invoiceid"] = $invoice_id;
$invoicefields["responsetype"] = "json";
$invoice_query_string = "";
foreach ($invoicefields as $k=>$v) $invoice_query_string .= "$k=".urlencode($v)."&";
//TODO: error checking
$result = $this->makeRequest($credentials["url"], $invoice_query_string);
$vat_amount = $result["subtotal"] * (VAT_RATE/100);
$invoice_total = $result["total"] + $vat_amount;
//Second, update the invoice with the VAT amount and updated total
$postfields = array();
$postfields["username"] = $credentials["username"];
$postfields["password"] = md5($credentials["password"]);
$postfields["action"] = "updateinvoice";
$postfields["invoiceid"] = $invoice_id;
$postfields["tax"] = "$vat_amount";
$postfields["taxrate"] = strval(VAT_RATE);
$postfields["total"] = "$invoice_total";
$postfields["responsetype"] = "json";
$query_string = "";
foreach ($postfields as $k=>$v) $query_string .= "$k=".urlencode($v)."&";
//TODO: error checking
$result = $this->makeRequest($credentials["url"], $query_string);
}
private function setErrorMessage($msg=null)
{
if (!is_null($msg)) {
$this->view->errorMessage = $msg;
} else {
$this->view->errorMessage = "An error occurred and we could not update your account. Please contact support for help.";
}
}
private function setSuccessMessage($msg=null)
{
if (!is_null($msg)) {
$this->view->successMessage = $msg;
} else {
$this->view->successMessage = "Your account has been updated.";
}
}
private static function getAPICredentials()
{
return array(
"username" => $_SERVER["WHMCS_USERNAME"],
"password" => $_SERVER["WHMCS_PASSWORD"],
"url" => "https://account.sourcefabric.com/includes/api.php?accesskey=".$_SERVER["WHMCS_ACCESS_KEY"],
);
}
private static function viewInvoice($invoice_id)
{
$whmcsurl = "https://account.sourcefabric.com/dologin.php";
$autoauthkey = $_SERVER["WHMCS_AUTOAUTH_KEY"];
$timestamp = time(); //whmcs timezone?
$client = self::getClientDetails();
$email = $client["email"];
$hash = sha1($email.$timestamp.$autoauthkey);
$goto = "viewinvoice.php?id=".$invoice_id;
header("Location: ".$whmcsurl."?email=$email&timestamp=$timestamp&hash=$hash&goto=$goto");
}
public function clientAction()
{
$CC_CONFIG = Config::getConfig();
$baseUrl = Application_Common_OsPath::getBaseDir();
$this->view->headLink()->appendStylesheet($baseUrl.'css/billing.css?'.$CC_CONFIG['airtime_version']);
$request = $this->getRequest();
$form = new Application_Form_BillingClient();
BillingController::ensureClientIdIsValid();
if ($request->isPost()) {
$formData = $request->getPost();
if ($form->isValid($formData)) {
$credentials = self::getAPICredentials();
$postfields = array();
$postfields["username"] = $credentials["username"];
$postfields["password"] = md5($credentials["password"]);
$postfields["action"] = "updateclient";
$postfields["customfields"] = base64_encode(serialize($formData["customfields"]));
unset($formData["customfields"]);
$postfields["clientid"] = Application_Model_Preference::GetClientId();
$postfields["responsetype"] = "json";
$postfields = array_merge($postfields, $formData);
unset($postfields["password2verify"]);
unset($postfields["submit"]);
$query_string = "";
foreach ($postfields AS $k=>$v) $query_string .= "$k=".urlencode($v)."&";
$result = $this->makeRequest($credentials["url"], $query_string);
if ($result["result"] == "error") {
$this->setErrorMessage();
} else {
$form = new Application_Form_BillingClient();
$this->setSuccessMessage();
}
$this->view->form = $form;
} else {
$this->view->form = $form;
}
} else {
$this->view->form = $form;
}
}
public function invoicesAction()
{
$CC_CONFIG = Config::getConfig();
$baseUrl = Application_Common_OsPath::getBaseDir();
$this->view->headLink()->appendStylesheet($baseUrl.'css/billing.css?'.$CC_CONFIG['airtime_version']);
BillingController::ensureClientIdIsValid();
$credentials = self::getAPICredentials();
$postfields = array();
$postfields["username"] = $credentials["username"];
$postfields["password"] = md5($credentials["password"]);
$postfields["action"] = "getinvoices";
$postfields["responsetype"] = "json";
$postfields["userid"] = Application_Model_Preference::GetClientId();
$query_string = "";
foreach ($postfields AS $k=>$v) $query_string .= "$k=".urlencode($v)."&";
$result = self::makeRequest($credentials["url"], $query_string);
if ($result["invoices"]) {
$this->view->invoices = $result["invoices"]["invoice"];;
} else {
$this->view->invoices = array();
}
}
public function invoiceAction()
{
BillingController::ensureClientIdIsValid();
$request = $this->getRequest();
$invoice_id = $request->getParam('invoiceid');
self::viewInvoice($invoice_id);
}
/** Get the Airtime instance ID of the instance the customer is currently viewing. */
private static function getClientInstanceId()
{
$currentProduct = BillingController::getClientCurrentAirtimeProduct();
return $currentProduct["id"];
}
public static function getProducts()
{
//Making this static to cache the products during a single HTTP request.
//This saves us roundtrips to WHMCS if getProducts() is called multiple times.
static $result = array();
if (!empty($result))
{
return $result["products"]["product"];
}
$credentials = self::getAPICredentials();
$postfields = array();
$postfields["username"] = $credentials["username"];
$postfields["password"] = md5($credentials["password"]);
$postfields["action"] = "getproducts";
$postfields["responsetype"] = "json";
//gid is the Airtime product group id on whmcs
$postfields["gid"] = "15";
$query_string = "";
foreach ($postfields AS $k=>$v) $query_string .= "$k=".urlencode($v)."&";
$result = self::makeRequest($credentials["url"], $query_string);
//Logging::info($result["products"]["product"]);
$products = $result["products"]["product"];
//Blacklist all free plans
foreach ($products as $k => $p) {
Logging::info($p);
if ($p["paytype"] === "free")
{
unset($products[$k]);
}
}
return $products;
}
public static function getProductPricesAndTypes()
{
$products = BillingController::getProducts();
foreach ($products as $k => $p) {
$productPrices[$p["name"]] = array(
"monthly" => $p["pricing"]["USD"]["monthly"],
"annually" => $p["pricing"]["USD"]["annually"]
);
$productTypes[$p["pid"]] = $p["name"] . " ($" . $productPrices[$p['name']]['monthly'] . "/mo)";
}
return array($productPrices, $productTypes);
}
/** Get the plan (or product in WHMCS lingo) that the customer is currently on.
* @return An associative array containing the fields for the product
* */
public static function getClientCurrentAirtimeProduct()
{
static $airtimeProduct = null;
//Ghetto caching to avoid multiple round trips to WHMCS
if ($airtimeProduct) {
return $airtimeProduct;
}
$credentials = self::getAPICredentials();
$postfields = array();
$postfields["username"] = $credentials["username"];
$postfields["password"] = md5($credentials["password"]);
$postfields["action"] = "getclientsproducts";
$postfields["responsetype"] = "json";
$postfields["clientid"] = Application_Model_Preference::GetClientId();
$query_string = "";
foreach ($postfields AS $k=>$v) $query_string .= "$k=".urlencode($v)."&";
$result = self::makeRequest($credentials["url"], $query_string);
//XXX: Debugging / local testing
if ($_SERVER['SERVER_NAME'] == "airtime.localhost") {
$_SERVER['SERVER_NAME'] = "bananas.airtime.pro";
}
//This code must run on airtime.pro for it to work... it's trying to match
//the server's hostname with the client subdomain. Once it finds a match
//between the product and the server's hostname/subdomain, then it
//returns the ID of that product (aka. the service ID of an Airtime instance)
foreach ($result["products"]["product"] as $product)
{
if (strpos($product["groupname"], "Airtime") === FALSE)
{
//Ignore non-Airtime products
continue;
}
else
{
if ($product["status"] === "Active") {
$airtimeProduct = $product;
$subdomain = '';
foreach ($airtimeProduct['customfields']['customfield'] as $customField) {
if ($customField['name'] === SUBDOMAIN_WHMCS_CUSTOM_FIELD_NAME) {
$subdomain = $customField['value'];
if (($subdomain . ".airtime.pro") === $_SERVER['SERVER_NAME']) {
return $airtimeProduct;
}
}
}
}
}
}
throw new Exception("Unable to match subdomain to a service ID");
}
public static function getClientDetails()
{
try {
$credentials = self::getAPICredentials();
$postfields = array();
$postfields["username"] = $credentials["username"];
$postfields["password"] = md5($credentials["password"]);
$postfields["action"] = "getclientsdetails";
$postfields["stats"] = true;
$postfields["clientid"] = Application_Model_Preference::GetClientId();
$postfields["responsetype"] = "json";
$query_string = "";
foreach ($postfields AS $k=>$v) $query_string .= "$k=".urlencode($v)."&";
$arr = self::makeRequest($credentials["url"], $query_string);
return $arr["client"];
} catch (Exception $e) {
Logging::info($e->getMessage());
}
}
private static function makeRequest($url, $query_string) {
try {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 5); //Aggressive 5 second timeout
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $query_string);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
$jsondata = curl_exec($ch);
if (curl_error($ch)) {
//die("Connection Error: ".curl_errno($ch).' - '.curl_error($ch));
throw new Exception("WHMCS server down or invalid request.");
}
curl_close($ch);
return json_decode($jsondata, true);
} catch (Exception $e) {
Logging::info($e->getMessage());
}
}
private static function ensureClientIdIsValid()
{
if (Application_Model_Preference::GetClientId() == null)
{
throw new Exception("Invalid client ID: " . Application_Model_Preference::GetClientId());
}
}
}

View File

@ -83,7 +83,7 @@ class LibraryController extends Zend_Controller_Action
$obj = new $objInfo['className']($obj_sess->id);
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
$user = new Application_Model_User($userInfo->id);
$isAdminOrPM = $user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));
$isAdminOrPM = $user->isUserType(array(UTYPE_SUPERADMIN, UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));
if ($isAdminOrPM || $obj->getCreatorId() == $userInfo->id) {
$this->view->obj = $obj;
@ -186,7 +186,7 @@ class LibraryController extends Zend_Controller_Action
//Open a jPlayer window and play the audio clip.
$menu["play"] = array("name"=> _("Preview"), "icon" => "play", "disabled" => false);
$isAdminOrPM = $user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));
$isAdminOrPM = $user->isUserType(array(UTYPE_SUPERADMIN, UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));
$obj_sess = new Zend_Session_Namespace(UI_PLAYLISTCONTROLLER_OBJ_SESSNAME);
@ -305,7 +305,7 @@ class LibraryController extends Zend_Controller_Action
$mediaItems = $this->_getParam('media', null);
$user = Application_Model_User::getCurrentUser();
//$isAdminOrPM = $user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));
//$isAdminOrPM = $user->isUserType(array(UTYPE_SUPERADMIN, UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));
$files = array();
$playlists = array();
@ -421,7 +421,7 @@ class LibraryController extends Zend_Controller_Action
public function editFileMdAction()
{
$user = Application_Model_User::getCurrentUser();
$isAdminOrPM = $user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));
$isAdminOrPM = $user->isUserType(array(UTYPE_SUPERADMIN, UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));
$request = $this->getRequest();

View File

@ -15,7 +15,8 @@ class LocaleController extends Zend_Controller_Action
$locale = Application_Model_Preference::GetLocale();
echo "var datatables_dict =" .
file_get_contents(Application_Common_OsPath::join(
$_SERVER["DOCUMENT_ROOT"],
//$_SERVER["DOCUMENT_ROOT"],
dirname(__FILE__) . "/../../public/", // Fixing this... -- Albert
"js/datatables/i18n/",
$locale.".txt")
);

View File

@ -1,5 +1,8 @@
<?php
require_once('WhmcsLoginController.php');
require_once('CORSHelper.php');
class LoginController extends Zend_Controller_Action
{
@ -12,7 +15,11 @@ class LoginController extends Zend_Controller_Action
$CC_CONFIG = Config::getConfig();
$request = $this->getRequest();
$response = $this->getResponse();
//Enable AJAX requests from www.airtime.pro for the sign-in process.
CORSHelper::enableATProCrossOriginRequests($request, $response);
Application_Model_Locale::configureLocalization($request->getcookie('airtime_locale', 'en_CA'));
$auth = Zend_Auth::getInstance();
@ -45,40 +52,53 @@ class LoginController extends Zend_Controller_Action
$username = $form->getValue('username');
$password = $form->getValue('password');
$locale = $form->getValue('locale');
if (Application_Model_Subjects::getLoginAttempts($username) >= 3 && $form->getElement('captcha') == NULL) {
$form->addRecaptcha();
} else {
$authAdapter = Application_Model_Auth::getAuthAdapter();
//pass to the adapter the submitted username and password
$authAdapter->setIdentity($username)
->setCredential($password);
$authAdapter = Application_Model_Auth::getAuthAdapter();
//pass to the adapter the submitted username and password
$authAdapter->setIdentity($username)
->setCredential($password);
$result = $auth->authenticate($authAdapter);
if ($result->isValid()) {
Zend_Session::regenerateId();
//all info about this user from the login table omit only the password
$userInfo = $authAdapter->getResultRowObject(null, 'password');
//the default storage is a session with namespace Zend_Auth
$authStorage = $auth->getStorage();
$authStorage->write($userInfo);
Application_Model_LoginAttempts::resetAttempts($_SERVER['REMOTE_ADDR']);
Application_Model_Subjects::resetLoginAttempts($username);
//set the user locale in case user changed it in when logging in
Application_Model_Preference::SetUserLocale($locale);
$this->_redirect('Showbuilder');
} else {
$email = $form->getValue('username');
$authAdapter = new WHMCS_Auth_Adapter("admin", $email, $password);
$auth = Zend_Auth::getInstance();
$result = $auth->authenticate($authAdapter);
if ($result->isValid()) {
// Regenerate session id on login to prevent session fixation.
Zend_Session::regenerateId();
//all info about this user from the login table omit only the password
$userInfo = $authAdapter->getResultRowObject(null, 'password');
//the default storage is a session with namespace Zend_Auth
$authStorage = $auth->getStorage();
$authStorage->write($userInfo);
Application_Model_LoginAttempts::resetAttempts($_SERVER['REMOTE_ADDR']);
Application_Model_Subjects::resetLoginAttempts($username);
//set the user locale in case user changed it in when logging in
Application_Model_Preference::SetUserLocale($locale);
$this->_redirect('Showbuilder');
} else {
}
else {
$message = _("Wrong username or password provided. Please try again.");
Application_Model_Subjects::increaseLoginAttempts($username);
Application_Model_LoginAttempts::increaseAttempts($_SERVER['REMOTE_ADDR']);
$form = new Application_Form_Login();
$form = new Application_Form_Login();
$error = true;
//Only show the captcha if you get your login wrong 4 times in a row.
if (Application_Model_Subjects::getLoginAttempts($username) > 3)
{
$form->addRecaptcha();
}
}
}
}

View File

@ -23,9 +23,7 @@ class PreferenceController extends Zend_Controller_Action
{
$CC_CONFIG = Config::getConfig();
$request = $this->getRequest();
$isSaas = Application_Model_Preference::GetPlanLevel() == 'disabled'?false:true;
$baseUrl = Application_Common_OsPath::getBaseDir();
$this->view->headScript()->appendFile($baseUrl.'js/airtime/preferences/preferences.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
@ -52,16 +50,6 @@ class PreferenceController extends Zend_Controller_Action
Application_Model_Preference::SetDefaultTimezone($values["timezone"]);
Application_Model_Preference::SetWeekStartDay($values["weekStartDay"]);
Application_Model_Preference::SetEnableSystemEmail($values["enableSystemEmail"]);
Application_Model_Preference::SetSystemEmail($values["systemEmail"]);
Application_Model_Preference::SetMailServerConfigured($values["configureMailServer"]);
Application_Model_Preference::SetMailServer($values["mailServer"]);
Application_Model_Preference::SetMailServerEmailAddress($values["email"]);
Application_Model_Preference::SetMailServerPassword($values["ms_password"]);
Application_Model_Preference::SetMailServerPort($values["port"]);
Application_Model_Preference::SetMailServerRequiresAuth($values["msRequiresAuth"]);
Application_Model_Preference::SetAutoUploadRecordedShowToSoundcloud($values["UseSoundCloud"]);
Application_Model_Preference::SetUploadToSoundcloudOption($values["UploadToSoundcloudOption"]);
Application_Model_Preference::SetSoundCloudDownloadbleOption($values["SoundCloudDownloadbleOption"]);
Application_Model_Preference::SetSoundCloudUser($values["SoundCloudUser"]);
@ -96,20 +84,11 @@ class PreferenceController extends Zend_Controller_Action
$form = new Application_Form_SupportSettings();
if ($request->isPost()) {
$values = $request->getPost();
if ($values["Publicise"] != 1) {
Application_Model_Preference::SetSupportFeedback($values["SupportFeedback"]);
Application_Model_Preference::SetPublicise($values["Publicise"]);
if (isset($values["Privacy"])) {
Application_Model_Preference::SetPrivacyPolicyCheck($values["Privacy"]);
}
} else if ($form->isValid($values)) {
if ($form->isValid($values)) {
Application_Model_Preference::SetHeadTitle($values["stationName"], $this->view);
Application_Model_Preference::SetPhone($values["Phone"]);
Application_Model_Preference::SetEmail($values["Email"]);
Application_Model_Preference::SetStationWebSite($values["StationWebSite"]);
Application_Model_Preference::SetSupportFeedback($values["SupportFeedback"]);
Application_Model_Preference::SetPublicise($values["Publicise"]);
$form->Logo->receive();
$imagePath = $form->Logo->getFileName();
@ -140,15 +119,6 @@ class PreferenceController extends Zend_Controller_Action
public function directoryConfigAction()
{
$CC_CONFIG = Config::getConfig();
$baseUrl = Application_Common_OsPath::getBaseDir();
$this->view->headScript()->appendFile($baseUrl.'js/serverbrowse/serverbrowser.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
$this->view->headScript()->appendFile($baseUrl.'js/airtime/preferences/musicdirs.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
$watched_dirs_pref = new Application_Form_WatchedDirPreferences();
$this->view->form = $watched_dirs_pref;
}
public function streamSettingAction()
@ -254,8 +224,6 @@ class PreferenceController extends Zend_Controller_Action
$error = false;
if ($form->isValid($values)) {
$values['output_sound_device'] = $form->getValue('output_sound_device');
$values['output_sound_device_type'] = $form->getValue('output_sound_device_type');
$values['icecast_vorbis_metadata'] = $form->getValue('icecast_vorbis_metadata');
$values['streamFormat'] = $form->getValue('streamFormat');
@ -288,33 +256,6 @@ class PreferenceController extends Zend_Controller_Action
//Application_Model_RabbitMq::PushSchedule();
}
if (!Application_Model_Preference::GetMasterDjConnectionUrlOverride()) {
$master_connection_url = "http://".$_SERVER['SERVER_NAME'].":".$values["master_harbor_input_port"]."/".$values["master_harbor_input_mount_point"];
if (empty($values["master_harbor_input_port"]) || empty($values["master_harbor_input_mount_point"])) {
Application_Model_Preference::SetMasterDJSourceConnectionURL('N/A');
} else {
Application_Model_Preference::SetMasterDJSourceConnectionURL($master_connection_url);
}
} else {
Application_Model_Preference::SetMasterDJSourceConnectionURL($values["master_dj_connection_url"]);
}
if (!Application_Model_Preference::GetLiveDjConnectionUrlOverride()) {
$live_connection_url = "http://".$_SERVER['SERVER_NAME'].":".$values["dj_harbor_input_port"]."/".$values["dj_harbor_input_mount_point"];
if (empty($values["dj_harbor_input_port"]) || empty($values["dj_harbor_input_mount_point"])) {
Application_Model_Preference::SetLiveDJSourceConnectionURL('N/A');
} else {
Application_Model_Preference::SetLiveDJSourceConnectionURL($live_connection_url);
}
} else {
Application_Model_Preference::SetLiveDJSourceConnectionURL($values["live_dj_connection_url"]);
}
// extra info that goes into cc_stream_setting
Application_Model_StreamSetting::setMasterLiveStreamPort($values["master_harbor_input_port"]);
Application_Model_StreamSetting::setMasterLiveStreamMountPoint($values["master_harbor_input_mount_point"]);
Application_Model_StreamSetting::setDjLiveStreamPort($values["dj_harbor_input_port"]);
Application_Model_StreamSetting::setDjLiveStreamMountPoint($values["dj_harbor_input_mount_point"]);
Application_Model_StreamSetting::setOffAirMeta($values['offAirMeta']);
// store stream update timestamp

View File

@ -1,5 +1,8 @@
<?php
$filepath = realpath (dirname(__FILE__));
require_once($filepath."/../modules/rest/controllers/MediaController.php");
class ScheduleController extends Zend_Controller_Action
{
@ -104,7 +107,7 @@ class ScheduleController extends Zend_Controller_Action
$this->createShowFormAction(true);
$user = Application_Model_User::getCurrentUser();
if ($user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER))) {
if ($user->isUserType(array(UTYPE_SUPERADMIN, UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER))) {
$this->view->preloadShowForm = true;
}
@ -133,10 +136,10 @@ class ScheduleController extends Zend_Controller_Action
{
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
$user = new Application_Model_User($userInfo->id);
$editable = $user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));
$editable = $user->isUserType(array(UTYPE_SUPERADMIN, UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));
$calendar_interval = Application_Model_Preference::GetCalendarTimeScale();
Logging::info($calendar_interval);
// Logging::info($calendar_interval);
if ($calendar_interval == "agendaDay") {
list($start, $end) = Application_Model_Show::getStartEndCurrentDayView();
} else if ($calendar_interval == "agendaWeek") {
@ -167,6 +170,15 @@ class ScheduleController extends Zend_Controller_Action
$deltaDay = $this->_getParam('day');
$deltaMin = $this->_getParam('min');
$log_vars = array();
$log_vars["url"] = $_SERVER['HTTP_HOST'];
$log_vars["action"] = "schedule/move-show";
$log_vars["params"] = array();
$log_vars["params"]["instance id"] = $this->_getParam('showInstanceId');
$log_vars["params"]["delta day"] = $deltaDay;
$log_vars["params"]["delta minute"] = $deltaMin;
Logging::info($log_vars);
try {
$service_calendar = new Application_Service_CalendarService(
$this->_getParam('showInstanceId'));
@ -174,7 +186,7 @@ class ScheduleController extends Zend_Controller_Action
$this->view->show_error = true;
return false;
}
$error = $service_calendar->moveShow($deltaDay, $deltaMin);
if (isset($error)) {
$this->view->error = $error;
@ -188,10 +200,19 @@ class ScheduleController extends Zend_Controller_Action
$showId = $this->_getParam('showId');
$instanceId = $this->_getParam('instanceId');
$log_vars = array();
$log_vars["url"] = $_SERVER['HTTP_HOST'];
$log_vars["action"] = "schedule/resize-show";
$log_vars["params"] = array();
$log_vars["params"]["instance id"] = $instanceId;
$log_vars["params"]["delta day"] = $deltaDay;
$log_vars["params"]["delta minute"] = $deltaMin;
Logging::info($log_vars);
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
$user = new Application_Model_User($userInfo->id);
if ($user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER))) {
if ($user->isUserType(array(UTYPE_SUPERADMIN, UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER))) {
try {
$show = new Application_Model_Show($showId);
} catch (Exception $e) {
@ -211,6 +232,13 @@ class ScheduleController extends Zend_Controller_Action
{
$instanceId = $this->_getParam('id');
$log_vars = array();
$log_vars["url"] = $_SERVER['HTTP_HOST'];
$log_vars["action"] = "schedule/delete-show-instance";
$log_vars["params"] = array();
$log_vars["params"]["instance id"] = $instanceId;
Logging::info($log_vars);
$service_show = new Application_Service_ShowService();
$showId = $service_show->deleteShow($instanceId, true);
@ -223,6 +251,7 @@ class ScheduleController extends Zend_Controller_Action
public function uploadToSoundCloudAction()
{
$show_instance = $this->_getParam('id');
try {
$show_inst = new Application_Model_ShowInstance($show_instance);
} catch (Exception $e) {
@ -250,6 +279,13 @@ class ScheduleController extends Zend_Controller_Action
public function clearShowAction()
{
$instanceId = $this->_getParam('id');
$log_vars = array();
$log_vars["url"] = $_SERVER['HTTP_HOST'];
$log_vars["action"] = "schedule/clear-show";
$log_vars["params"] = array();
$log_vars["params"]["instance id"] = $instanceId;
Logging::info($log_vars);
$service_scheduler = new Application_Service_SchedulerService();
@ -328,7 +364,7 @@ class ScheduleController extends Zend_Controller_Action
return false;
}
$originalShowId = $show->isRebroadcast();
if (!is_null($originalShowId)) {
try {
@ -425,6 +461,13 @@ class ScheduleController extends Zend_Controller_Action
$data['add_show_hosts'] = $this->_getParam('hosts');
$log_vars = array();
$log_vars["url"] = $_SERVER['HTTP_HOST'];
$log_vars["action"] = "schedule/edit-repeating-show-instance";
$log_vars["params"] = array();
$log_vars["params"]["form_data"] = $data;
Logging::info($log_vars);
$service_showForm = new Application_Service_ShowFormService(
$data["add_show_id"], $data["add_show_instance_id"]);
$service_show = new Application_Service_ShowService(null, $data);
@ -441,7 +484,7 @@ class ScheduleController extends Zend_Controller_Action
$this->view->addNewShow = true;
$this->view->newForm = $this->view->render('schedule/add-show-form.phtml');
} else {
} else {
if (!$validateStartDate) {
$this->view->when->getElement('add_show_start_date')->setOptions(array('disabled' => true));
}
@ -476,18 +519,25 @@ class ScheduleController extends Zend_Controller_Action
if ($data['add_show_day_check'] == "") {
$data['add_show_day_check'] = null;
}
$log_vars = array();
$log_vars["url"] = $_SERVER['HTTP_HOST'];
$log_vars["action"] = "schedule/edit-show";
$log_vars["params"] = array();
$log_vars["params"]["form_data"] = $data;
Logging::info($log_vars);
$forms = $this->createShowFormAction();
list($data, $validateStartDate, $validateStartTime, $originalShowStartDateTime) =
$service_showForm->preEditShowValidationCheck($data);
if ($service_showForm->validateShowForms($forms, $data, $validateStartDate,
$originalShowStartDateTime, true, $data["add_show_instance_id"])) {
$service_show->addUpdateShow($data);
$this->view->addNewShow = true;
// Get the show ID from the show service to pass as a parameter to the RESTful ShowController
$this->view->showId = $service_show->addUpdateShow($data);
$this->view->addNewShow = true;
$this->view->newForm = $this->view->render('schedule/add-show-form.phtml');
} else {
if (!$validateStartDate) {
@ -496,7 +546,8 @@ class ScheduleController extends Zend_Controller_Action
if (!$validateStartTime) {
$this->view->when->getElement('add_show_start_time')->setOptions(array('disabled' => true));
}
$this->view->rr->getElement('add_show_record')->setOptions(array('disabled' => true));
//$this->view->rr->getElement('add_show_record')->setOptions(array('disabled' => true));
$this->view->addNewShow = false;
$this->view->action = "edit-show";
$this->view->form = $this->view->render('schedule/add-show-form.phtml');
@ -506,8 +557,7 @@ class ScheduleController extends Zend_Controller_Action
public function addShowAction()
{
$service_showForm = new Application_Service_ShowFormService(null);
//$service_show = new Application_Service_ShowService();
$js = $this->_getParam('data');
$data = array();
@ -519,31 +569,39 @@ class ScheduleController extends Zend_Controller_Action
$service_show = new Application_Service_ShowService(null, $data);
// TODO: move this to js
$data['add_show_hosts'] = $this->_getParam('hosts');
$data['add_show_day_check'] = $this->_getParam('days');
$data['add_show_hosts'] = $this->_getParam('hosts');
$data['add_show_day_check'] = $this->_getParam('days');
if ($data['add_show_day_check'] == "") {
$data['add_show_day_check'] = null;
}
$log_vars = array();
$log_vars["url"] = $_SERVER['HTTP_HOST'];
$log_vars["action"] = "schedule/add-show";
$log_vars["params"] = array();
$log_vars["params"]["form_data"] = $data;
Logging::info($log_vars);
$forms = $this->createShowFormAction();
$this->view->addNewShow = true;
if ($service_showForm->validateShowForms($forms, $data)) {
$service_show->addUpdateShow($data);
// Get the show ID from the show service to pass as a parameter to the RESTful ShowController
$this->view->showId = $service_show->addUpdateShow($data);
//send new show forms to the user
$this->createShowFormAction(true);
$this->view->newForm = $this->view->render('schedule/add-show-form.phtml');
Logging::debug("Show creation succeeded");
} else {
$this->view->form = $this->view->render('schedule/add-show-form.phtml');
$this->view->form = $this->view->render('schedule/add-show-form.phtml');
Logging::debug("Show creation failed");
}
}
public function createShowFormAction($populateDefaults=false)
{
$service_showForm = new Application_Service_ShowFormService();
@ -572,10 +630,17 @@ class ScheduleController extends Zend_Controller_Action
public function deleteShowAction()
{
$instanceId = $this->_getParam('id');
$log_vars = array();
$log_vars["url"] = $_SERVER['HTTP_HOST'];
$log_vars["action"] = "schedule/delete-show";
$log_vars["params"] = array();
$log_vars["params"]["instance id"] = $instanceId;
Logging::info($log_vars);
$service_show = new Application_Service_ShowService();
$showId = $service_show->deleteShow($instanceId);
if (!$showId) {
$this->view->show_error = true;
}
@ -584,9 +649,16 @@ class ScheduleController extends Zend_Controller_Action
public function cancelCurrentShowAction()
{
$log_vars = array();
$log_vars["url"] = $_SERVER['HTTP_HOST'];
$log_vars["action"] = "schedule/cancel-current-show";
$log_vars["params"] = array();
$log_vars["params"]["instance id"] = $this->_getParam('id');
Logging::info($log_vars);
$user = Application_Model_User::getCurrentUser();
if ($user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER))) {
if ($user->isUserType(array(UTYPE_SUPERADMIN, UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER))) {
$id = $this->_getParam('id');
try {
@ -611,7 +683,7 @@ class ScheduleController extends Zend_Controller_Action
$paramsPop = str_replace('#id#', $id, $params);
// added for downlaod
// added for download
$id = $this->_getParam('id');
$file_id = $this->_getParam('id', null);
@ -636,7 +708,7 @@ class ScheduleController extends Zend_Controller_Action
Application_Model_Preference::SetCalendarTimeScale($this->_getParam('timeScale'));
}
/**
/**
* Sets the user specific preference for which time interval to use in Calendar.
* This is only being used by schedule.js at the moment.
*/
@ -682,4 +754,5 @@ class ScheduleController extends Zend_Controller_Action
$this->_helper->json->sendJson($localTime);
}
}

View File

@ -1,5 +1,7 @@
<?php
require_once('CORSHelper.php');
class ShowbuilderController extends Zend_Controller_Action
{
@ -22,12 +24,18 @@ class ShowbuilderController extends Zend_Controller_Action
$CC_CONFIG = Config::getConfig();
$request = $this->getRequest();
$response = $this->getResponse();
//Enable AJAX requests from www.airtime.pro because the autologin during the seamless sign-up follows
//a redirect here.
CORSHelper::enableATProCrossOriginRequests($request, $response);
$baseUrl = Application_Common_OsPath::getBaseDir();
$user = Application_Model_User::GetCurrentUser();
$userType = $user->getType();
$this->view->headScript()->appendScript("localStorage.setItem( 'user-type', '$userType' );");
$this->view->headScript()->appendScript($this->generateGoogleTagManagerDataLayerJavaScript());
$this->view->headScript()->appendFile($baseUrl.'js/contextmenu/jquery.contextMenu.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
$this->view->headScript()->appendFile($baseUrl.'js/datatables/js/jquery.dataTables.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
@ -323,8 +331,17 @@ class ShowbuilderController extends Zend_Controller_Action
public function scheduleAddAction()
{
$request = $this->getRequest();
$mediaItems = $request->getParam("mediaIds", array());
$scheduledItems = $request->getParam("schedIds", array());
$log_vars = array();
$log_vars["url"] = $_SERVER['HTTP_HOST'];
$log_vars["action"] = "showbuilder/schedule-add";
$log_vars["params"] = array();
$log_vars["params"]["media_items"] = $mediaItems;
$log_vars["params"]["scheduled_items"] = $scheduledItems;
Logging::info($log_vars);
try {
$scheduler = new Application_Model_Scheduler();
@ -342,6 +359,13 @@ class ShowbuilderController extends Zend_Controller_Action
{
$request = $this->getRequest();
$items = $request->getParam("items", array());
$log_vars = array();
$log_vars["url"] = $_SERVER['HTTP_HOST'];
$log_vars["action"] = "showbuilder/schedule-remove";
$log_vars["params"] = array();
$log_vars["params"]["removed_items"] = $items;
Logging::info($log_vars);
try {
$scheduler = new Application_Model_Scheduler();
@ -360,6 +384,14 @@ class ShowbuilderController extends Zend_Controller_Action
$request = $this->getRequest();
$selectedItems = $request->getParam("selectedItem");
$afterItem = $request->getParam("afterItem");
$log_vars = array();
$log_vars["url"] = $_SERVER['HTTP_HOST'];
$log_vars["action"] = "showbuilder/schedule-move";
$log_vars["params"] = array();
$log_vars["params"]["selected_items"] = $selectedItems;
$log_vars["params"]["destination_after_item"] = $afterItem;
Logging::info($log_vars);
try {
$scheduler = new Application_Model_Scheduler();
@ -378,4 +410,103 @@ class ShowbuilderController extends Zend_Controller_Action
throw new Exception("this controller is/was a no-op please fix your
code");
}
/** Returns a string containing the JavaScript code to pass some billing account info
* into Google Tag Manager / Google Analytics, so we can track things like the plan type.
*/
private static function generateGoogleTagManagerDataLayerJavaScript()
{
$code = "";
try
{
$accessKey = $_SERVER["WHMCS_ACCESS_KEY"];
$username = $_SERVER["WHMCS_USERNAME"];
$password = $_SERVER["WHMCS_PASSWORD"];
$url = "https://account.sourcefabric.com/includes/api.php?accesskey=" . $accessKey; # URL to WHMCS API file goes here
$postfields = array();
$postfields["username"] = $username;
$postfields["password"] = md5($password);
$postfields["action"] = "getclientsdetails";
$postfields["stats"] = true;
$postfields["clientid"] = Application_Model_Preference::GetClientId();
$postfields["responsetype"] = "json";
$query_string = "";
foreach ($postfields AS $k=>$v) $query_string .= "$k=".urlencode($v)."&";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 5); //Aggressive 5 second timeout
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $query_string);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
$jsondata = curl_exec($ch);
if (curl_error($ch)) {
//die("Connection Error: ".curl_errno($ch).' - '.curl_error($ch));
throw new Exception("WHMCS server down or invalid request.");
}
curl_close($ch);
$arr = json_decode($jsondata); # Decode JSON String
if ($arr->result !== "success") {
Logging::warn("WHMCS API call failed in " . __FUNCTION__);
return;
}
$client = $arr->client;
$stats = $arr->stats;
$currencyCode = $client->currency_code;
//$incomeCents = NumberFormatter::parseCurrency($stats->income, $currencyCode);
$isTrial = true;
if (strpos($stats->income, "0.00") === FALSE) {
$isTrial = false;
}
/*
if ($incomeCents > 0) {
$isTrial = false;
}*/
$plan = Application_Model_Preference::GetPlanLevel();
$country = $client->country;
$postcode = $client->postcode;
//Figure out how long the customer has been around using a mega hack.
//(I'm avoiding another round trip to WHMCS for now...)
//We calculate it based on the trial end date...
$trialEndDateStr = Application_Model_Preference::GetTrialEndingDate();
if ($trialEndDateStr == '') {
$accountDuration = 0;
} else {
$today = new DateTime();
$trialEndDate = new DateTime($trialEndDateStr);
$trialDuration = new DateInterval("P30D"); //30 day trial duration
$accountCreationDate = $trialEndDate->sub($trialDuration);
$interval = $today->diff($accountCreationDate);
$accountDuration = $interval->days;
}
$code = "$( document ).ready(function() {
dataLayer.push({
'ZipCode': '" . $postcode . "',
'UserID': '" . $client->id . "',
'Customer': 'Customer',
'PlanType': '" . $plan . "',
'Trial': '" . $isTrial . "',
'Country': '" . $country . "',
'AccountDuration': '" . strval($accountDuration) . "'
});
});";
}
catch (Exception $e)
{
return "";
}
return $code;
}
}

View File

@ -1,76 +1,53 @@
<?php
require_once("Upgrades.php");
class UpgradeController extends Zend_Controller_Action
{
public function indexAction()
{
$airtime_upgrade_version = '2.5.3';
$this->view->layout()->disableLayout();
$this->_helper->viewRenderer->setNoRender(true);
if (!$this->verifyAuth()) {
return;
}
$upgraders = array();
array_push($upgraders, new AirtimeUpgrader253());
array_push($upgraders, new AirtimeUpgrader254());
array_push($upgraders, new AirtimeUpgrader255());
if (!$this->verifyAirtimeVersion()) {
return;
}
$con = Propel::getConnection();
$con->beginTransaction();
try {
//Disable Airtime UI
//create a temporary maintenance notification file
//when this file is on the server, zend framework redirects all
//requests to the maintenance page and sets a 503 response code
$maintenanceFile = isset($_SERVER['AIRTIME_BASE']) ? $_SERVER['AIRTIME_BASE']."maintenance.txt" : "/tmp/maintenance.txt";
$file = fopen($maintenanceFile, 'w');
fclose($file);
//Begin upgrade
$didWePerformAnUpgrade = false;
try
{
for ($i = 0; $i < count($upgraders); $i++)
{
$upgrader = $upgraders[$i];
if ($upgrader->checkIfUpgradeSupported())
{
// pass __DIR__ to the upgrades, since __DIR__ returns parent dir of file, not executor
$upgrader->upgrade(__DIR__); //This will throw an exception if the upgrade fails.
$didWePerformAnUpgrade = true;
$this->getResponse()
->setHttpResponseCode(200)
->appendBody("Upgrade to Airtime " . $upgrader->getNewVersion() . " OK<br>");
$i = 0; //Start over, in case the upgrade handlers are not in ascending order.
}
}
//Update disk_usage value in cc_pref
$musicDir = CcMusicDirsQuery::create()
->filterByType('stor')
->filterByExists(true)
->findOne();
$storPath = $musicDir->getDirectory();
$freeSpace = disk_free_space($storPath);
$totalSpace = disk_total_space($storPath);
Application_Model_Preference::setDiskUsage($totalSpace - $freeSpace);
//TODO: clear out the cache
$con->commit();
//update system_version in cc_pref and change some columns in cc_files
$airtimeConf = isset($_SERVER['AIRTIME_CONF']) ? $_SERVER['AIRTIME_CONF'] : "/etc/airtime/airtime.conf";
$values = parse_ini_file($airtimeConf, true);
$username = $values['database']['dbuser'];
$password = $values['database']['dbpass'];
$host = $values['database']['host'];
$database = $values['database']['dbname'];
$dir = __DIR__;
passthru("export PGPASSWORD=$password && psql -h $host -U $username -q -f $dir/upgrade_sql/airtime_$airtime_upgrade_version/upgrade.sql $database 2>&1 | grep -v \"will create implicit index\"");
//delete maintenance.txt to give users access back to Airtime
unlink($maintenanceFile);
if (!$didWePerformAnUpgrade)
{
$this->getResponse()
->setHttpResponseCode(200)
->appendBody("No upgrade was performed. The current Airtime version is " . AirtimeUpgrader::getCurrentVersion() . ".<br>");
}
}
catch (Exception $e)
{
$this->getResponse()
->setHttpResponseCode(200)
->appendBody("Upgrade to Airtime 2.5.3 OK");
} catch(Exception $e) {
$con->rollback();
unlink($maintenanceFile);
$this->getResponse()
->setHttpResponseCode(400)
->appendBody($e->getMessage());
->setHttpResponseCode(400)
->appendBody($e->getMessage());
}
}
@ -90,26 +67,11 @@ class UpgradeController extends Zend_Controller_Action
if ($encodedRequestApiKey !== $encodedStoredApiKey)
{
$this->getResponse()
->setHttpResponseCode(401)
->appendBody("Error: Incorrect API key.");
->setHttpResponseCode(401)
->appendBody("Error: Incorrect API key.<br>");
return false;
}
return true;
}
private function verifyAirtimeVersion()
{
$pref = CcPrefQuery::create()
->filterByKeystr('system_version')
->findOne();
$airtime_version = $pref->getValStr();
if (!in_array($airtime_version, array('2.5.1', '2.5.2'))) {
$this->getResponse()
->setHttpResponseCode(400)
->appendBody("Upgrade to Airtime 2.5.3 FAILED. You must be using Airtime 2.5.1 or 2.5.2 to upgrade.");
return false;
}
return true;
}
}

View File

@ -62,7 +62,11 @@ class UserController extends Zend_Controller_Action
if ($formData['password'] != "xxxxxx") {
$user->setPassword($formData['password']);
}
$user->setType($formData['type']);
if (array_key_exists('type', $formData)) {
if ($formData['type'] != UTYPE_SUPERADMIN) { //Don't allow any other user to be promoted to Super Admin
$user->setType($formData['type']);
}
}
$user->setEmail($formData['email']);
$user->setCellPhone($formData['cell_phone']);
$user->setSkype($formData['skype']);
@ -120,7 +124,7 @@ class UserController extends Zend_Controller_Action
}
public function editUserAction()
{
{
$request = $this->getRequest();
$form = new Application_Form_EditUser();
if ($request->isPost()) {
@ -129,12 +133,21 @@ class UserController extends Zend_Controller_Action
if ($form->isValid($formData) &&
$form->validateLogin($formData['cu_login'], $formData['cu_user_id'])) {
$user = new Application_Model_User($formData['cu_user_id']);
//Stupid hack because our schema enforces non-null first_name
//even though by default the admin user has no first name... (....)
if (Application_Model_User::getCurrentUser()->isSuperAdmin()) {
if (empty($formData['cu_first_name'])) {
$formData['cu_first_name'] = "admin";
$formData['cu_last_name'] = "admin"; //ditto, avoid non-null DB constraint
}
}
$user->setFirstName($formData['cu_first_name']);
$user->setLastName($formData['cu_last_name']);
// We don't allow 6 x's as a password.
// The reason is because we use that as a password placeholder
// on the client side.
if ($formData['cu_password'] != "xxxxxx") {
if (($formData['cu_password'] != "xxxxxx") &&
(!empty($formData['cu_password']))) {
$user->setPassword($formData['cu_password']);
}
$user->setEmail($formData['cu_email']);
@ -187,6 +200,12 @@ class UserController extends Zend_Controller_Action
}
$user = new Application_Model_User($delId);
// Don't allow super admins to be deleted.
if ($user->isSuperAdmin())
{
return;
}
# Take care of the user's files by either assigning them to somebody
# or deleting them all

View File

@ -88,7 +88,7 @@ class WebstreamController extends Zend_Controller_Action
public function isAuthorized($webstream_id)
{
$user = Application_Model_User::getCurrentUser();
if ($user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER))) {
if ($user->isUserType(array(UTYPE_SUPERADMIN, UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER))) {
return true;
}

View File

@ -0,0 +1,258 @@
<?php
class WhmcsLoginController extends Zend_Controller_Action
{
public function init()
{
}
public function indexAction()
{
$CC_CONFIG = Config::getConfig();
$request = $this->getRequest();
$this->view->layout()->disableLayout();
$this->_helper->viewRenderer->setNoRender(true);
$username = "admin"; //This is just for appearance in your session. It shows up in the corner of the Airtime UI.
$email = $_POST["email"];
$password = $_POST["password"];
Application_Model_Locale::configureLocalization($request->getcookie('airtime_locale', 'en_CA'));
if (Zend_Auth::getInstance()->hasIdentity())
{
$this->_redirect('Showbuilder');
}
$authAdapter = new WHMCS_Auth_Adapter($username, $email, $password);
$auth = Zend_Auth::getInstance();
$result = $auth->authenticate($authAdapter);
if ($result->isValid()) {
//all info about this user from the login table omit only the password
//$userInfo = $authAdapter->getResultRowObject(null, 'password');
//the default storage is a session with namespace Zend_Auth
/*
[id] => 1
[login] => admin
[pass] => hashed password
[type] => A
[first_name] =>
[last_name] =>
[lastlogin] =>
[lastfail] =>
[skype_contact] =>
[jabber_contact] =>
[email] => asdfasdf@asdasdf.com
[cell_phone] =>
[login_attempts] => 0
*/
//Zend_Auth already does this for us, it's not needed:
//$authStorage = $auth->getStorage();
//$authStorage->write($result->getIdentity()); //$userInfo);
//set the user locale in case user changed it in when logging in
//$locale = $form->getValue('locale');
//Application_Model_Preference::SetUserLocale($locale);
$this->_redirect('Showbuilder');
}
else {
echo("Sorry, that username or password was incorrect.");
}
return;
}
}
class WHMCS_Auth_Adapter implements Zend_Auth_Adapter_Interface {
private $username;
private $password;
private $email;
function __construct($username, $email, $password) {
$this->username = $username;
$this->password = $password;
$this->email = $email;
$this->identity = null;
}
function authenticate() {
list($credentialsValid, $clientId) = $this->validateCredentialsWithWHMCS($this->email, $this->password);
if (!$credentialsValid)
{
return new Zend_Auth_Result(Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID, null);
}
if (!$this->verifyClientSubdomainOwnership($clientId))
{
return new Zend_Auth_Result(Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID, null);
}
$identity = array();
//TODO: Get identity of the first admin user!
/*
$identity["id"] = 1;
$identity["type"] = "S";
$identity["login"] = $this->username; //admin";
$identity["email"] = $this->email;*/
$identity = $this->getSuperAdminIdentity();
if (is_null($identity)) {
Logging::error("No super admin user found");
return new Zend_Auth_Result(Zend_Auth_Result::FAILURE, null);
}
$identity = (object)$identity; //Convert the array into an stdClass object
try {
return new Zend_Auth_Result(Zend_Auth_Result::SUCCESS, $identity);
} catch (Exception $e) {
// exception occured
return new Zend_Auth_Result(Zend_Auth_Result::FAILURE, null);
}
}
private function getSuperAdminIdentity()
{
$firstSuperAdminUser = CcSubjsQuery::create()
->filterByDbType('S')
->orderByDbId()
->findOne();
if (!$firstSuperAdminUser) {
//If there's no super admin users, get the first regular admin user!
$firstSuperAdminUser = CcSubjsQuery::create()
->filterByDbType('A')
->orderByDbId()
->findOne();
if (!$firstSuperAdminUser) {
return null;
}
}
$identity["id"] = $firstSuperAdminUser->getDbId();
$identity["type"] = "S"; //Super Admin
$identity["login"] = $firstSuperAdminUser->getDbLogin();
$identity["email"] = $this->email;
return $identity;
}
//Returns an array! Read the code carefully:
private function validateCredentialsWithWHMCS($email, $password)
{
$client_postfields = array();
$client_postfields["username"] = $_SERVER['WHMCS_USERNAME']; //WHMCS API username
$client_postfields["password"] = md5($_SERVER['WHMCS_PASSWORD']); //WHMCS API password
$client_postfields["action"] ="validatelogin";
$client_postfields["responsetype"] = "json";
$client_postfields["email"] = $email;
$client_postfields["password2"] = $password;
$query_string = "";
foreach ($client_postfields as $k => $v) $query_string .= "$k=".urlencode($v)."&";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, WHMCS_API_URL);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_FAILONERROR, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $query_string);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
$jsondata = curl_exec($ch);
if (curl_error($ch)) {
die(curl_getinfo($ch, CURLINFO_EFFECTIVE_URL));
//die("Connection Error: ".curl_errno($ch).' - '.curl_error($ch));
}
curl_close($ch);
$arr = json_decode($jsondata, true); # Decode JSON String
if ($arr["result"] != "success") {
return array(false, -1);
}
$clientId = $arr["userid"];
return array(true, $clientId);
}
function verifyClientSubdomainOwnership($clientId)
{
//Do a quick safety check to ensure the client ID we're authenticating
//matches up to the owner of this instance.
if ($clientId != Application_Model_Preference::GetClientId())
{
return false;
}
$client_postfields = array();
$client_postfields["username"] = $_SERVER['WHMCS_USERNAME'];
$client_postfields["password"] = md5($_SERVER['WHMCS_PASSWORD']);
$client_postfields["action"] ="getclientsproducts";
$client_postfields["responsetype"] = "json";
$client_postfields["clientid"] = $clientId;
//$client_postfields["stats"] = "true";
$query_string = "";
foreach ($client_postfields as $k => $v) $query_string .= "$k=".urlencode($v)."&";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, WHMCS_API_URL);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_FAILONERROR, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $query_string);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
$jsondata = curl_exec($ch);
if (curl_error($ch)) {
die(curl_getinfo($ch, CURLINFO_EFFECTIVE_URL));
//die("Connection Error: ".curl_errno($ch).' - '.curl_error($ch));
}
curl_close($ch);
$arr = json_decode($jsondata, true); # Decode JSON String
//$client_id = $arr["clientid"];
//print_r($arr);
if ($arr["result"] != "success") {
die("Sorry, that email address or password was incorrect.");
}
$doesAirtimeProductExist = false;
$isAirtimeAccountSuspended = true;
$airtimeProduct = null;
foreach ($arr["products"]["product"] as $product)
{
if (strpos($product["groupname"], "Airtime") === FALSE)
{
//Ignore non-Airtime products
continue;
}
else
{
if ($product["status"] === "Active") {
$airtimeProduct = $product;
$subdomain = '';
foreach ($airtimeProduct['customfields']['customfield'] as $customField)
{
if ($customField['name'] === SUBDOMAIN_WHMCS_CUSTOM_FIELD_NAME)
{
$subdomain = $customField['value'];
if (($subdomain . ".airtime.pro") === $_SERVER['SERVER_NAME'])
{
return true;
}
}
}
}
}
}
return false;
}
}

View File

@ -118,7 +118,7 @@ class Zend_Controller_Plugin_Acl extends Zend_Controller_Plugin_Abstract
return;
}
if (in_array($controller, array("api", "auth", "locale", "upgrade"))) {
if (in_array($controller, array("api", "auth", "locale", "upgrade", 'whmcs-login'))) {
$this->setRoleName("G");
} elseif (!Zend_Auth::getInstance()->hasIdentity()) {

View File

@ -7,13 +7,9 @@ class RabbitMqPlugin extends Zend_Controller_Plugin_Abstract
if (Application_Model_RabbitMq::$doPush) {
$md = array('schedule' => Application_Model_Schedule::getSchedule());
Application_Model_RabbitMq::SendMessageToPypo("update_schedule", $md);
if (!isset($_SERVER['AIRTIME_SRV'])) {
Application_Model_RabbitMq::SendMessageToShowRecorder("update_recorder_schedule");
}
}
if (memory_get_peak_usage() > 30*pow(2, 20)) {
Logging::debug("Peak memory usage: "
.(memory_get_peak_usage()/1000000)
." MB while accessing URI ".$_SERVER['REQUEST_URI']);

View File

@ -0,0 +1,5 @@
DELETE FROM cc_pref WHERE keystr = 'system_version';
INSERT INTO cc_pref (keystr, valstr) VALUES ('system_version', '2.5.5');
ALTER TABLE cc_show ADD COLUMN image_path varchar(255) DEFAULT '';
ALTER TABLE cc_show_instances ADD COLUMN description varchar(255) DEFAULT '';

View File

@ -1,5 +1,7 @@
<?php
require_once 'customfilters/ImageSize.php';
class Application_Form_AddShowStyle extends Zend_Form_SubForm
{
@ -24,7 +26,7 @@ class Application_Form_AddShowStyle extends Zend_Form_SubForm
'Hex', $stringLengthValidator
));
// Add show color input
// Add show color input
$this->addElement('text', 'add_show_color', array(
'label' => _('Text Colour:'),
'class' => 'input_text',
@ -41,6 +43,56 @@ class Application_Form_AddShowStyle extends Zend_Form_SubForm
$c->setValidators(array(
'Hex', $stringLengthValidator
));
// Show the current logo
$this->addElement('image', 'add_show_logo_current', array(
'label' => _('Current Logo:'),
));
$logo = $this->getElement('add_show_logo_current');
$logo->setDecorators(array(
array('ViewScript', array(
'viewScript' => 'form/add-show-style.phtml',
'class' => 'big'
))
));
// Since we need to use a Zend_Form_Element_Image proto, disable it
$logo->setAttrib('disabled','disabled');
// Button to remove the current logo
$this->addElement('button', 'add_show_logo_current_remove', array(
'label' => '<span class="ui-button-text">' . _('Remove') . '</span>',
'class' => 'ui-button ui-state-default ui-button-text-only',
'escape' => false
));
// Add show image input
$upload = new Zend_Form_Element_File('add_show_logo');
$upload->setLabel(_('Show Logo:'))
->setRequired(false)
->setDecorators(array('File', array('ViewScript', array(
'viewScript' => 'form/add-show-style.phtml',
'class' => 'big',
'placement' => false
))))
->addValidator('Count', false, 1)
->addValidator('Extension', false, 'jpg,jpeg,png,gif')
->addFilter('ImageSize');
$this->addElement($upload);
// Add image preview
$this->addElement('image', 'add_show_logo_preview', array(
'label' => _('Logo Preview:'),
));
$preview = $this->getElement('add_show_logo_preview');
$preview->setDecorators(array(array('ViewScript', array(
'viewScript' => 'form/add-show-style.phtml',
'class' => 'big'
))));
$preview->setAttrib('disabled','disabled');
}
public function disable()

View File

@ -27,7 +27,7 @@ class Application_Form_AddShowWhat extends Zend_Form_SubForm
'class' => 'input_text',
'required' => true,
'filters' => array('StringTrim'),
'value' => _('Untitled Show'),
'value' => _('Untitled Show'),
'validators' => array($notEmptyValidator, array('StringLength', false, array(0, $maxLens['name'])))
));
@ -63,7 +63,33 @@ class Application_Form_AddShowWhat extends Zend_Form_SubForm
'viewScript' => 'form/add-show-block.phtml',
'class' => 'block-display'
))));
// Add the instance description
$this->addElement('textarea', 'add_show_instance_description', array(
'label' => _('Instance Description:'),
'required' => false,
'class' => 'input_text_area',
'validators' => array(array('StringLength', false, array(0, $maxLens['description'])))
));
$instanceDesc = $this->getElement('add_show_instance_description');
$instanceDesc->setDecorators(array(array('ViewScript', array(
'viewScript' => 'form/add-show-block.phtml',
'class' => 'block-display'
))));
$instanceDesc->setAttrib('disabled','disabled');
}
/**
* Enable the instance description when editing a show instance
*/
public function enableInstanceDesc()
{
$el = $this->getElement('add_show_instance_description');
Logging::info($el);
$el->setAttrib('disabled', null);
$el->setAttrib('readonly', null);
}
public function disable()

View File

@ -118,7 +118,7 @@ class Application_Form_AddShowWhen extends Zend_Form_SubForm
$nowDateTime = new DateTime("now", $showTimezone);
$showStartDateTime = new DateTime($start_time, $showTimezone);
$showEndDateTime = new DateTime($end_time, $showTimezone);
if ($validateStartDate) {
if ($showStartDateTime < $nowDateTime) {
$this->getElement('add_show_start_time')->setErrors(array(_('Cannot create show in the past')));
@ -135,16 +135,16 @@ class Application_Form_AddShowWhen extends Zend_Form_SubForm
}
}
}
// if end time is in the past, return error
if ($showEndDateTime < $nowDateTime) {
$this->getElement('add_show_end_time')->setErrors(array(_('End date/time cannot be in the past')));
$valid = false;
}
//validate duration.
$duration = $showStartDateTime->diff($showEndDateTime);
if ($showStartDateTime > $showEndDateTime) {
$this->getElement('add_show_duration')->setErrors(array(_('Cannot have duration < 0m')));
$valid = false;
@ -153,14 +153,14 @@ class Application_Form_AddShowWhen extends Zend_Form_SubForm
$this->getElement('add_show_duration')->setErrors(array(_('Cannot have duration 00h 00m')));
$valid = false;
}
else if (intval($duration->format('%d')) > 0 &&
else if (intval($duration->format('%d')) > 0 &&
(intval($duration->format('%h')) > 0
|| intval($duration->format('%i')) > 0
|| intval($duration->format('%s')) > 0)) {
$this->getElement('add_show_duration')->setErrors(array(_('Cannot have duration greater than 24h')));
$valid = false;
}
/* We need to know the show duration broken down into hours and minutes
* They are used for checking overlapping shows and for validating
@ -176,7 +176,7 @@ class Application_Form_AddShowWhen extends Zend_Form_SubForm
if ($valid) {
//we need to know the start day of the week in show's local timezome
$startDow = $showStartDateTime->format("w");
$utc = new DateTimeZone('UTC');
$showStartDateTime->setTimezone($utc);
$showEndDateTime->setTimezone($utc);
@ -264,24 +264,11 @@ class Application_Form_AddShowWhen extends Zend_Form_SubForm
//this is a new show
$overlapping = Application_Model_Schedule::checkOverlappingShows(
$repeatShowStart, $repeatShowEnd);
/* If the repeating show is rebroadcasted we need to check
* the rebroadcast dates relative to the repeating show
*/
if (!$overlapping && $formData['add_show_rebroadcast']) {
$overlapping = self::checkRebroadcastDates(
$repeatShowStart, $formData, $hours, $minutes);
}
} else {
$overlapping = Application_Model_Schedule::checkOverlappingShows(
$repeatShowStart, $repeatShowEnd, $update, null, $formData["add_show_id"]);
if (!$overlapping && $formData['add_show_rebroadcast']) {
$overlapping = self::checkRebroadcastDates(
$repeatShowStart, $formData, $hours, $minutes, true);
}
}
if ($overlapping) {
$valid = false;
$this->getElement('add_show_duration')->setErrors(array(_('Cannot schedule overlapping shows')));
@ -300,36 +287,7 @@ class Application_Form_AddShowWhen extends Zend_Form_SubForm
$valid = false;
$this->getElement('add_show_duration')->setErrors(array(_('Cannot schedule overlapping shows')));
}
} elseif ($formData["add_show_rebroadcast"]) {
/* Check first show
* Continue if the first show does not overlap
*/
$overlapping = Application_Model_Schedule::checkOverlappingShows($showStartDateTime, $showEndDateTime, $update, $instanceId);
if (!$overlapping) {
$durationToAdd = "PT".$hours."H".$minutes."M";
for ($i = 1; $i <= 10; $i++) {
if (empty($formData["add_show_rebroadcast_date_absolute_".$i])) break;
$abs_rebroadcast_start = $formData["add_show_rebroadcast_date_absolute_".$i]." ".
$formData["add_show_rebroadcast_time_absolute_".$i];
$rebroadcastShowStart = new DateTime($abs_rebroadcast_start);
$rebroadcastShowStart->setTimezone(new DateTimeZone('UTC'));
$rebroadcastShowEnd = clone $rebroadcastShowStart;
$rebroadcastShowEnd->add(new DateInterval($durationToAdd));
$overlapping = Application_Model_Schedule::checkOverlappingShows($rebroadcastShowStart,
$rebroadcastShowEnd, $update, null, $formData["add_show_id"]);
if ($overlapping) {
$valid = false;
$this->getElement('add_show_duration')->setErrors(array(_('Cannot schedule overlapping shows')));
break;
}
}
} else {
$valid = false;
$this->getElement('add_show_duration')->setErrors(array(_('Cannot schedule overlapping shows')));
}
} else {
$overlapping = Application_Model_Schedule::checkOverlappingShows($showStartDateTime, $showEndDateTime, $update, $instanceId);
if ($overlapping) {
@ -357,10 +315,10 @@ class Application_Form_AddShowWhen extends Zend_Form_SubForm
$rebroadcastShowStart->add(new DateInterval("P".$rebroadcastWhenDays[0]."D"));
$rebroadcastShowStart->setTime($rebroadcastWhenTime[0], $rebroadcastWhenTime[1]);
$rebroadcastShowStart->setTimezone(new DateTimeZone('UTC'));
$rebroadcastShowEnd = clone $rebroadcastShowStart;
$rebroadcastShowEnd->add(new DateInterval("PT".$hours."H".$minutes."M"));
if ($showEdit) {
$overlapping = Application_Model_Schedule::checkOverlappingShows(
$rebroadcastShowStart, $rebroadcastShowEnd, true, null, $formData['add_show_id']);
@ -368,13 +326,13 @@ class Application_Form_AddShowWhen extends Zend_Form_SubForm
$overlapping = Application_Model_Schedule::checkOverlappingShows(
$rebroadcastShowStart, $rebroadcastShowEnd);
}
if ($overlapping) break;
}
return $overlapping;
}
public function disable()
{
$elements = $this->getElements();

View File

@ -99,9 +99,9 @@ class Application_Form_AddUser extends Zend_Form
"G" => _("Guest"),
"H" => _("DJ"),
"P" => _("Program Manager"),
"A" => _("Admin")
"A" => _("Admin"),
));
$select->setRequired(true);
$select->setRequired(false);
$this->addElement($select);
$saveBtn = new Zend_Form_Element_Button('save_user');

View File

@ -0,0 +1,196 @@
<?php
require_once 'Zend/Locale.php';
class Application_Form_BillingClient extends Zend_Form
{
public function init()
{
/*$this->setDecorators(array(
array('ViewScript', array('viewScript' => 'form/billing-purchase.phtml'))));*/
$client = BillingController::getClientDetails();
$this->setAttrib("id", "clientdetails_form");
$notEmptyValidator = Application_Form_Helper_ValidationTypes::overrideNotEmptyValidator();
$emailValidator = Application_Form_Helper_ValidationTypes::overrideEmailAddressValidator();
$firstname = new Zend_Form_Element_Text('firstname');
$firstname->setLabel(_('First Name:'))
->setValue($client["firstname"])
->setAttrib('class', 'input_text')
->setRequired(true)
->addValidator($notEmptyValidator)
->addFilter('StringTrim');
$this->addElement($firstname);
$lastname = new Zend_Form_Element_Text('lastname');
$lastname->setLabel(_('Last Name:'))
->setValue($client["lastname"])
->setAttrib('class', 'input_text')
->setRequired(true)
->addValidator($notEmptyValidator)
->addFilter('StringTrim');
$this->addElement($lastname);
$companyname = new Zend_Form_Element_Text('companyname');
$companyname->setLabel(_('Company Name:'))
->setValue($client["companyname"])
->setAttrib('class', 'input_text')
->setRequired(false)
->addValidator($notEmptyValidator)
->addFilter('StringTrim');
$this->addElement($companyname);
$email = new Zend_Form_Element_Text('email');
$email->setLabel(_('Email Address:'))
->setValue($client["email"])
->setAttrib('class', 'input_text')
->setRequired(true)
->setAttrib('readonly', 'readonly')
->addValidator($emailValidator)
->addFilter('StringTrim');
$this->addElement($email);
$address1 = new Zend_Form_Element_Text('address1');
$address1->setLabel(_('Address 1:'))
->setValue($client["address1"])
->setAttrib('class', 'input_text')
->setRequired(true)
->addValidator($notEmptyValidator)
->addFilter('StringTrim');
$this->addElement($address1);
$address2 = new Zend_Form_Element_Text('address2');
$address2->setLabel(_('Address 2:'))
->setValue($client["address2"])
->setAttrib('class', 'input_text')
->addFilter('StringTrim');
$this->addElement($address2);
$city = new Zend_Form_Element_Text('city');
$city->setLabel(_('City:'))
->setValue($client["city"])
->setAttrib('class', 'input_text')
->setRequired(true)
->addValidator($notEmptyValidator)
->addFilter('StringTrim');
$this->addElement($city);
//TODO: get list from whmcs?
$state = new Zend_Form_Element_Text('state');
$state->setLabel(_('State/Region:'))
->setValue($client["state"])
->setAttrib('class', 'input_text')
->setRequired(true)
->addValidator($notEmptyValidator)
->addFilter('StringTrim');
$this->addElement($state);
$postcode = new Zend_Form_Element_Text('postcode');
$postcode->setLabel(_('Zip Code / Postal Code:'))
->setValue($client["postcode"])
->setAttrib('class', 'input_text')
->setRequired(true)
->addValidator($notEmptyValidator)
->addFilter('StringTrim');
$this->addElement($postcode);
$locale = new Zend_Locale('en_US');
$countries = $locale->getTranslationList('Territory', 'en', 2);
asort($countries, SORT_LOCALE_STRING);
$country = new Zend_Form_Element_Select('country');
$country->setLabel(_('Country:'))
->setValue($client["country"])
->setAttrib('class', 'input_text')
->setMultiOptions($countries)
->setRequired(true)
->addValidator($notEmptyValidator)
->addFilter('StringTrim');
$this->addElement($country);
$phonenumber = new Zend_Form_Element_Text('phonenumber');
$phonenumber->setLabel(_('Phone Number:'))
->setValue($client["phonenumber"])
->setAttrib('class', 'input_text')
->setRequired(true)
->addValidator($notEmptyValidator)
->addFilter('StringTrim');
$this->addElement($phonenumber);
$securityqid = new Zend_Form_Element_Select('securityqid');
$securityqid->setLabel(_('Please choose a security question:'))
->setValue($client["securityqid"])
->setAttrib('class', 'input_text')
->setRequired(true)
->setMultiOptions(array(
"1" => _("What is the name of your favorite childhood friend?"),
"3" => _("What school did you attend for sixth grade?"),
"4" => _("In what city did you meet your spouse/significant other?"),
"5" => _("What street did you live on in third grade?"),
"6" => _("What is the first name of the boy or girl that you first kissed?"),
"7" => _("In what city or town was your first job?")));
$this->addElement($securityqid);
$securityqans = new Zend_Form_Element_Text('securityqans');
$securityqans->setLabel(_('Please enter an answer:'))
->setValue($client["securityqans"])
->setAttrib('class', 'input_text')
->setRequired(true)
->addValidator($notEmptyValidator)
->addFilter('StringTrim');
$this->addElement($securityqans);
foreach ($client["customfields"] as $field) {
if ($field["id"] == "7") {
$vatvalue = $field["value"];
} elseif ($field["id"] == "71") {
$subscribevalue = $field["value"];
}
}
$vat = new Zend_Form_Element_Text("7");
$vat->setLabel(_('VAT/Tax ID (EU only)'))
->setBelongsTo('customfields')
->setValue($vatvalue)
->setAttrib('class', 'input_text')
//->setRequired(true)
//->addValidator($notEmptyValidator)
->addFilter('StringTrim');
$this->addElement($vat);
$subscribe = new Zend_Form_Element_Checkbox('71');
$subscribe->setLabel(_('Subscribe to Sourcefabric newsletter'))
->setValue($subscribevalue)
->setBelongsTo('customfields')
->setAttrib('class', 'input_text')
->setRequired(true)
->addValidator($notEmptyValidator)
->addFilter('StringTrim');
$this->addElement($subscribe);
$password = new Zend_Form_Element_Password('password2');
$password->setLabel(_('Password:'));
$password->setAttrib('class', 'input_text');
$password->setValue("xxxxxx");
$password->setRequired(true);
$password->addFilter('StringTrim');
$password->addValidator($notEmptyValidator);
$this->addElement($password);
$passwordVerify = new Zend_Form_Element_Password('password2verify');
$passwordVerify->setLabel(_('Verify Password:'));
$passwordVerify->setAttrib('class', 'input_text');
$passwordVerify->setValue("xxxxxx");
$passwordVerify->setRequired(true);
$passwordVerify->addFilter('StringTrim');
//$passwordVerify->addValidator($notEmptyValidator);
$passwordVerify->addValidator('Identical', false, array('token' => 'password2'));
$passwordVerify->addValidator($notEmptyValidator);
$this->addElement($passwordVerify);
$submit = new Zend_Form_Element_Submit("submit");
$submit->setIgnore(true)
->setLabel(_("Save"));
$this->addElement($submit);
}
}

View File

@ -0,0 +1,53 @@
<?php
class Application_Form_BillingUpgradeDowngrade extends Zend_Form
{
public function init()
{
$productPrices = array();
$productTypes = array();
list($productPrices, $productTypes) = BillingController::getProductPricesAndTypes();
$currentPlanProduct = BillingController::getClientCurrentAirtimeProduct();
$currentPlanProductId = $currentPlanProduct["pid"];
$currentPlanProductBillingCycle = $currentPlanProduct["billingcycle"];
$pid = new Zend_Form_Element_Radio('newproductid');
$pid->setLabel(_('Plan type:'))
->setMultiOptions($productTypes)
->setRequired(true)
->setValue($currentPlanProductId);
$this->addElement($pid);
//Logging::info(BillingController::getClientCurrentAirtimeProduct());
$billingcycle = new Zend_Form_Element_Radio('newproductbillingcycle');
$billingCycleOptionMap = array('monthly' => 'Monthly', 'annually' => 'Annually');
if (!array_key_exists($currentPlanProductBillingCycle, $billingCycleOptionMap)) {
$currentPlanProductBillingCycle = 'monthly';
}
$billingcycle->setLabel(_('Billing cycle:'))
->setMultiOptions($billingCycleOptionMap)
->setRequired(true)
->setValue($currentPlanProductBillingCycle);
$this->addElement($billingcycle);
$paymentmethod = new Zend_Form_Element_Radio('paymentmethod');
$paymentmethod->setLabel(_('Payment method:'))
->setRequired(true)
->setMultiOptions(array(
'paypal' => _('PayPal'),
'tco' => _('Credit Card via 2Checkout')))
->setValue('paypal');
$this->addElement($paymentmethod);
/*$submit = new Zend_Form_Element_Submit("submit");
$submit->setIgnore(true)
->setLabel(_("Save"));
$this->addElement($submit);*/
$client = new Application_Form_BillingClient();
$client->removeElement("password2");
$client->removeElement("password2verify");
$this->addSubForm($client, 'billing_client_info');
}
}

View File

@ -42,7 +42,7 @@ class Application_Form_EditUser extends Zend_Form
$login->addFilter('StringTrim');
$login->setDecorators(array('viewHelper'));
$this->addElement($login);
$password = new Zend_Form_Element_Password('cu_password');
$password->setLabel(_('Password:'));
$password->setAttrib('class', 'input_text');
@ -127,6 +127,18 @@ class Application_Form_EditUser extends Zend_Form
$timezone->setValue(Application_Model_Preference::GetUserTimezone($currentUserId));
$timezone->setDecorators(array('ViewHelper'));
$this->addElement($timezone);
if (Application_Model_User::getCurrentUser()->isSuperAdmin()) {
$elemsToDisable = array($password, $passwordVerify, $email, $firstName, $lastName,
$cellPhone, $skype, $jabber);
foreach ($elemsToDisable as $element) {
//$this->_redirect('billing/client');
$element->setAttrib('disabled', 'disabled');
$element->setAttrib('readonly', 'readonly');
$element->setRequired(false);
}
}
}
public function validateLogin($p_login, $p_userId) {

View File

@ -7,7 +7,6 @@ class Application_Form_EmailServerPreferences extends Zend_Form_SubForm
public function init()
{
$this->setDecorators(array(
array('ViewScript', array('viewScript' => 'form/preferences_email_server.phtml'))
));

View File

@ -5,7 +5,6 @@ class Application_Form_GeneralPreferences extends Zend_Form_SubForm
public function init()
{
$notEmptyValidator = Application_Form_Helper_ValidationTypes::overrideNotEmptyValidator();
$rangeValidator = Application_Form_Helper_ValidationTypes::overrideBetweenValidator(0, 59.9);
$this->setDecorators(array(
@ -92,6 +91,20 @@ class Application_Form_GeneralPreferences extends Zend_Form_SubForm
$third_party_api->setValue(Application_Model_Preference::GetAllow3rdPartyApi());
$third_party_api->setDecorators(array('ViewHelper'));
$this->addElement($third_party_api);
//
// Add the description element
$this->addElement('textarea', 'widgetCode', array(
'label' => 'Javascript Code:',
'required' => false,
'readonly' => true,
'style' => 'font-family: Consolas, "Liberation Mono", Courier,
monospace;',
'class' => 'input_text_area',
'value' => self::getWidgetCode(), //$_SERVER["SERVER_NAME"],
'decorators' => array(
'ViewHelper'
)
));
$locale = new Zend_Form_Element_Select("locale");
$locale->setLabel(_("Default Interface Language"));
@ -117,6 +130,42 @@ class Application_Form_GeneralPreferences extends Zend_Form_SubForm
$this->addElement($week_start_day);
}
private static function getWidgetCode() {
$host = $_SERVER['SERVER_NAME'];
$code = <<<CODE
<script src="http://$host/widgets/js/jquery-1.6.1.min.js" type="text/javascript"></script>
<script src="http://$host/widgets/js/jquery-ui-1.8.10.custom.min.js" type="text/javascript"></script>
<script src="http://$host/widgets/js/jquery.showinfo.js" type="text/javascript"></script>
<div id="headerLiveHolder" style="border: 1px solid #999999; padding: 10px;"></div>
<div id="onAirToday"></div>
<div id="scheduleTabs"></div>
<script type="text/javascript">
$(document).ready(function() {
$("#headerLiveHolder").airtimeLiveInfo({
sourceDomain: "http://$host",
updatePeriod: 20 //seconds
});
$("#onAirToday").airtimeShowSchedule({
sourceDomain: "http://$host",
updatePeriod: 5, //seconds
showLimit: 10
});
$("#scheduleTabs").airtimeWeekSchedule({
sourceDomain:"http://$host",
updatePeriod: 600 //seconds
});
});
</script>
CODE;
return $code;
}
private function getWeekStartDays()
{
$days = array(

View File

@ -80,44 +80,6 @@ class Application_Form_LiveStreamingPreferences extends Zend_Form_SubForm
->setDecorators(array('ViewHelper'));
$this->addElement($live_dj_connection_url);
//liquidsoap harbor.input port
$betweenValidator = Application_Form_Helper_ValidationTypes::overrideBetweenValidator(1024, 49151);
$m_port = Application_Model_StreamSetting::getMasterLiveStreamPort();
$master_dj_port = new Zend_Form_Element_Text('master_harbor_input_port');
$master_dj_port->setLabel(_("Master Source Port"))
->setValue($m_port)
->setValidators(array($betweenValidator))
->addValidator('regex', false, array('pattern'=>'/^[0-9]+$/', 'messages'=>array('regexNotMatch'=>_('Only numbers are allowed.'))))
->setDecorators(array('ViewHelper'));
$this->addElement($master_dj_port);
$m_mount = Application_Model_StreamSetting::getMasterLiveStreamMountPoint();
$master_dj_mount = new Zend_Form_Element_Text('master_harbor_input_mount_point');
$master_dj_mount->setLabel(_("Master Source Mount Point"))
->setValue($m_mount)
->setValidators(array(
array('regex', false, array('/^[^ &<>]+$/', 'messages' => _('Invalid character entered')))))
->setDecorators(array('ViewHelper'));
$this->addElement($master_dj_mount);
//liquidsoap harbor.input port
$l_port = Application_Model_StreamSetting::getDjLiveStreamPort();
$live_dj_port = new Zend_Form_Element_Text('dj_harbor_input_port');
$live_dj_port->setLabel(_("Show Source Port"))
->setValue($l_port)
->setValidators(array($betweenValidator))
->addValidator('regex', false, array('pattern'=>'/^[0-9]+$/', 'messages'=>array('regexNotMatch'=>_('Only numbers are allowed.'))))
->setDecorators(array('ViewHelper'));
$this->addElement($live_dj_port);
$l_mount = Application_Model_StreamSetting::getDjLiveStreamMountPoint();
$live_dj_mount = new Zend_Form_Element_Text('dj_harbor_input_mount_point');
$live_dj_mount->setLabel(_("Show Source Mount Point"))
->setValue($l_mount)
->setValidators(array(
array('regex', false, array('/^[^ &<>]+$/', 'messages' => _('Invalid character entered')))))
->setDecorators(array('ViewHelper'));
$this->addElement($live_dj_mount);
// demo only code
if (!$isStreamConfigable) {
$elements = $this->getElements();
@ -145,49 +107,6 @@ class Application_Form_LiveStreamingPreferences extends Zend_Form_SubForm
public function isValid($data)
{
$isValid = parent::isValid($data);
$master_harbor_input_port = $data['master_harbor_input_port'];
$dj_harbor_input_port = $data['dj_harbor_input_port'];
if ($master_harbor_input_port == $dj_harbor_input_port && $master_harbor_input_port != "") {
$element = $this->getElement("dj_harbor_input_port");
$element->addError(_("You cannot use same port as Master DJ port."));
$isValid = false;
}
if ($master_harbor_input_port != "") {
if (is_numeric($master_harbor_input_port)) {
if ($master_harbor_input_port != Application_Model_StreamSetting::getMasterLiveStreamPort()) {
$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
try {
socket_bind($sock, 0, $master_harbor_input_port);
} catch (Exception $e) {
$element = $this->getElement("master_harbor_input_port");
$element->addError(sprintf(_("Port %s is not available"), $master_harbor_input_port));
$isValid = false;
}
socket_close($sock);
}
} else {
$isValid = false;
}
}
if ($dj_harbor_input_port != "") {
if (is_numeric($dj_harbor_input_port)) {
if ($dj_harbor_input_port != Application_Model_StreamSetting::getDjLiveStreamPort()) {
$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
try {
socket_bind($sock, 0, $dj_harbor_input_port);
} catch (Exception $e) {
$element = $this->getElement("dj_harbor_input_port");
$element->addError(sprintf(_("Port %s is not available"), $dj_harbor_input_port));
$isValid = false;
}
socket_close($sock);
}
} else {
$isValid = false;
}
}
return $isValid;
}

View File

@ -2,14 +2,12 @@
class Application_Form_Preferences extends Zend_Form
{
public function init()
{
$baseUrl = Application_Common_OsPath::getBaseDir();
$this->setMethod('post');
$this->setDecorators(array(
array('ViewScript', array('viewScript' => 'form/preferences.phtml'))
));
@ -25,9 +23,6 @@ class Application_Form_Preferences extends Zend_Form
$this->addSubForm($general_pref, 'preferences_general');
$email_pref = new Application_Form_EmailServerPreferences();
$this->addSubForm($email_pref, 'preferences_email_server');
$soundcloud_pref = new Application_Form_SoundcloudPreferences();
$this->addSubForm($soundcloud_pref, 'preferences_soundcloud');

View File

@ -11,16 +11,6 @@ class Application_Form_SoundcloudPreferences extends Zend_Form_SubForm
array('ViewScript', array('viewScript' => 'form/preferences_soundcloud.phtml'))
));
//enable soundcloud uploads
$this->addElement('checkbox', 'UseSoundCloud', array(
'label' => _('Automatically Upload Recorded Shows'),
'required' => false,
'value' => Application_Model_Preference::GetAutoUploadRecordedShowToSoundcloud(),
'decorators' => array(
'ViewHelper'
)
));
//enable soundcloud uploads option
$this->addElement('checkbox', 'UploadToSoundcloudOption', array(
'label' => _('Enable SoundCloud Upload'),

View File

@ -17,28 +17,6 @@ class Application_Form_StreamSetting extends Zend_Form
public function startFrom()
{
$setting = $this->setting;
if (Application_Model_Preference::GetPlanLevel() == 'disabled') {
$output_sound_device = new Zend_Form_Element_Checkbox('output_sound_device');
$output_sound_device->setLabel(_('Hardware Audio Output'))
->setRequired(false)
->setValue(($setting['output_sound_device'] == "true")?1:0)
->setDecorators(array('ViewHelper'));
if (Application_Model_Preference::GetEnableStreamConf() == "false") {
$output_sound_device->setAttrib("readonly", true);
}
$this->addElement($output_sound_device);
$output_types = array("ALSA"=>"ALSA", "AO"=>"AO", "OSS"=>"OSS", "Portaudio"=>"Portaudio", "Pulseaudio"=>"Pulseaudio");
$output_type = new Zend_Form_Element_Select('output_sound_device_type');
$output_type->setLabel(_("Output Type"))
->setMultiOptions($output_types)
->setValue($setting['output_sound_device_type'])
->setDecorators(array('ViewHelper'));
if ($setting['output_sound_device'] != "true") {
$output_type->setAttrib("disabled", "disabled");
}
$this->addElement($output_type);
}
$icecast_vorbis_metadata = new Zend_Form_Element_Checkbox('icecast_vorbis_metadata');
$icecast_vorbis_metadata->setLabel(_('Icecast Vorbis Metadata'))

View File

@ -4,7 +4,6 @@ require_once 'customfilters/ImageSize.php';
class Application_Form_SupportSettings extends Zend_Form
{
public function init()
{
$country_list = Application_Model_Preference::GetCountryList();
@ -128,20 +127,6 @@ class Application_Form_SupportSettings extends Zend_Form
}
$this->addElement($checkboxPublicise);
// text area for sending detail
$this->addElement('textarea', 'SendInfo', array(
'class' => 'sending_textarea',
'required' => false,
'filters' => array('StringTrim'),
'readonly' => true,
'cols' => 61,
'rows' => 5,
'value' => Application_Model_Preference::GetSystemInfo(false, true),
'decorators' => array(
'ViewHelper'
)
));
// checkbox for privacy policy
$checkboxPrivacy = new Zend_Form_Element_Checkbox("Privacy");
$checkboxPrivacy->setLabel(
@ -164,7 +149,6 @@ class Application_Form_SupportSettings extends Zend_Form
public function isValid ($data)
{
$isValid = parent::isValid($data);
if (isset($data["Privacy"])) {
$checkPrivacy = $this->getElement('Privacy');
if ($data["SupportFeedback"] == "1" && $data["Privacy"] != "1") {

View File

@ -92,5 +92,5 @@ Class Application_Form_Helper_ValidationTypes {
return $validator;
}
}

View File

@ -9,6 +9,15 @@
<?php $baseUrl = Application_Common_OsPath::getBaseDir(); ?>
</head>
<body>
<!-- Google Tag Manager -->
<noscript><iframe src="//www.googletagmanager.com/ns.html?id=GTM-55N6NH"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'//www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-55N6NH');</script>
<!-- End Google Tag Manager -->
<?php echo $this->partial('partialviews/trialBox.phtml', array("is_trial"=>$this->isTrial(), "trial_remain"=> $this->trialRemaining())) ?>
<div id="Panel">
@ -24,7 +33,9 @@
<div class="personal-block solo">
<ul>
<li>
<a id="current-user" href=<?php echo $baseUrl . "User/edit-user"?>><span class="name"><?php echo $this->escape($this->loggedInAs()); ?></span></a> | <a href=<?php echo $baseUrl . "Login/logout"?>><?php echo _("Logout")?></a>
<!-- <span class="trial-box-button"><a title="Billing" href=<?php echo $baseUrl . 'billing/upgrade'?>>Upgrade</a></span>&nbsp;-->
<a id="current-user" href=<?php echo $baseUrl . "User/edit-user"?>><span class="name"><?php echo $this->escape($this->loggedInAs()); ?></span></a>
| <a href=<?php echo $baseUrl . "Login/logout"?>><?php echo _("Logout")?></a>
</li>
</ul>
</div>

View File

@ -1038,7 +1038,7 @@ SQL;
{
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
$user = new Application_Model_User($userInfo->id);
$isAdminOrPM = $user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));
$isAdminOrPM = $user->isUserType(array(UTYPE_SUPERADMIN, UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));
// get only the files from the blocks
// we are about to delete

View File

@ -2,30 +2,44 @@
class Cache
{
private function createCacheKey($key, $isUserValue, $userId = null) {
$CC_CONFIG = Config::getConfig();
$a = $CC_CONFIG["apiKey"][0];
if ($isUserValue) {
$cacheKey = "{$key}{$userId}{$a}";
}
else {
$cacheKey = "{$key}{$a}";
}
private function createCacheKey($key, $isUserValue, $userId = null) {
$CC_CONFIG = Config::getConfig();
$a = $CC_CONFIG["apiKey"][0];
if ($isUserValue) {
$cacheKey = "{$key}{$userId}{$a}";
}
else {
$cacheKey = "{$key}{$a}";
}
return $cacheKey;
}
public function store($key, $value, $isUserValue, $userId = null) {
//$cacheKey = self::createCacheKey($key, $userId);
return false; ///apc_store($cacheKey, $value);
}
public function fetch($key, $isUserValue, $userId = null) {
//$cacheKey = self::createCacheKey($key, $isUserValue, $userId);
return false; //apc_fetch($cacheKey);
return $cacheKey;
}
public function store($key, $value, $isUserValue, $userId = null) {
$cacheKey = self::createCacheKey($key, $userId);
//XXX: Disabling APC on SaaS because it turns out we have multiple webservers
// running, which means we have to use a distributed data cache like memcached.
//return apc_store($cacheKey, $value);
return false;
}
public function fetch($key, $isUserValue, $userId = null) {
$cacheKey = self::createCacheKey($key, $isUserValue, $userId);
//XXX: Disabling APC on SaaS because it turns out we have multiple webservers
// running, which means we have to use a distributed data cache like memcached.
//return apc_fetch($cacheKey);
return false;
}
public static function clear()
{
// Disabled on SaaS
// apc_clear_cache('user');
// apc_clear_cache();
}
}

View File

@ -38,10 +38,16 @@ class Application_Model_Locale
} else {
$lang = $locale.'.'.$codeset;
}
putenv("LC_ALL=$lang");
putenv("LANG=$lang");
$res = setlocale(LC_MESSAGES, $lang);
//putenv("LC_ALL=$lang");
//putenv("LANG=$lang");
//Setting the LANGUAGE env var supposedly lets gettext search inside our locale dir even if the system
//doesn't have the particular locale that we want installed. This doesn't actually seem to work though. -- Albert
putenv("LANGUAGE=$locale");
if (setlocale(LC_MESSAGES, $lang) === false)
{
Logging::warn("Your system does not have the " . $lang . " locale installed. Run: sudo locale-gen " . $lang);
}
$domain = 'airtime';
bindtextdomain($domain, '../locale');
textdomain($domain);

View File

@ -987,7 +987,7 @@ SQL;
{
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
$user = new Application_Model_User($userInfo->id);
$isAdminOrPM = $user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));
$isAdminOrPM = $user->isUserType(array(UTYPE_SUPERADMIN, UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));
// get only the files from the playlists
// we are about to delete

View File

@ -6,7 +6,7 @@ class Application_Model_Preference
{
private static function getUserId()
{
{
//pass in true so the check is made with the autoloader
//we need this check because saas calls this function from outside Zend
if (!class_exists("Zend_Auth", true) || !Zend_Auth::getInstance()->hasIdentity()) {
@ -733,11 +733,7 @@ class Application_Model_Preference
$outputArray['NUM_OF_PAST_SHOWS'] = Application_Model_ShowInstance::GetShowInstanceCount(gmdate("Y-m-d H:i:s"));
$outputArray['UNIQUE_ID'] = self::GetUniqueId();
$outputArray['SAAS'] = self::GetPlanLevel();
if ($outputArray['SAAS'] != 'disabled') {
$outputArray['TRIAL_END_DATE'] = self::GetTrialEndingDate();
} else {
$outputArray['TRIAL_END_DATE'] = NULL;
}
$outputArray['TRIAL_END_DATE'] = self::GetTrialEndingDate();
$outputArray['INSTALL_METHOD'] = self::GetInstallMethod();
$outputArray['NUM_OF_STREAMS'] = self::GetNumOfStreams();
$outputArray['STREAM_INFO'] = Application_Model_StreamSetting::getStreamInfoForDataCollection();
@ -763,9 +759,7 @@ class Application_Model_Preference
$outputString .= $key." : FALSE\n";
}
} elseif ($key == "SAAS") {
if (strcmp($out, 'disabled')!=0) {
$outputString .= $key.' : '.$out."\n";
}
$outputString .= $key.' : '.$out."\n";
} else {
$outputString .= $key.' : '.$out."\n";
}
@ -1023,6 +1017,24 @@ class Application_Model_Preference
Logging::warn("Attempting to set client_id to invalid value: $id");
}
}
public static function GetLiveChatEnabled()
{
$liveChat = self::getValue("live_chat", false);
if (is_null($liveChat) || $liveChat == "" || $liveChat == "1") { //Defaults to on
return true;
}
return false;
}
public static function SetLiveChatEnabled($toggle)
{
if (is_bool($toggle)) {
self::setValue("live_chat", $toggle ? "1" : "0");
} else {
Logging::warn("Attempting to set live_chat to invalid value: $toggle. Must be a bool.");
}
}
/* User specific preferences start */

View File

@ -82,8 +82,24 @@ class Application_Model_RabbitMq
public static function SendMessageToAnalyzer($tmpFilePath, $importedStorageDirectory, $originalFilename,
$callbackUrl, $apiKey)
{
$exchange = 'airtime-uploads';
//Hack for Airtime Pro. The RabbitMQ settings for communicating with airtime_analyzer are global
//and shared between all instances on Airtime Pro.
$CC_CONFIG = Config::getConfig();
$devEnv = "production"; //Default
if (array_key_exists("dev_env", $CC_CONFIG)) {
$devEnv = $CC_CONFIG["dev_env"];
}
$config = parse_ini_file("/etc/airtime-saas/rabbitmq-analyzer-" . $devEnv . ".ini", true);
$conn = new AMQPConnection($config["rabbitmq"]["host"],
$config["rabbitmq"]["port"],
$config["rabbitmq"]["user"],
$config["rabbitmq"]["password"],
$config["rabbitmq"]["vhost"]);
$exchange = 'airtime-uploads';
$exchangeType = 'topic';
$queue = 'airtime-uploads';
$autoDeleteExchange = false;
$data['tmp_file_path'] = $tmpFilePath;
$data['import_directory'] = $importedStorageDirectory;
$data['original_filename'] = $originalFilename;
@ -91,6 +107,68 @@ class Application_Model_RabbitMq
$data['api_key'] = $apiKey;
$jsonData = json_encode($data);
self::sendMessage($exchange, 'topic', false, $jsonData, 'airtime-uploads');
//self::sendMessage($exchange, 'topic', false, $jsonData, 'airtime-uploads');
if (!isset($conn)) {
throw new Exception("Cannot connect to RabbitMQ server");
}
$channel = $conn->channel();
$channel->access_request($config["rabbitmq"]["vhost"], false, false,
true, true);
//I'm pretty sure we DON'T want to autodelete ANY exchanges but I'm keeping the code
//the way it is just so I don't accidentally break anything when I add the Analyzer code in. -- Albert, March 13, 2014
$channel->exchange_declare($exchange, $exchangeType, false, true, $autoDeleteExchange);
$msg = new AMQPMessage($jsonData, array('content_type' => 'text/plain'));
$channel->basic_publish($msg, $exchange);
$channel->close();
$conn->close();
}
public static function SendMessageToHaproxyConfigDaemon($md){
$config = parse_ini_file("/etc/airtime-saas/rabbitmq.ini", true);
$conn = new AMQPConnection($config["rabbitmq"]["host"],
$config["rabbitmq"]["port"],
$config["rabbitmq"]["user"],
$config["rabbitmq"]["password"],
$config["rabbitmq"]["vhost"]);
$exchange = $config["rabbitmq"]["queue"];
$queue = $config["rabbitmq"]["queue"];
$ch = $conn->channel();
/*
name: $queue
passive: false
durable: true // the queue will survive server restarts
exclusive: false // the queue can be accessed in other channels
auto_delete: false //the queue won't be deleted once the channel is closed.
*/
$ch->queue_declare($queue, false, true, false, false);
/*
name: $exchange
type: direct
passive: false
durable: true // the exchange will survive server restarts
auto_delete: false //the exchange won't be deleted once the channel is closed.
*/
$ch->exchange_declare($exchange, 'direct', false, true, false);
$ch->queue_bind($queue, $exchange);
$data = json_encode($md).PHP_EOL;
$msg = new AMQPMessage($data, array('content_type' => 'application/json'));
$ch->basic_publish($msg, $exchange);
$ch->close();
$conn->close();
}
}

View File

@ -62,7 +62,14 @@ SQL;
*/
public static function GetPlayOrderRange($utcTimeEnd = null, $showsToRetrieve = 5)
{
// Everything in this function must be done in UTC. You will get a swift kick in the pants if you mess that up.
//Everything in this function must be done in UTC. You will get a swift kick in the pants if you mess that up.
if (!is_int($p_prev) || !is_int($p_next)) {
//must enter integers to specify ranges
Logging::info("Invalid range parameters: $p_prev or $p_next");
return array();
}
// when timeEnd is unspecified, return to the default behaviour - set a range of 48 hours from current time
if (!$utcTimeEnd) {
@ -873,7 +880,7 @@ SQL;
$CC_CONFIG = Config::getConfig();
$utcTimeZone = new DateTimeZone('UTC');
/* if $p_fromDateTime and $p_toDateTime function parameters are null,
then set range * from "now" to "now + 24 hours". */
if (is_null($p_fromDateTime)) {
@ -931,6 +938,7 @@ SQL;
//row is from "file"
$media_id = $item['file_id'];
$storedFile = Application_Model_StoredFile::RecallById($media_id);
$file = $storedFile->getPropelOrm();
$uri = $file->getAbsoluteFilePath();
@ -939,13 +947,13 @@ SQL;
$object_name = $storedFile->getResourceId();
}
self::createFileScheduleEvent($data, $item, $media_id, $uri, $object_name);
}
}
elseif (!is_null($item['stream_id'])) {
//row is type "webstream"
$media_id = $item['stream_id'];
$uri = $item['url'];
self::createStreamScheduleEvent($data, $item, $media_id, $uri);
}
}
else {
throw new Exception("Unknown schedule type: ".print_r($item, true));
}
@ -1021,7 +1029,6 @@ SQL;
$needScheduleUntil->add(new DateInterval("P1D"));
}
Application_Model_Show::createAndFillShowInstancesPastPopulatedUntilDate($needScheduleUntil);
list($range_start, $range_end) = self::getRangeStartAndEnd($p_fromDateTime, $p_toDateTime);
$data = array();

View File

@ -877,11 +877,14 @@ SELECT si1.starts AS starts,
si1.instance_id AS record_id,
si1.show_id AS show_id,
show.name AS name,
show.description AS description,
show.color AS color,
show.background_color AS background_color,
show.image_path AS image_path,
show.linked AS linked,
si1.file_id AS file_id,
si1.id AS instance_id,
si1.description AS instance_description,
si1.created AS created,
si1.last_scheduled AS last_scheduled,
si1.time_filled AS time_filled,
@ -1076,10 +1079,13 @@ SQL;
SELECT si.starts AS start_timestamp,
si.ends AS end_timestamp,
s.name,
s.description,
s.id,
si.id AS instance_id,
si.description AS instance_description,
si.record,
s.url,
s.image_path,
starts,
ends
FROM cc_show_instances si
@ -1211,7 +1217,7 @@ SQL;
$CC_CONFIG = Config::getConfig();
$con = Propel::getConnection();
//TODO, returning starts + ends twice (once with an alias). Unify this after the 2.0 release. --Martin
$sql = <<<SQL
SELECT si.starts AS start_timestamp,
@ -1310,16 +1316,16 @@ SQL;
"id" => $rows[$i]['id'],
"instance_id" => $rows[$i]['instance_id'],
"instance_description" => $rows[$i]['instance_description'],
"name" => $rows[$i]['name'],
"name" => $rows[$i]['name'],
"description" => $rows[$i]['description'],
"url" => $rows[$i]['url'],
"url" => $rows[$i]['url'],
"start_timestamp" => $rows[$i]['start_timestamp'],
"end_timestamp" => $rows[$i]['end_timestamp'],
"starts" => $rows[$i]['starts'],
"ends" => $rows[$i]['ends'],
"record" => $rows[$i]['record'],
"image_path" => $rows[$i]['image_path'],
"type" => "show");
"type" => "show");
break;
}
}
@ -1369,11 +1375,14 @@ SQL;
SELECT si.starts AS start_timestamp,
si.ends AS end_timestamp,
s.name,
s.description,
s.id,
si.id AS instance_id,
si.description AS instance_description,
si.record,
s.url,
starts,
s.image_path,
starts,
ends
FROM cc_show_instances si
LEFT JOIN cc_show s

View File

@ -69,6 +69,13 @@ SQL;
return $show->getDbName();
}
public function getImagePath()
{
$show = CcShowQuery::create()->findPK($this->getShowId());
return $show->getDbImagePath();
}
public function getGenre()
{

View File

@ -375,7 +375,7 @@ SQL;
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
$user = new Application_Model_User($userInfo->id);
$isAdminOrPM = $user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));
$isAdminOrPM = $user->isUserType(array(UTYPE_SUPERADMIN, UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));
if (!$isAdminOrPM && $this->getFileOwnerId() != $user->getId()) {
throw new FileNoPermissionException();
}
@ -972,6 +972,8 @@ SQL;
// Did all the checks for real, now trying to copy
$audio_stor = Application_Common_OsPath::join($stor, "organize",
$originalFilename);
Logging::info($originalFilename);
Logging::info($audio_stor);
$user = Application_Model_User::getCurrentUser();
if (is_null($user)) {
$uid = Application_Model_User::getFirstAdminId();

View File

@ -215,23 +215,25 @@ class Application_Model_Systemstatus
{
$partitions = array();
/* First lets get all the watched directories. Then we can group them
* into the same partitions by comparing the partition sizes. */
$musicDirs = Application_Model_MusicDir::getWatchedDirs();
$musicDirs[] = Application_Model_MusicDir::getStorDir();
//connect to DB and find how much total space user has allocated.
$totalSpace = Application_Model_Preference::GetDiskQuota();
foreach ($musicDirs as $md) {
$totalSpace = disk_total_space($md->getDirectory());
if (!isset($partitions[$totalSpace])) {
$partitions[$totalSpace] = new StdClass;
$partitions[$totalSpace]->totalSpace = $totalSpace;
$partitions[$totalSpace]->totalFreeSpace = disk_free_space($md->getDirectory());
}
$partitions[$totalSpace]->dirs[] = $md->getDirectory();
$usedSpace = Application_Model_Preference::getDiskUsage();
if (empty($usedSpace)) {
$usedSpace = 0;
}
/* $path = $_SERVER['AIRTIME_BASE']."etc/airtime/num_bytes.ini";
$arr = parse_ini_file($path);
$usedSpace = 0;
if ($arr !== false) {
$usedSpace = $arr['num_bytes'];
} */
$partitions[$totalSpace] = new stdClass();
$partitions[$totalSpace]->totalSpace = $totalSpace;
$partitions[$totalSpace]->totalFreeSpace = $totalSpace - $usedSpace;
//Logging::info($partitions[$totalSpace]->totalFreeSpace);
return array_values($partitions);
}
@ -241,7 +243,7 @@ class Application_Model_Systemstatus
$diskInfo = self::GetDiskInfo();
$diskInfo = $diskInfo[0];
$diskUsage = $diskInfo->totalSpace - $diskInfo->totalFreeSpace;
if ($diskUsage >= $diskInfo->totalSpace) {
if ($diskUsage > 0 && $diskUsage >= $diskInfo->totalSpace) {
return true;
}

View File

@ -49,14 +49,20 @@ class Application_Model_User
{
return $this->isUserType(UTYPE_ADMIN);
}
public function isSuperAdmin()
{
return $this->isUserType(UTYPE_SUPERADMIN);
}
public function canSchedule($p_showId)
{
$type = $this->getType();
$result = false;
if ($type === UTYPE_ADMIN ||
$type === UTYPE_PROGRAM_MANAGER ||
if ($this->isAdmin() ||
$this->isSuperAdmin() ||
$this->isPM() ||
self::isHostOfShow($p_showId)) {
$result = true;
}
@ -239,10 +245,14 @@ class Application_Model_User
}
public static function getFirstAdmin() {
$admins = Application_Model_User::getUsersOfType('A');
if (count($admins) > 0) { // found admin => pick first one
return $admins[0];
$superAdmins = Application_Model_User::getUsersOfType('S');
if (count($superAdmins) > 0) { // found superadmin => pick first one
return $superAdmins[0];
} else {
$admins = Application_Model_User::getUsersOfType('A');
if (count($admins) > 0) { // found admin => pick first one
return $admins[0];
}
Logging::warn("Warning. no admins found in database");
return null;
}
@ -324,16 +334,26 @@ class Application_Model_User
$res = Application_Model_Datatables::findEntries($con, $displayColumns, $fromTable, $datatables);
// mark record which is for the current user
foreach ($res['aaData'] as &$record) {
foreach($res['aaData'] as $key => &$record){
if ($record['login'] == $username) {
$record['delete'] = "self";
} else {
$record['delete'] = "";
}
if($record['login'] == 'sourcefabric_admin'){
//arrays in PHP are basically associative arrays that can be iterated in order.
//Deleting an earlier element does not change the keys of elements that come after it. --MK
unset($res['aaData'][$key]);
$res['iTotalDisplayRecords']--;
$res['iTotalRecords']--;
}
$record = array_map('htmlspecialchars', $record);
}
$res['aaData'] = array_values($res['aaData']);
return $res;
}

View File

@ -15,7 +15,7 @@ class CcSubjs extends BaseCcSubjs {
public function isAdminOrPM()
{
return $this->type === UTYPE_ADMIN || $this->type === UTYPE_PROGRAM_MANAGER;
return $this->type === UTYPE_SUPERADMIN || $this->type === UTYPE_ADMIN || $this->type === UTYPE_PROGRAM_MANAGER;
}
public function isHostOfShow($showId)

View File

@ -8,9 +8,10 @@ class Rest_Bootstrap extends Zend_Application_Module_Bootstrap
$router = $front->getRouter();
$restRoute = new Zend_Rest_Route($front, array(), array(
'rest'=> array('media')));
'rest'=> array('media', 'show')));
assert($router->addRoute('rest', $restRoute));
/** MediaController Routes **/
$downloadRoute = new Zend_Controller_Router_Route(
'rest/media/:id/download',
array(
@ -46,5 +47,32 @@ class Rest_Bootstrap extends Zend_Application_Module_Bootstrap
)
);
$router->addRoute('delete-success', $deleteSuccessRoute);
/** ShowController Routes **/
$uploadImageRoute = new Zend_Controller_Router_Route(
'rest/show/:id/upload-image',
array(
'controller' => 'show',
'action' => 'upload-image',
'module' => 'rest'
),
array(
'id' => '\d+'
)
);
$router->addRoute('upload-image', $uploadImageRoute);
$deleteImageRoute = new Zend_Controller_Router_Route(
'rest/show/:id/delete-image',
array(
'controller' => 'show',
'action' => 'delete-image',
'module' => 'rest'
),
array(
'id' => '\d+'
)
);
$router->addRoute('delete-image', $deleteImageRoute);
}
}

View File

@ -24,6 +24,10 @@ class Rest_MediaController extends Zend_Rest_Controller
$ajaxContext = $this->_helper->getHelper('AjaxContext');
$ajaxContext->addActionContext('delete-success', 'json');
// Remove reliance on .phtml files to render requests
$this->_helper->viewRenderer->setNoRender(true);
}
public function indexAction()
@ -96,16 +100,9 @@ class Rest_MediaController extends Zend_Rest_Controller
exec("rm -rf $path");
//update disk_usage value in cc_pref
$musicDir = CcMusicDirsQuery::create()
->filterByType('stor')
->filterByExists(true)
->findOne();
$storPath = $musicDir->getDirectory();
$freeSpace = disk_free_space($storPath);
$totalSpace = disk_total_space($storPath);
Application_Model_Preference::setDiskUsage($totalSpace - $freeSpace);
$storDir = isset($_SERVER['AIRTIME_BASE']) ? $_SERVER['AIRTIME_BASE']."srv/airtime/stor" : "/srv/airtime/stor";
$diskUsage = shell_exec("du -sb $storDir | awk '{print $1}'");
Application_Model_Preference::setDiskUsage($diskUsage);
$this->getResponse()
->setHttpResponseCode(200)
@ -137,6 +134,15 @@ class Rest_MediaController extends Zend_Rest_Controller
public function postAction()
{
/* If the user presents a valid API key, we don't check CSRF tokens.
CSRF tokens are only used for session based authentication.
*/
if(!$this->verifyAPIKey()){
if(!$this->verifyCSRFToken($this->_getParam('csrf_token'))){
return;
}
}
if (!$this->verifyAuth(true, true))
{
return;
@ -316,6 +322,18 @@ class Rest_MediaController extends Zend_Rest_Controller
return $id;
}
private function verifyCSRFToken($token){
$current_namespace = new Zend_Session_Namespace('csrf_namespace');
$observed_csrf_token = $token;
$expected_csrf_token = $current_namespace->authtoken;
if($observed_csrf_token == $expected_csrf_token){
return true;
}else{
return false;
}
}
private function verifyAuth($checkApiKey, $checkSession)
{
// Session takes precedence over API key for now:
@ -342,18 +360,6 @@ class Rest_MediaController extends Zend_Rest_Controller
return false;
}
private function verifyCSRFToken($token){
$current_namespace = new Zend_Session_Namespace('csrf_namespace');
$observed_csrf_token = $token;
$expected_csrf_token = $current_namespace->authtoken;
if($observed_csrf_token == $expected_csrf_token){
return true;
}else{
return false;
}
}
private function verifyAPIKey()
{
//The API key is passed in via HTTP "basic authentication":
@ -461,7 +467,7 @@ class Rest_MediaController extends Zend_Rest_Controller
$tempFilePath = $_FILES['file']['tmp_name'];
$tempFileName = basename($tempFilePath);
//Only accept files with a file extension that we support.
$fileExtension = pathinfo($originalFilename, PATHINFO_EXTENSION);
if (!in_array(strtolower($fileExtension), explode(",", "ogg,mp3,oga,flac,wav,m4a,mp4,opus")))
@ -469,7 +475,7 @@ class Rest_MediaController extends Zend_Rest_Controller
@unlink($tempFilePath);
throw new Exception("Bad file extension.");
}
//TODO: Remove uploadFileAction from ApiController.php **IMPORTANT** - It's used by the recorder daemon...
$storDir = Application_Model_MusicDir::getStorDir();
@ -491,7 +497,7 @@ class Rest_MediaController extends Zend_Rest_Controller
$importedStorageDirectory, basename($originalFilename),
$callbackUrl, $apiKey);
}
private function getOwnerId()
{
try {

View File

@ -0,0 +1,294 @@
<?php
/**
*
* Controller class for handling Show-related functionality.
*
* Changelog:
* 16/09/2014 : v1.0 Created class skeleton, added image upload functionality
* 18/09/2014 : v1.1 Changed auth references to static calls
*
* @author sourcefabric
* @version 1.1
*
*/
$filepath = realpath(__DIR__);
require_once($filepath."/../helpers/RestAuth.php");
class Rest_ShowController extends Zend_Rest_Controller
{
public function init()
{
// Remove layout dependencies
$this->view->layout()->disableLayout();
// Remove reliance on .phtml files to render requests
$this->_helper->viewRenderer->setNoRender(true);
}
/*
* TODO shift functionality from add-show.js and ScheduleController to here,
* and have a referenceable Show object
*/
public function indexAction() {
Logging::info("INDEX action received");
}
public function getAction() {
Logging::info("GET action received");
}
public function putAction() {
Logging::info("PUT action received");
}
public function postAction() {
Logging::info("POST action received");
}
public function deleteAction() {
Logging::info("DELETE action received");
}
public function uploadImageAction()
{
if (!RestAuth::verifyAuth(true, true))
{
$this->getResponse()
->setHttpResponseCode(401)
->appendBody("Authentication failed");
return;
}
$showId = $this->getShowId();
if (!$showId) {
$this->getResponse()
->setHttpResponseCode(400)
->appendBody("No show ID provided");
return;
}
try {
$path = $this->processUploadedImage($showId, $_FILES["file"]["tmp_name"], $_FILES["file"]["name"]);
} catch (Exception $e) {
$this->getResponse()
->setHttpResponseCode(500)
->appendBody("Error processing image: " . $e->getMessage());
}
$show = CcShowQuery::create()->findPk($showId);
try {
$con = Propel::getConnection();
$con->beginTransaction();
$show->setDbImagePath($path);
$show->save();
$con->commit();
} catch (Exception $e) {
$con->rollBack();
$this->getResponse()
->setHttpResponseCode(500)
->appendBody("Couldn't add show image: " . $e->getMessage());
}
$this->getResponse()
->setHttpResponseCode(201);
}
public function deleteImageAction()
{
if (!RestAuth::verifyAuth(true, true))
{
$this->getResponse()
->setHttpResponseCode(401)
->appendBody("Authentication failed");
return;
}
$showId = $this->getShowId();
if (!$showId) {
$this->getResponse()
->setHttpResponseCode(400)
->appendBody("No show ID provided");
return;
}
try {
Rest_ShowController::deleteShowImagesFromStor($showId);
} catch (Exception $e) {
$this->getResponse()
->setHttpResponseCode(500)
->appendBody("Error processing image: " . $e->getMessage());
}
$show = CcShowQuery::create()->findPk($showId);
try {
$con = Propel::getConnection();
$con->beginTransaction();
$show->setDbImagePath(null);
$show->save();
$con->commit();
} catch (Exception $e) {
$con->rollBack();
$this->getResponse()
->setHttpResponseCode(500)
->appendBody("Couldn't remove show image: " . $e->getMessage());
}
$this->getResponse()
->setHttpResponseCode(201);
}
/**
* Verify and process an uploaded image file, copying it into
* .../stor/imported/:owner-id/show-images/:show-id/ to differentiate between
* individual users and shows
*
* @param unknown $tempFilePath
* - temporary filepath assigned to the upload generally of the form /tmp/:tmp_name
* @param unknown
* - $originalFilename the file name at time of upload
* @throws Exception
* - when a file with an unsupported file extension is uploaded or an
* error occurs in copyFileToStor
*/
private function processUploadedImage($showId, $tempFilePath, $originalFilename)
{
$ownerId = RestAuth::getOwnerId();
$CC_CONFIG = Config::getConfig();
$apiKey = $CC_CONFIG["apiKey"][0];
$tempFileName = basename($tempFilePath);
//Only accept files with a file extension that we support.
$fileExtension = $this->getFileExtension($originalFilename, $tempFilePath);
if (!in_array(strtolower($fileExtension), explode(",", "jpg,png,gif,jpeg")))
{
@unlink($tempFilePath);
throw new Exception("Bad file extension.");
}
$storDir = Application_Model_MusicDir::getStorDir();
$importedStorageDirectory = $storDir->getDirectory() . "imported/" . $ownerId . "/show-images/" . $showId;
try {
$importedStorageDirectory = $this->copyFileToStor($tempFilePath, $importedStorageDirectory, $fileExtension);
} catch (Exception $e) {
@unlink($tempFilePath);
throw new Exception("Failed to copy file: " . $e->getMessage());
}
return $importedStorageDirectory;
}
private function getFileExtension($originalFileName, $tempFilePath)
{
// Don't trust the extension - get the MIME-type instead
$fileInfo = finfo_open();
$mime = finfo_file($fileInfo, $tempFilePath, FILEINFO_MIME_TYPE);
return $this->getExtensionFromMime($mime);
}
private function getExtensionFromMime($mime)
{
$extensions = array(
'image/jpeg' => 'jpg',
'image/png' => 'png',
'image/gif' => 'gif'
);
return $extensions[$mime];
}
private function copyFileToStor($tempFilePath, $importedStorageDirectory, $fileExtension)
{
$image_file = $tempFilePath;
// check if show image dir exists and if not, create one
if (!file_exists($importedStorageDirectory)) {
if (!mkdir($importedStorageDirectory, 0777, true)) {
throw new Exception("Failed to create storage directory.");
}
}
if (chmod($image_file, 0644) === false) {
Logging::info("Warning: couldn't change permissions of $image_file to 0644");
}
$newFileName = substr($tempFilePath, strrpos($tempFilePath, "/")).".".$fileExtension;
// Did all the checks for real, now trying to copy
$image_stor = Application_Common_OsPath::join($importedStorageDirectory, $newFileName);
Logging::info("Adding image: " . $image_stor);
Logging::info("copyFileToStor: moving file $image_file to $image_stor");
if (@rename($image_file, $image_stor) === false) {
//something went wrong likely there wasn't enough space in .
//the audio_stor to move the file too warn the user that .
//the file wasn't uploaded and they should check if there .
//is enough disk space .
unlink($image_file); //remove the file after failed rename
throw new Exception("The file was not uploaded, this error can occur if the computer "
."hard drive does not have enough disk space or the stor "
."directory does not have correct write permissions.");
}
return $image_stor;
}
// Should this be an endpoint instead?
public static function deleteShowImagesFromStor($showId) {
$ownerId = RestAuth::getOwnerId();
$storDir = Application_Model_MusicDir::getStorDir();
$importedStorageDirectory = $storDir->getDirectory() . "imported/" . $ownerId . "/show-images/" . $showId;
Logging::info("Deleting images from " . $importedStorageDirectory);
// to be safe in case image uploading functionality is extended later
if (!file_exists($importedStorageDirectory)) {
Logging::info("No uploaded images for show with id " . $showId);
return true;
} else {
return Rest_ShowController::delTree($importedStorageDirectory);
}
}
// from a note @ http://php.net/manual/en/function.rmdir.php
private static function delTree($dir) {
$files = array_diff(scandir($dir), array('.','..'));
foreach ($files as $file) {
(is_dir("$dir/$file")) ? delTree("$dir/$file") : unlink("$dir/$file");
}
return rmdir($dir);
}
/**
* Fetch the id parameter from the request.
*
* @return boolean|unknown false if the show id wasn't
* provided, otherwise returns the id
*/
private function getShowId()
{
if (!$id = $this->_getParam('id', false)) {
$resp = $this->getResponse();
$resp->setHttpResponseCode(400);
$resp->appendBody("ERROR: No show ID specified.");
return false;
}
return $id;
}
}

View File

@ -0,0 +1,64 @@
<?php
class RestAuth
{
public static function verifyAuth($checkApiKey, $checkSession)
{
//Session takes precedence over API key for now:
if ($checkSession && RestAuth::verifySession()
|| $checkApiKey && RestAuth::verifyAPIKey())
{
return true;
}
$resp = $this->getResponse();
$resp->setHttpResponseCode(401);
$resp->appendBody("ERROR: Incorrect API key.");
return false;
}
public static function getOwnerId()
{
try {
if (RestAuth::verifySession()) {
$service_user = new Application_Service_UserService();
return $service_user->getCurrentUser()->getDbId();
} else {
$defaultOwner = CcSubjsQuery::create()
->filterByDbType('A')
->orderByDbId()
->findOne();
if (!$defaultOwner) {
// what to do if there is no admin user?
// should we handle this case?
return null;
}
return $defaultOwner->getDbId();
}
} catch(Exception $e) {
Logging::info($e->getMessage());
}
}
private static function verifySession()
{
$auth = Zend_Auth::getInstance();
return $auth->hasIdentity();
}
private static function verifyAPIKey()
{
//The API key is passed in via HTTP "basic authentication":
// http://en.wikipedia.org/wiki/Basic_access_authentication
$CC_CONFIG = Config::getConfig();
//Decode the API key that was passed to us in the HTTP request.
$authHeader = $this->getRequest()->getHeader("Authorization");
$encodedRequestApiKey = substr($authHeader, strlen("Basic "));
$encodedStoredApiKey = base64_encode($CC_CONFIG["apiKey"][0] . ":");
return ($encodedRequestApiKey === $encodedStoredApiKey);
}
}

View File

@ -9,6 +9,7 @@ class Application_Service_ShowFormService
if (!is_null($showId)) {
$this->ccShow = CcShowQuery::create()->findPk($showId);
}
$this->instanceId = $instanceId;
}
@ -91,6 +92,7 @@ class Application_Service_ShowFormService
* when the user edits a repeating instance
*/
$forms["what"]->makeReadonly();
$forms["what"]->enableInstanceDesc();
$forms["repeats"]->disable();
$forms["who"]->disable();
$forms["style"]->disable();
@ -123,14 +125,17 @@ class Application_Service_ShowFormService
private function populateFormWhat($form)
{
$form->populate(
$ccShowInstance = CcShowInstancesQuery::create()->findPk($this->instanceId);
$form->populate(
array(
'add_show_instance_id' => $this->instanceId,
'add_show_id' => $this->ccShow->getDbId(),
'add_show_name' => $this->ccShow->getDbName(),
'add_show_url' => $this->ccShow->getDbUrl(),
'add_show_genre' => $this->ccShow->getDbGenre(),
'add_show_description' => $this->ccShow->getDbDescription()));
'add_show_description' => $this->ccShow->getDbDescription(),
'add_show_instance_description' => $ccShowInstance->getDbDescription()));
}
private function populateFormWhen($form)
@ -284,10 +289,33 @@ class Application_Service_ShowFormService
private function populateFormStyle($form)
{
$src = $this->ccShow->getDbImagePath() ?
$this->imagePathToDataUri($this->ccShow->getDbImagePath()) : '';
$form->populate(
array(
'add_show_background_color' => $this->ccShow->getDbBackgroundColor(),
'add_show_color' => $this->ccShow->getDbColor()));
'add_show_color' => $this->ccShow->getDbColor(),
'add_show_logo_current' => $src));
}
/**
* Convert a static image from disk to a base64 data URI
*
* @param unknown $path
* - the path to the image on the disk
* @return string
* - the data URI representation of the image
*/
private function imagePathToDataUri($path) {
ob_start();
header("Content-type: image/*");
readfile($path);
$imageData = base64_encode(ob_get_contents());
ob_end_clean();
// return the data URI - data:{mime};base64,{data}
return ($imageData === null || $imageData === '') ?
'' : 'data: '.mime_content_type($path).';base64,'.$imageData;
}
private function populateFormLive($form)
@ -440,7 +468,19 @@ class Application_Service_ShowFormService
$live = $forms["live"]->isValid($formData);
$record = $forms["record"]->isValid($formData);
$who = $forms["who"]->isValid($formData);
/*
* hack to prevent validating the file upload field since it
* isn't passed into $data
*/
$upload = $forms["style"]->getElement("add_show_logo");
$forms["style"]->removeElement("add_show_logo");
$style = $forms["style"]->isValid($formData);
// re-add the upload element
$forms["style"]->addElement($upload);
$when = $forms["when"]->isWhenFormValid($formData, $validateStartDate,
$originalStartDate, $editShow, $instanceId);
@ -478,14 +518,10 @@ class Application_Service_ShowFormService
}
}
if ($what && $live && $record && $who && $style && $when &&
$repeats && $absRebroadcast && $rebroadcast) {
return true;
} else {
return false;
}
return ($what && $live && $record && $who && $style && $when &&
$repeats && $absRebroadcast && $rebroadcast);
}
public function calculateDuration($start, $end, $timezone)
{
try {

View File

@ -141,9 +141,15 @@ class Application_Service_ShowService
$ccShowInstance->updateDbTimeFilled($con);
$ccShowInstance->updateScheduleStatus($con);
$ccShowInstance
->setDbDescription($showData['add_show_instance_description'])
->save();
//delete the edited instance from the repeating sequence
$ccShowInstanceOrig->setDbModifiedInstance(true)->save();
$ccShowInstanceOrig
->setDbModifiedInstance(true)
->setDbDescription($showData['add_show_instance_description'])
->save();
$con->commit();
Application_Model_RabbitMq::PushSchedule();
@ -176,7 +182,7 @@ class Application_Service_ShowService
$this->localShowStartHour = $origStartTime[0];
$this->localShowStartMin = $origStartTime[1];
}
public function addUpdateShow($showData)
{
$service_user = new Application_Service_UserService();
@ -199,6 +205,15 @@ class Application_Service_ShowService
if ($this->isUpdate) {
$showId = $this->ccShow->getDbId();
// Only delete the previous logo if a new one is being uploaded
if (array_key_exists("add_show_logo_name", $showData) && $showData["add_show_logo_name"] !== "") {
if (!Rest_ShowController::deleteShowImagesFromStor($showId)) {
throw new Exception("Error deleting show images");
}
}
if (!$this->ccShow->getCcShowDayss()->isEmpty()) {
$this->storeOrigLocalShowInfo();
}
@ -225,7 +240,7 @@ class Application_Service_ShowService
//update ccShowHosts
$this->setCcShowHosts($showData);
//create new ccShowInstances
$this->delegateInstanceCreation($daysAdded);
@ -251,6 +266,9 @@ class Application_Service_ShowService
Logging::info("EXCEPTION: Show ".$action." failed.");
Logging::info($e->getMessage());
}
// Added to pass along to the RESTful ShowController
return $this->ccShow->getDbId();
}
/**
@ -584,17 +602,17 @@ SQL;
$currentShowEndDateTime = $this->getRepeatingEndDate();
if ($endDateTime && $currentShowEndDateTime != $endDateTime) {
$endDate = clone $endDateTime;
$endDate->setTimezone(new DateTimeZone("UTC"));
$endDate = clone $endDateTime;
$endDate->setTimezone(new DateTimeZone("UTC"));
//show's "No End" option was toggled
//or the end date comes earlier
if (is_null($currentShowEndDateTime) || ($endDateTime < $currentShowEndDateTime)) {
//"No End" option was unchecked so we need to delete the
//repeat instances that are scheduled after the new end date
//OR
//end date was pushed back so we have to delete any
//instances of this show scheduled after the new end date
//end date was pushed back so we have to delete any
//instances of this show scheduled after the new end date
$this->deleteInstancesFromDate($endDate->format("Y-m-d"), $showId);
}
}
@ -641,10 +659,10 @@ SQL;
$date = null;
if ($query !== false && isset($query["last_show"])) {
$date = new DateTime(
$query["last_show"],
new DateTimeZone($query["timezone"])
);
$date = new DateTime(
$query["last_show"],
new DateTimeZone($query["timezone"])
);
}
return $date;
@ -732,6 +750,7 @@ SQL;
$con = Propel::getConnection();
$con->beginTransaction();
try {
if (!$currentUser->isAdminOrPM()) {
throw new Exception("Permission denied");
}
@ -742,7 +761,12 @@ SQL;
throw new Exception("Could not find show instance");
}
// Delete show images
$showId = $ccShowInstance->getDbShowId();
if (!Rest_ShowController::deleteShowImagesFromStor($showId)) {
throw new Exception("Error deleting show images");
}
if ($singleInstance) {
$ccShowInstances = array($ccShowInstance);
} else {
@ -772,7 +796,7 @@ SQL;
return false;
}
}
public function deleteShowInstances($ccShowInstances, $showId)
{
foreach ($ccShowInstances as $ccShowInstance) {
@ -931,23 +955,23 @@ SQL;
*/
private function calculateEndDate($showData)
{
//if no end return null
//if no end return null
if ($showData['add_show_no_end']) {
$endDate = null;
}
//if the show is repeating & ends, then return the end date
elseif ($showData['add_show_repeats']) {
$endDate = new DateTime(
$showData['add_show_end_date'],
new DateTimeZone($showData["add_show_timezone"])
$showData['add_show_end_date'],
new DateTimeZone($showData["add_show_timezone"])
);
$endDate->add(new DateInterval("P1D"));
}
//the show doesn't repeat, so add one day to the start date.
else {
$endDate = new DateTime(
$showData['add_show_start_date'],
new DateTimeZone($showData["add_show_timezone"])
$showData['add_show_start_date'],
new DateTimeZone($showData["add_show_timezone"])
);
$endDate->add(new DateInterval("P1D"));
}
@ -1117,11 +1141,11 @@ SQL;
$repeatInterval, $populateUntil);
if ($last_show) {
$utcLastShowDateTime = new DateTime($last_show, new DateTimeZone($timezone));
$utcLastShowDateTime->setTimezone(new DateTimeZone("UTC"));
$utcLastShowDateTime = new DateTime($last_show, new DateTimeZone($timezone));
$utcLastShowDateTime->setTimezone(new DateTimeZone("UTC"));
}
else {
$utcLastShowDateTime = null;
$utcLastShowDateTime = null;
}
$previousDate = clone $start;
@ -1217,12 +1241,12 @@ SQL;
$this->repeatType = $showDay->getDbRepeatType();
if ($last_show) {
$utcLastShowDateTime = new DateTime($last_show, new DateTimeZone($timezone));
$utcLastShowDateTime->setTimezone(new DateTimeZone("UTC"));
if ($last_show) {
$utcLastShowDateTime = new DateTime($last_show, new DateTimeZone($timezone));
$utcLastShowDateTime->setTimezone(new DateTimeZone("UTC"));
}
else {
$utcLastShowDateTime = null;
$utcLastShowDateTime = null;
}
while ($start->getTimestamp() < $end->getTimestamp()) {
@ -1545,8 +1569,8 @@ SQL;
$showId = $this->ccShow->getDbId();
$startDateTime = new DateTime(
$showData['add_show_start_date']." ".$showData['add_show_start_time'],
new DateTimeZone($showData['add_show_timezone'])
$showData['add_show_start_date']." ".$showData['add_show_start_time'],
new DateTimeZone($showData['add_show_timezone'])
);
$endDateTime = $this->calculateEndDate($showData);
@ -1554,7 +1578,7 @@ SQL;
$endDate = $endDateTime->format("Y-m-d");
}
else {
$endDate = null;
$endDate = null;
}
//Our calculated start DOW must be used for non repeating since a day has not been selected.
@ -1731,7 +1755,7 @@ SQL;
}
}
}
/**
*
* Gets the date and time shows (particularly repeating shows)

View File

@ -0,0 +1,254 @@
<?php
abstract class AirtimeUpgrader
{
/** Versions that this upgrader class can upgrade from (an array of version strings). */
abstract protected function getSupportedVersions();
/** The version that this upgrader class will upgrade to. (returns a version string) */
abstract public function getNewVersion();
public static function getCurrentVersion()
{
CcPrefPeer::clearInstancePool(); //Ensure we don't get a cached Propel object (cached DB results)
//because we're updating this version number within this HTTP request as well.
$pref = CcPrefQuery::create()
->filterByKeystr('system_version')
->findOne();
$airtime_version = $pref->getValStr();
return $airtime_version;
}
/**
* This function checks to see if this class can perform an upgrade of your version of Airtime
* @return boolean True if we can upgrade your version of Airtime.
*/
public function checkIfUpgradeSupported()
{
if (!in_array(AirtimeUpgrader::getCurrentVersion(), $this->getSupportedVersions())) {
return false;
}
return true;
}
protected function toggleMaintenanceScreen($toggle)
{
if ($toggle)
{
//Disable Airtime UI
//create a temporary maintenance notification file
//when this file is on the server, zend framework redirects all
//requests to the maintenance page and sets a 503 response code
$this->maintenanceFile = isset($_SERVER['AIRTIME_BASE']) ? $_SERVER['AIRTIME_BASE']."maintenance.txt" : "/tmp/maintenance.txt";
$file = fopen($this->maintenanceFile, 'w');
fclose($file);
} else {
//delete maintenance.txt to give users access back to Airtime
if ($this->maintenanceFile) {
unlink($this->maintenanceFile);
}
}
}
/** Implement this for each new version of Airtime */
abstract public function upgrade();
}
class AirtimeUpgrader253 extends AirtimeUpgrader
{
protected function getSupportedVersions()
{
return array('2.5.1', '2.5.2');
}
public function getNewVersion()
{
return '2.5.3';
}
public function upgrade($dir = __DIR__)
{
Cache::clear();
assert($this->checkIfUpgradeSupported());
$con = Propel::getConnection();
$con->beginTransaction();
try {
$this->toggleMaintenanceScreen(true);
Cache::clear();
//Begin upgrade
//Update disk_usage value in cc_pref
$musicDir = CcMusicDirsQuery::create()
->filterByType('stor')
->filterByExists(true)
->findOne();
$storPath = $musicDir->getDirectory();
//Update disk_usage value in cc_pref
$storDir = isset($_SERVER['AIRTIME_BASE']) ? $_SERVER['AIRTIME_BASE']."srv/airtime/stor" : "/srv/airtime/stor";
$diskUsage = shell_exec("du -sb $storDir | awk '{print $1}'");
Application_Model_Preference::setDiskUsage($diskUsage);
//clear out the cache
Cache::clear();
$con->commit();
//update system_version in cc_pref and change some columns in cc_files
$airtimeConf = isset($_SERVER['AIRTIME_CONF']) ? $_SERVER['AIRTIME_CONF'] : "/etc/airtime/airtime.conf";
$values = parse_ini_file($airtimeConf, true);
$username = $values['database']['dbuser'];
$password = $values['database']['dbpass'];
$host = $values['database']['host'];
$database = $values['database']['dbname'];
passthru("export PGPASSWORD=$password && psql -h $host -U $username -q -f $dir/upgrade_sql/airtime_".$this->getNewVersion()."/upgrade.sql $database 2>&1 | grep -v \"will create implicit index\"");
Application_Model_Preference::SetAirtimeVersion($this->getNewVersion());
//clear out the cache
Cache::clear();
$this->toggleMaintenanceScreen(false);
} catch (Exception $e) {
$con->rollback();
$this->toggleMaintenanceScreen(false);
}
}
}
class AirtimeUpgrader254 extends AirtimeUpgrader
{
protected function getSupportedVersions()
{
return array('2.5.3');
}
public function getNewVersion()
{
return '2.5.4';
}
public function upgrade()
{
Cache::clear();
assert($this->checkIfUpgradeSupported());
$newVersion = $this->getNewVersion();
$con = Propel::getConnection();
//$con->beginTransaction();
try {
$this->toggleMaintenanceScreen(true);
Cache::clear();
//Begin upgrade
//First, ensure there are no superadmins already.
$numberOfSuperAdmins = CcSubjsQuery::create()
->filterByDbType(UTYPE_SUPERADMIN)
->filterByDbLogin("sourcefabric_admin", Criteria::NOT_EQUAL) //Ignore sourcefabric_admin users
->count();
//Only create a super admin if there isn't one already.
if ($numberOfSuperAdmins == 0)
{
//Find the "admin" user and promote them to superadmin.
$adminUser = CcSubjsQuery::create()
->filterByDbLogin('admin')
->findOne();
if (!$adminUser)
{
//TODO: Otherwise get the user with the lowest ID that is of type administrator:
//
$adminUser = CcSubjsQuery::create()
->filterByDbType(UTYPE_ADMIN)
->orderByDbId(Criteria::ASC)
->findOne();
if (!$adminUser) {
throw new Exception("Failed to find any users of type 'admin' ('A').");
}
}
$adminUser = new Application_Model_User($adminUser->getDbId());
$adminUser->setType(UTYPE_SUPERADMIN);
$adminUser->save();
Logging::info($_SERVER['HTTP_HOST'] . ': ' . $newVersion . " Upgrade: Promoted user " . $adminUser->getLogin() . " to be a Super Admin.");
//Also try to promote the sourcefabric_admin user
$sofabAdminUser = CcSubjsQuery::create()
->filterByDbLogin('sourcefabric_admin')
->findOne();
if ($sofabAdminUser) {
$sofabAdminUser = new Application_Model_User($sofabAdminUser->getDbId());
$sofabAdminUser->setType(UTYPE_SUPERADMIN);
$sofabAdminUser->save();
Logging::info($_SERVER['HTTP_HOST'] . ': ' . $newVersion . " Upgrade: Promoted user " . $sofabAdminUser->getLogin() . " to be a Super Admin.");
}
}
//$con->commit();
Application_Model_Preference::SetAirtimeVersion($newVersion);
Cache::clear();
$this->toggleMaintenanceScreen(false);
return true;
} catch(Exception $e) {
//$con->rollback();
$this->toggleMaintenanceScreen(false);
throw $e;
}
}
}
class AirtimeUpgrader255 extends AirtimeUpgrader {
protected function getSupportedVersions() {
return array (
'2.5.4'
);
}
public function getNewVersion() {
return '2.5.5';
}
public function upgrade($dir = __DIR__) {
Cache::clear();
assert($this->checkIfUpgradeSupported());
$newVersion = $this->getNewVersion();
try {
$this->toggleMaintenanceScreen(true);
Cache::clear();
// Begin upgrade
$airtimeConf = isset($_SERVER['AIRTIME_CONF']) ? $_SERVER['AIRTIME_CONF'] : "/etc/airtime/airtime.conf";
$values = parse_ini_file($airtimeConf, true);
$username = $values['database']['dbuser'];
$password = $values['database']['dbpass'];
$host = $values['database']['host'];
$database = $values['database']['dbname'];
passthru("export PGPASSWORD=$password && psql -h $host -U $username -q -f $dir/upgrade_sql/airtime_"
.$this->getNewVersion()."/upgrade.sql $database 2>&1 | grep -v \"will create implicit index\"");
Application_Model_Preference::SetAirtimeVersion($newVersion);
Cache::clear();
$this->toggleMaintenanceScreen(false);
return true;
} catch(Exception $e) {
$this->toggleMaintenanceScreen(false);
throw $e;
}
}
}

View File

@ -3,10 +3,6 @@
class Airtime_View_Helper_IsTrial extends Zend_View_Helper_Abstract{
public function isTrial(){
$plan = Application_Model_Preference::GetPlanLevel();
if($plan == 'trial'){
return true;
}else{
return false;
}
return $plan == 'trial';
}
}
}

View File

@ -12,46 +12,6 @@
class Airtime_View_Helper_VersionNotify extends Zend_View_Helper_Abstract{
public function versionNotify(){
if(Application_Model_Preference::GetPlanLevel() != 'disabled'){
return "";
}
// retrieve and validate current and latest versions,
$current = Application_Model_Preference::GetAirtimeVersion();
$latest = Application_Model_Preference::GetLatestVersion();
$link = Application_Model_Preference::GetLatestLink();
$currentExploded = explode('.', $current);
$latestExploded = explode('.', $latest);
if(count($currentExploded) != 3 || count($latestExploded) != 3) {
return "";
}
// Calculate the version difference;
// Example: if current = 1.9.5 and latest = 3.0.0, diff = 105
// Note: algorithm assumes the number after 1st dot never goes above 9
$versionDifference = (intval($latestExploded[0]) * 100 + intval($latestExploded[1]) *10 + intval($latestExploded[2]))
- (intval($currentExploded[0]) * 100 + intval($currentExploded[1] *10 + intval($currentExploded[2])));
// Pick icon based on distance this version is to the latest version available
if($versionDifference <= 0) {
// current version is up to date or newer
$class = "uptodate";
} else if($versionDifference < 20) {
// 2 or less major versions back
$class = "update";
} else if($versionDifference < 30) {
// 3 major versions back
$class = "update2";
} else {
// more than 3 major versions back
$class = "outdated";
}
$result = "<div id='version-diff' style='display:none'>" . $versionDifference . "</div>"
. "<div id='version-current' style='display:none'>" . $current . "</div>"
. "<div id='version-latest' style='display:none'>" . $latest . "</div>"
. "<div id='version-link' style='display:none'>" . $link . "</div>"
. "<div id='version-icon' class='" . $class . "'></div>";
return $result;
return "";
}
}

View File

@ -0,0 +1,15 @@
<?php
$this->form->getElement("submit")->setAttrib("class", "right-align");
$this->form->getElement("country")->setAttrib("class", "right-align");
$this->form->getElement("securityqid")->setAttrib("class", "right-align");
?>
<div class="ui-widget ui-widget-content block-shadow clearfix padded-strong billing-panel">
<H2>Billing Account Details</H2>
<?php if (isset($this->errorMessage)) {?>
<div class="errors"><?php echo $this->errorMessage ?></div>
<?php } else if (isset($this->successMessage)) {?>
<div class="success"><?php echo $this->successMessage ?></div>
<?php }?>
<?php echo $this->form ?>
</div>

View File

@ -0,0 +1 @@
test

View File

@ -0,0 +1,34 @@
<div class="ui-widget ui-widget-content block-shadow clearfix padded-strong billing-panel">
<H2>Invoices</H2>
<?php
$topTextClass = "";
if (array_key_exists("planupdated", $_GET))
{
$topText = _("<b>Thank you!</b> Your plan has been updated and you will be invoiced during your next billing cycle.");
$topTextClass = "status-good";
}
else {
$topText = _("Tip: To pay an invoice, click \"View Invoice\"<br> and look for the \"Checkout\" button.");
}
?>
<p style="text-align: center; padding-left: 20px;" class="<?=$topTextClass?>"><?=$topText?></p>
<table id="invoices_table">
<tr class="header">
<th>Date Issued</th>
<th>Due Date</th>
<th>Link</th>
<th>Status</th>
</tr>
<?php
foreach ($this->invoices as $invoice) {?>
<tr>
<td><?php echo $invoice["date"]?></td>
<td><?php echo $invoice["duedate"]?></td>
<td><a href="invoice?invoiceid=<?php echo $invoice["id"]?>">View Invoice</a></td>
<td class="<?=$invoice["status"]==="Unpaid" ? "unpaid" : "";?>"><?php echo $invoice["status"]?></td>
</tr>
<?php };?>
</table>
</div>

View File

@ -0,0 +1,370 @@
<?php
$form = $this->form;
$form->setAttrib('id', 'upgrade-downgrade');
?>
<script type="text/javascript">
<?php echo("var products = " . json_encode(BillingController::getProducts()) . ";\n");
echo("var vatRate = " . json_encode(VAT_RATE) . ";");
?>
var vatFieldId = "#customfields-7";
var validVATNumber = false;
var customerInEU = false;
//Disable annual billing for hobbyist plan
function validatePlan()
{
if ($("#newproductid-25").is(":checked")) {
$("#newproductbillingcycle-monthly").attr("checked", "true");
//It's import that we switch the checked item first (because you can't disable a checked radio button in Chrome)
$("#newproductbillingcycle-annually").attr("disabled", "disabled");
$("label[for='newproductbillingcycle-annually']").addClass("disabled");
} else {
$("#newproductbillingcycle-annually").removeAttr("disabled");
$("label[for='newproductbillingcycle-annually']").removeClass("disabled");
}
}
function validateVATNumber()
{
$.post("/billing/vat-validator", { "vatnumber" : $(vatFieldId).val(), "country" : $("#country").val() })
.success(function(data, textStatus, jqXHR) {
if (data["result"]) {
$("#vaterror").html("&#10003; Your VAT number is valid.");
window.validVATNumber = true;
} else {
$("#vaterror").text("Error: Your VAT number is invalid.");
window.validVATNumber = false;
}
recalculateTotals();
});
}
/* Recalculate subtotal and total */
function recalculateTotals()
{
var newProductId = $("input[type='radio'][name='newproductid']:checked");
if (newProductId.length > 0) {
newProductId = newProductId.val();
} else {
return;
}
var newProduct = null;
for (var i = 0; i < products.length; i++)
{
if (products[i].pid == newProductId) {
newProduct = products[i];
break;
}
}
/** This calculation is all done on the server side too inside WHMCS so don't waste your time
trying to hax0r it to get cheap Airtime Pro. */
var subtotal = "0";
var savings = "0";
var subtotalNumber = "0";
var billingPeriodString = "";
if ($("#newproductbillingcycle-monthly").is(":checked")) {
billingPeriodString = " per month";
subtotalNumber = newProduct.pricing["USD"]["monthly"];
subtotal = "$" + subtotalNumber + billingPeriodString;
$("#savings").text("");
} else if ($("#newproductbillingcycle-annually").is(":checked")) {
subtotalNumber = newProduct.pricing["USD"]["annually"];
billingPeriodString = " per year";
subtotal = "$" + subtotalNumber + billingPeriodString;
savings = "$" + (newProduct.pricing["USD"]["monthly"]*12 - subtotalNumber).toFixed(2);
$("#savings").html("You save: " + savings + " per year");
}
$("#subtotal").text(subtotal);
//Calculate total:
var vatAmount = 0;
if (window.customerInEU && !window.validVATNumber) {
vatAmount = (parseFloat(subtotalNumber) * vatRate)/100.00;
}
var total = (vatAmount + parseFloat(subtotalNumber)).toFixed(2);
$(".subtotal").text(subtotal);
if (vatAmount > 0) {
$("#tax").text("Plus VAT at " + parseInt(vatRate) + "%: $" + vatAmount.toFixed(2) + billingPeriodString);
} else {
$("#tax").text("");
}
$("#total").text("$" + total + billingPeriodString);
}
function configureByCountry(countryCode)
{
//Disable the VAT tax field if the country is not in the EU.
$.post("/billing/is-country-in-eu", { "country" : countryCode })
.success(function(data, textStatus, jqXHR) {
if (data["result"]) {
$(vatFieldId).prop("disabled", false);
$(vatFieldId).prop("readonly", false);
$(vatFieldId + "-label").removeClass("disabled");
$("#vat_disclaimer2").fadeIn(300);
window.customerInEU = true;
} else {
$(vatFieldId).prop("disabled", true);
$(vatFieldId).prop("readonly", true);
$(vatFieldId).val("");
$(vatFieldId + "-label").addClass("disabled");
$("#vat_disclaimer2").fadeOut(0);
window.customerInEU = false;
}
recalculateTotals();
});
}
$(document).ready(function() {
configureByCountry($("#country").val());
recalculateTotals();
$("input[name='newproductid']").change(function() {
validatePlan();
recalculateTotals();
});
$("input[name='newproductbillingcycle']").change(function() {
recalculateTotals();
});
$("#country").change(function() {
configureByCountry($(this).val());
});
vatFieldChangeTimer = null;
$(vatFieldId).change(function() {
$("#vaterror").text("Please wait, checking VAT number...");
if (vatFieldChangeTimer) {
clearTimeout(vatFieldChangeTimer);
}
if ($(this).val() == "") {
$("#vaterror").text("");
window.validVATNumber = false;
recalculateTotals();
return;
}
vatFieldChangeTimer = setTimeout(function() {
validateVATNumber(); //Validate and recalculate the totals
}, 1500); //Wait 1.5 seconds before validating the VAT number
});
//We don't assume the VAT number we have in the database is valid.
//Let's force it to be rechecked and the total to be recalculated when the page loads.
validateVATNumber();
$("#hobbyist_grid_price").text("$" + products[0].pricing["USD"]["monthly"] + " / month");
$("#starter_grid_price").text("$" + products[1].pricing["USD"]["monthly"] + " / month");
$("#plus_grid_price").text("$" + products[2].pricing["USD"]["monthly"] + " / month");
$("#premium_grid_price").text("$" + products[3].pricing["USD"]["monthly"] + " / month");
});
</script>
<div class="ui-widget ui-widget-content block-shadow clearfix padded-strong billing-panel">
<H2><?=_("Account Plans")?></H2>
<H4><?=_("Upgrade today to get more listeners and storage space!")?></H4>
<div class="pricing-grid">
<table>
<tr>
<th>Hobbyist</th>
<th>Starter</th>
<th>Plus</th>
<th>Premium</th>
</tr>
<tr>
<td>1 Stream
</td>
<td>2 Streams
</td>
<td>2 Streams
</td>
<td>3 Streams
</td>
</tr>
<tr>
<td>64kbps Stream Quality
</td>
<td>64kbps and 128kbps Stream Quality
</td>
<td>64kbps and 196kbps Stream Quality
</td>
<td>64kbps, 128kbps, and 196kbps Stream Quality
</td>
</tr>
<tr>
<td>5 Listeners
</td>
<td>40 Listeners per stream
</td>
<td>100 Listeners per stream
</td>
<td>500 Listeners per stream
</td>
</tr>
<tr>
<td>2GB Storage
</td>
<td>5GB Storage
</td>
<td>30GB Storage
</td>
<td>150GB Storage
</td>
</tr>
<tr>
<td>Ticket, Email, Forum Support
</td>
<td>Live Chat, Ticket, Email, Forum Support
</td>
<td>Live Chat, Ticket, Email, Forum Support
</td>
<td>Live Chat, Ticket, Email, Forum Support
</td>
</tr>
<tr>
<td>
</td>
<td>Save 15% if paid annually
</td>
<td>Save 15% if paid annually
</td>
<td>Save 15% if paid annually
</td>
</tr>
<tr class="price">
<td id="hobbyist_grid_price">
</td>
<td id="starter_grid_price">
</td>
<td id="plus_grid_price">
</td>
<td id="premium_grid_price">
</td>
</tr>
</table>
</div>
<!--
<p> <a target="_blank" href="https://www.airtime.pro/pricing"><?=_("View Plans")?></a> (Opens in a new window)</p>
-->
<p id="current_plan"><b>Current Plan:</b>
<?php
$currentProduct = BillingController::getClientCurrentAirtimeProduct();
echo($currentProduct["name"]);
//echo Application_Model_Preference::GetPlanLevel();
?>
</p>
<h3>Choose a plan:</h3>
<form id="<?php echo $form->getId(); ?>" method="<?php echo $form->getMethod() ?>" action="<?php echo
$form->getAction()?>" enctype="<?php echo $form->getEncType();?>">
<div id="plantype">
<?php echo $form->newproductid ?>
</div>
<div id="billingcycle">
<?php echo $form->newproductbillingcycle ?>
</div>
<div id="billingcycle_disclaimer">
Save 15% on annual plans (Hobbyist plan excluded).
</div>
<div class="clearfix"></div>
<div id="subtotal_box">
<b>Subtotal:</b><br>
<span class="subtotal"></span><br>
<div id="savings"></div>
</div>
<div id="vat_disclaimer">
VAT will be added below if you are an EU resident without a valid VAT number.
</div>
<h3>Enter your payment details:</h3>
<?php if (isset($this->errorMessage)) {?>
<div class="errors"><?php echo $this->errorMessage ?></div>
<?php }?>
<?php //echo $form ?>
<?php $billingForm = $form->getSubform("billing_client_info") ?>
<div class="billing_col1">
<?=$billingForm->firstname?>
</div>
<div class="billing_col2">
<?=$billingForm->lastname?>
</div>
<div class="clearfix"></div>
<div class="billing_col1">
<?=$billingForm->companyname?>
</div>
<div class="billing_col2">
<?=$billingForm->email?>
</div>
<div class="clearfix"></div>
<div class="billing_col1">
<?=$billingForm->address1?>
</div>
<div class="billing_col2">
<?=$billingForm->address2?>
</div>
<div class="clearfix"></div>
<div class="billing_col1">
<?=$billingForm->city?>
</div>
<div class="billing_col2">
<?=$billingForm->state?>
</div>
<div class="clearfix"></div>
<div>
<?=$billingForm->postcode?>
</div>
<div>
<?=$billingForm->country?>
</div>
<div>
<?=$billingForm->phonenumber?>
</div>
<div>
<?=$billingForm->securityqid?>
</div>
<div>
<?=$billingForm->securityqans?>
</div>
<div id="vat_disclaimer2"><p>VAT will be added to your invoice if you are an EU resident without a valid company VAT number.</p>
</div>
<div>
<?=$billingForm->getElement("7"); ?>
<div id="vaterror"></div>
</div>
<div class="clearfix"></div>
<div>
<div class="billing_checkbox">
<?=$billingForm->getElement("71")->renderViewHelper(); ?>
</div>
<?=$billingForm->getElement("71")->renderLabel(); ?>
</div>
<div class="clearfix"></div>
<div style="float:right; width: 200px;"><p>After submitting your order, you will be redirected to an invoice with payment buttons.</p>
</div>
<div id="paymentmethod">
<?php echo $form->paymentmethod ?>
</div>
<div class="clearfix"></div>
<div id="total_box">
<b>Subtotal:</b> <span class="subtotal"></span><br>
<span id="tax"></span><br>
<b>Total:</b> <span id="total"></span>
</div>
<input type="submit" value="Submit Order" id="atpro_submitorder"></input>
<div class="clearfix"></div>
</form>
</div>

View File

@ -1,5 +1,14 @@
<h2><?php echo sprintf(_("%s's Settings"), $this->escape($this->currentUser)) ?></h2>
<div id="current-user-container">
<?php if(Application_Model_User::getCurrentUser()->isSuperAdmin()) : ?>
<div class="user-data" id="user_details_superadmin_message" style="text-align: center;">
<?=sprintf(_("<b>Note:</b> You are a special \"Super Admin\" type of user.<br>Account details for Super Admins can be changed in your <a href=\"%s\">Billing Settings</a> instead."), "/billing/client");?>
<br><br>
</div>
<?php endif; ?>
<form id="current-user-form" class="edit-user-global" method="post" enctype="application/x-www-form-urlencoded">
<dl class="zend_form">
<?php echo $this->element->getElement('cu_user_id') ?>
@ -157,10 +166,8 @@
</ul>
<?php endif; ?>
</dd>
<?php echo $this->element->getElement('csrf') ?>
<button type="submit" id="cu_save_user" class="btn btn-small right-floated"><?php echo _("Save")?></button>
</dl>
<button type="submit" id="cu_save_user" class="btn btn-small right-floated"><?php echo _("Save")?></button>
</form>
</div>

View File

@ -1,14 +1,8 @@
<form method="<?php echo $this->element->getMethod() ?>" enctype="multipart/form-data">
<?php echo $this->element->getElement('csrf') ?>
<?php echo $this->element->getSubform('preferences_general') ?>
<h3 class="collapsible-header" id="email-server-heading"><span class="arrow-icon"></span><?php echo _("Email / Mail Server Settings"); ?></h3>
<div class="collapsible-content" id="email-server-settings">
<?php echo $this->element->getSubform('preferences_email_server') ?>
</div>
<h3 class="collapsible-header" id="soundcloud-heading"><span class="arrow-icon"></span><?php echo _("SoundCloud Settings") ?></h3>
<h3 class="collapsible-header" id="soundcloud-heading"><span class="arrow-icon"></span><? echo _("SoundCloud Settings") ?></h3>
<div class="collapsible-content" id="soundcloud-settings">
<?php echo $this->element->getSubform('preferences_soundcloud') ?>
</div>

View File

@ -1,106 +1,5 @@
<fieldset class="padded">
<dl class="zend_form">
<!-- Enable System Email option -->
<dd id="enableSystemEmail-element" class="block-display">
<label class="required" for="timezone">
<?php echo $this->element->getElement('enableSystemEmail') ?>
<strong><?php echo $this->element->getElement('enableSystemEmail')->getLabel() ?></strong>
</label>
<?php if($this->element->getElement('enableSystemEmail')->hasErrors()) : ?>
<ul class='errors'>
<?php foreach($this->element->getElement('enableSystemEmail')->getMessages() as $error): ?>
<li><?php echo $error; ?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
</dd>
<!-- System Email option -->
<dt id="systemEmail-label" class="block-display">
<label class="required" for="timezone"><?php echo $this->element->getElement('systemEmail')->getLabel() ?>:
</label>
</dt>
<dd id="systemEmail-element" class="block-display">
<?php echo $this->element->getElement('systemEmail') ?>
<?php if($this->element->getElement('systemEmail')->hasErrors()) : ?>
<ul class='errors'>
<?php foreach($this->element->getElement('systemEmail')->getMessages() as $error): ?>
<li><?php echo $error; ?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
</dd>
<br />
<dd id="configureMailServer-element" class="block-display">
<label class="required" for="configureMailServer">
<?php echo $this->element->getElement('configureMailServer') ?>
<strong><?php echo $this->element->getElement('configureMailServer')->getLabel() ?></strong>
</label>
</dd>
<dt id="mailServer-label" class="block-display">
<label class="required" for="mailServer"><?php echo $this->element->getElement('mailServer')->getLabel() ?>
<span class="info-text-small"><?php echo _("(Required)") ?></span>:
</label>
<label class="required" for="msRequiresAuth">
<?php echo $this->element->getElement('msRequiresAuth') ?>
<?php echo $this->element->getElement('msRequiresAuth')->getLabel() ?>
</label>
</dt>
<dd id="mailServer-element" class="block-display">
<?php echo $this->element->getElement('mailServer') ?>
<?php if($this->element->getElement('mailServer')->hasErrors()) : ?>
<ul class='errors'>
<?php foreach($this->element->getElement('mailServer')->getMessages() as $error): ?>
<li><?php echo $error; ?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
</dd>
<dt id="port-label" class="block-display">
<label class="required" for="port"><?php echo $this->element->getElement('port')->getLabel() ?>:
</label>
</dt>
<dd id="port-element" class="block-display">
<?php echo $this->element->getElement('port') ?>
</dd>
<dt id="email-label" class="block-display">
<label class="required" for="email"><?php echo $this->element->getElement('email')->getLabel() ?>
<span class="info-text-small"><?php echo _("(Required)") ?></span>:
</label>
</dt>
<dd id="email-element" class="block-display">
<?php echo $this->element->getElement('email') ?>
<?php if($this->element->getElement('email')->hasErrors()) : ?>
<ul class='errors'>
<?php foreach($this->element->getElement('email')->getMessages() as $error): ?>
<li><?php echo $error; ?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
</dd>
<dt id="password-label" class="block-display">
<label class="required" for="password"><?php echo $this->element->getElement('ms_password')->getLabel() ?>
<span class="info-text-small"><?php echo _("(Required)") ?></span>:
</label>
</dt>
<dd id="password-element" class="block-display">
<?php echo $this->element->getElement('ms_password') ?>
<?php if($this->element->getElement('ms_password')->hasErrors()) : ?>
<ul class='errors'>
<?php foreach($this->element->getElement('ms_password')->getMessages() as $error): ?>
<li><?php echo $error; ?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
</dd>
</dl>
</fieldset>

View File

@ -54,12 +54,17 @@
<?php endif; ?>
</dd>
<dt id="thirdPartyApi-label" class="block-display">
<label class="optional"><?php echo $this->element->getElement('thirdPartyApi')->getLabel() ?></label>
<label class="optional"><?php echo $this->element->getElement('thirdPartyApi')->getLabel() ?>
<span class="icecast_metadata_help_icon" id="thirdPartyApiInfo"></span>
</label>
</dt>
<dd id="thirdPartyApi-element" class="block-display radio-inline-list">
<?php $i=0;
$value = $this->element->getElement('thirdPartyApi')->getValue();
?>
<?php foreach ($this->element->getElement('thirdPartyApi')->getMultiOptions() as $radio) : ?>
<label for="thirdPartyApi-<?php echo $i ?>">
<input type="radio" value="<?php echo $i ?>" id="thirdPartyApi-<?php echo $i ?>" name="thirdPartyApi" <?php if($i == $value){echo 'checked="checked"';}?>>
@ -77,6 +82,19 @@
<?php endif; ?>
</dd>
<dt id="widgetCode-label" style="display:none;" class="block-display">
<label class="optional" for="widgetCode"><?php echo $this->element->getElement('widgetCode')->getLabel() ?></label>
</dt>
<dd id="widgetCode-element" style="display:none;" class="block-display clearfix">
<?php echo $this->element->getElement('widgetCode') ?>
<?php if($this->element->getElement('widgetCode')->hasErrors()) : ?>
<ul class='errors'>
<?php foreach($this->element->getElement('widgetCode')->getMessages() as $error): ?>
<li><?php echo $error; ?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
</dd>
<dt id="locale-label" class="block-display">
<label class="required" for="locale"><?php echo $this->element->getElement('locale')->getLabel() ?>:
</label>

View File

@ -15,7 +15,7 @@
<li><?php echo $error; ?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
<?php endif; ?>
</dd>
<dt id="auto_switch-label">
<label class="optional" for="auto_transition"><?php echo $this->element->getElement('auto_switch')->getLabel() ?> :
@ -31,7 +31,7 @@
<li><?php echo $error; ?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
<?php endif; ?>
</dd>
<dt id="transition_fade-label">
<label class="optional" for="transition_fade"><?php echo $this->element->getElement('transition_fade')->getLabel() ?> :
@ -45,7 +45,7 @@
<li><?php echo $error; ?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
<?php endif; ?>
</dd>
<dt id="master_username-label">
<label class="optional" for="master_username"><?php echo $this->element->getElement('master_username')->getLabel() ?> :
@ -60,7 +60,7 @@
<li><?php echo $error; ?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
<?php endif; ?>
</dd>
<dt id="master_password-label">
<label class="optional" for="master_password"><?php echo $this->element->getElement('master_password')->getLabel() ?> :
@ -74,36 +74,8 @@
<li><?php echo $error; ?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
<?php endif; ?>
</dd>
<dt id="master_harbor_input_port-label">
<label class="optional" for="master_harbor_input_port"><?php echo $this->element->getElement('master_harbor_input_port')->getLabel() ?> :
</label>
</dt>
<dd id="master_harbor_input_port-element">
<?php echo $this->element->getElement('master_harbor_input_port') ?>
<?php if($this->element->getElement('master_harbor_input_port')->hasErrors()) : ?>
<ul class='errors'>
<?php foreach($this->element->getElement('master_harbor_input_port')->getMessages() as $error): ?>
<li><?php echo $error; ?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
</dd>
<dt id="master_harbor_input_mount_point-label">
<label class="optional" for="master_harbor_input_mount_point"><?php echo $this->element->getElement('master_harbor_input_mount_point')->getLabel() ?> :
</label>
</dt>
<dd id="master_harbor_input_mount_point-element">
<?php echo $this->element->getElement('master_harbor_input_mount_point') ?>
<?php if($this->element->getElement('master_harbor_input_mount_point')->hasErrors()) : ?>
<ul class='errors'>
<?php foreach($this->element->getElement('master_harbor_input_mount_point')->getMessages() as $error): ?>
<li><?php echo $error; ?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
</dd>
<dt id="master_dj_connection_url-label">
<label class="optional" for="master_dj_connection_url" style="white-space: nowrap">
<?php echo _("Master Source Connection URL:")?>
@ -111,43 +83,10 @@
</dt>
<dd id="master_dj_connection_url-element">
<span id="stream_url"><?php echo $this->element->getElement('master_dj_connection_url')->setValue($this->master_dj_connection_url) ?></span>
<?php if(!$this->isDemo){?>
<a href=# id="connection_url_override" style="font-size: 12px;"><?php echo _("Override") ?></a>&nbsp;&nbsp;
<span class="override_help_icon">
</span><br>
<?php } ?>
<div id="master_dj_connection_url_actions" style="display:none">
<a href=# id="ok" style="font-size: 12px;"><?php echo _("OK") ?></a> <a href=# id="reset" style="font-size: 12px;"><?php echo _("RESET"); ?></a>
</div>
</dd>
<dt id="dj_harbor_input_port-label">
<label class="optional" for="dj_harbor_input_port"><?php echo $this->element->getElement('dj_harbor_input_port')->getLabel() ?> :
</label>
</dt>
<dd id="dj_harbor_input_port-element">
<?php echo $this->element->getElement('dj_harbor_input_port') ?>
<?php if($this->element->getElement('dj_harbor_input_port')->hasErrors()) : ?>
<ul class='errors'>
<?php foreach($this->element->getElement('dj_harbor_input_port')->getMessages() as $error): ?>
<li><?php echo $error; ?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
</dd>
<dt id="dj_harbor_input_mount_point-label">
<label class="optional" for="dj_harbor_input_mount_point"><?php echo $this->element->getElement('dj_harbor_input_mount_point')->getLabel() ?> :
</label>
</dt>
<dd id="dj_harbor_input_mount_point-element">
<?php echo $this->element->getElement('dj_harbor_input_mount_point') ?>
<?php if($this->element->getElement('dj_harbor_input_mount_point')->hasErrors()) : ?>
<ul class='errors'>
<?php foreach($this->element->getElement('dj_harbor_input_mount_point')->getMessages() as $error): ?>
<li><?php echo $error; ?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
</dd>
<dt id="live_dj_connection_url-label">
<label class="optional" for="live_dj_connection_url" style="white-space: nowrap">
<?php echo _("Show Source Connection URL:")?>
@ -155,11 +94,6 @@
</dt>
<dd id="live_dj_connection_url-element">
<span id="stream_url"><?php echo $this->element->getElement('live_dj_connection_url')->setValue($this->live_dj_connection_url) ?></span>
<?php if( !$this->isDemo ){?>
<a href=# id="connection_url_override" style="font-size: 12px;"><?php echo _("Override") ?></a>&nbsp;&nbsp;
<span class="override_help_icon">
</span><br>
<?php } ?>
<div id="live_dj_connection_url_actions" style="display:none">
<a href=# id="ok" style="font-size: 12px;"><?php echo _("OK") ?></a> <a href=# id="reset" style="font-size: 12px;"><?php echo _("RESET"); ?></a>
</div>

View File

@ -13,19 +13,6 @@
</ul>
<?php endif; ?>
</dd>
<dd id="UseSoundCloud-element" class="block-display" style="padding-left:20px; margin:6px 0 10px 0">
<label class="optional" for="UseSoundCloud">
<?php echo $this->element->getElement('UseSoundCloud') ?>
<strong><?php echo $this->element->getElement('UseSoundCloud')->getLabel() ?></strong>
</label>
<?php if($this->element->getElement('UseSoundCloud')->hasErrors()) : ?>
<ul class='errors'>
<?php foreach($this->element->getElement('UseSoundCloud')->getMessages() as $error): ?>
<li><?php echo $error; ?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
</dd>
<dd id="SoundCloudDownloadbleOption-element" class="block-display" style="padding-left:20px; margin:6px 0 10px 0">
<label class="optional" for="SoundCloudDownloadbleOption">
<?php echo $this->element->getElement('SoundCloudDownloadbleOption') ?>

View File

@ -1,46 +1,5 @@
<fieldset class="padded">
<dl class="zend_form">
<dd id="SupportFeedback-element" style="width:90%;">
<div class="info-text">
<?php echo sprintf(_("Help Airtime improve by letting Sourcefabric know how you are using it. This information"
." will be collected regularly in order to enhance your user experience.%s"
."Click the 'Send support feedback' box and we'll make sure the features you use are constantly improving."), "<br />")?>
</div>
<label class="optional" for="SupportFeedback">
<?php echo $this->element->getElement('SupportFeedback') ?>
<strong><?php echo $this->element->getElement('SupportFeedback')->getLabel() ?></strong>
</label>
<?php if($this->element->getElement('SupportFeedback')->hasErrors()) : ?>
<ul class='errors'>
<?php foreach($this->element->getElement('SupportFeedback')->getMessages() as $error): ?>
<li><?php echo $error; ?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
</dd>
<dd id="publicize-element" style="width:90%;">
<div class="info-text">
<?php echo sprintf(_("Click the box below to promote your station on %sSourcefabric.org%s."),
"<a id='link_to_whos_using' href='http://www.sourcefabric.org/en/airtime/whosusing/' onclick='window.open(this.href); return false'>",
"</a>")?>
</div>
<label class="optional" for="Publicise">
<?php echo $this->element->getElement('Publicise') ?>
<strong><?php echo $this->element->getElement('Publicise')->getLabel() ?></strong>
</label>
<?php if($this->element->getElement('Publicise')->hasErrors()) : ?>
<ul class='errors'>
<?php foreach($this->element->getElement('Publicise')->getMessages() as $error): ?>
<li><?php echo $error; ?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
</dd>
</dl>
<div class="info-text" style="clear: both;padding: 4px 0 4px 15px;">
<?php echo _("(In order to promote your station, 'Send support feedback' must be enabled).")?><br /><br />
</div>
<dl id="public-info" style="display:<?php echo "none"?>;">
<dl id="public-info" style="display:<?php echo "block"?>;">
<dt id="stationName-label" class="block-display">
<label class="required" for="stationName"><?php echo $this->element->getElement('stationName')->getLabel() ?>
<span class="info-text-small"><?php echo _("(Required)")?></span>:
@ -68,7 +27,7 @@
<li><?php echo $error; ?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
<?php endif; ?>
</dd>
<dt id="Email-label" class="block-display">
<label class="optional" for="Email"><?php echo $this->element->getElement('Email')->getLabel() ?></label>
@ -84,7 +43,7 @@
<li><?php echo $error; ?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
<?php endif; ?>
</dd>
<dt id="StationWebSite-label" class="block-display">
<label class="optional" for="StationWebSite"><?php echo $this->element->getElement('StationWebSite')->getLabel() ?></label>
@ -145,7 +104,7 @@
<?php if($this->element->getView()->logoImg){?>
<div id="Logo-img-container"><img id="logo-img" onload='resizeImg(this, 450, 450);' src="data:image/png;base64,<?php echo $this->element->getView()->logoImg ?>" /></div>
<?php }?>
<?php echo $this->element->getElement('Logo') ?>
<div class="info-text">
<p><?php echo _("Note: Anything larger than 600x600 will be resized.")?></p>
@ -159,31 +118,4 @@
<?php endif; ?>
</dd>
</dl>
<div id="show_what_sending" style="display: block;">
<fieldset class="display_field toggle closed">
<legend style="cursor: pointer;"><span class="ui-icon ui-icon-triangle-2-n-s"></span><?php echo _("Show me what I am sending ") ?></legend>
<dl>
<?php echo $this->element->getElement('SendInfo') ?>
</dl>
</fieldset>
</div>
<div>
<br>
<?php if(!$this->element->getView()->privacyChecked){?>
<label class="optional" for="Privacy">
<?php echo $this->element->getElement('Privacy') ?>
<?php echo $this->element->getElement('Privacy')->getLabel() ?>
</label>
<?php if($this->element->getElement('Privacy')->hasErrors()) : ?>
<ul class='errors'>
<?php foreach($this->element->getElement('Privacy')->getMessages() as $error): ?>
<li><?php echo $error; ?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
<?php }else{?>
<a id="link_to_terms_and_condition" href="http://www.sourcefabric.org/en/about/policy/" onclick="window.open(this.href); return false;"><?php echo _("Sourcefabric Privacy Policy") ?></a>
<?php }?>
</div>
</fieldset>

View File

@ -7,8 +7,14 @@
<span class="down"><?php echo _($page->getLabel()); ?></span>
</a>
<ul class="sub">
<?php foreach ($page->getPages() as $sub) : ?>
<?php foreach ($page->getPages() as $sub) :
if($sub->getId() == "manage_folder"){
continue;
} ?>
<?php if($this->navigation()->accept($sub)) : ?>
<li>
<a href="<?php echo $sub->getHref(); ?>" <?php echo ($sub->getTarget() != "")?"target=\"".$sub->getTarget()."\"":""; ?>><?php echo _($sub->getLabel()); ?></a>
</li>

View File

@ -6,7 +6,7 @@
<div class="trial-box-calendar-gray"><?php echo _("days") ?></div>
</div>
<div class="trial-box-button">
<a title="<?php echo _("Purchase your copy of Airtime")?> href="https://account.sourcefabric.com/clientarea.php" target="_blank"><?php echo _("My Account") ?></a>
<a title="<?php echo _("Purchase an Airtime Pro plan!")?>" href="/billing/upgrade"><?php echo _("My Account") ?></a>
</div>
</div>
<?php }?>

View File

@ -2,7 +2,6 @@
#plupload_files input[type="file"] {
font-size: 200px !important;
}
<<<<<<< HEAD
</style>
<?php if ($this->quotaLimitReached) { ?>
<div class="errors quota-reached">

View File

@ -20,12 +20,6 @@
<div id="live-stream-override" class="collapsible-content">
<?php echo $this->live; ?>
</div>
<h3 class="collapsible-header"><span class="arrow-icon"></span><?php echo _("Record & Rebroadcast")?></h3>
<div id="schedule-record-rebroadcast" class="collapsible-content">
<?php echo $this->rr; ?>
<?php echo $this->absoluteRebroadcast; ?>
<?php echo $this->rebroadcast; ?>
</div>
<h3 class="collapsible-header"><span class="arrow-icon"></span><?php echo _("Who") ?></h3>
<div id="schedule-show-who" class="collapsible-content">
<?php echo $this->who; ?>

View File

@ -26,6 +26,9 @@
</table>
</div>
</div>
<div class="user-data" id="user_details_superadmin_message" style="display: none; margin-top: 105px; text-align: center;">
<?=sprintf(_("Super Admin details can be changed in your <a href=\"%s\">Billing Settings</a>."), "/billing/client");?>
</div>
<div class="user-data simple-formblock" id="user_details">
<?php echo $this->successMessage ?>
<fieldset class="padded">

View File

@ -1,6 +1,6 @@
#Note: project.home is automatically generated by the propel-install script.
#Any manual changes to this value will be overwritten.
project.home = /home/ubuntu/airtime/airtime_mvc
project.home = /home/sourcefabric/dev/Airtime-SaaS/Airtime/airtime_mvc
project.build = ${project.home}/build
#Database driver

View File

@ -148,9 +148,13 @@
<column name="is_linkable" phpName="DbIsLinkable" type="BOOLEAN" required="true" defaultValue="true" />
<!-- A show is_linkable if it has never been linked before. Once a show becomes unlinked
it can not be linked again -->
<column name="image_path" phpName="DbImagePath" type="VARCHAR" size="255" required="false" defaultValue=""/>
<!-- Fully qualified path for the image associated with this show.
Default is /path/to/stor/dir/:ownerId/show-images/:showId/imageName -->
</table>
<table name="cc_show_instances" phpName="CcShowInstances">
<column name="id" phpName="DbId" type="INTEGER" primaryKey="true" autoIncrement="true" required="true"/>
<column name="description" phpName="DbDescription" type="VARCHAR" size="512" required="false" defaultValue=""/>
<column name="starts" phpName="DbStarts" type="TIMESTAMP" required="true"/>
<column name="ends" phpName="DbEnds" type="TIMESTAMP" required="true"/>
<column name="show_id" phpName="DbShowId" type="INTEGER" required="true"/>

View File

@ -143,23 +143,29 @@ DROP TABLE IF EXISTS "cc_show" CASCADE;
CREATE TABLE "cc_show"
(
"id" serial NOT NULL,
"name" VARCHAR(255) DEFAULT '' NOT NULL,
"url" VARCHAR(255) DEFAULT '',
"genre" VARCHAR(255) DEFAULT '',
"description" VARCHAR(512),
"color" VARCHAR(6),
"background_color" VARCHAR(6),
"live_stream_using_airtime_auth" BOOLEAN DEFAULT 'f',
"live_stream_using_custom_auth" BOOLEAN DEFAULT 'f',
"live_stream_user" VARCHAR(255),
"live_stream_pass" VARCHAR(255),
"linked" BOOLEAN DEFAULT 'f' NOT NULL,
"is_linkable" BOOLEAN DEFAULT 't' NOT NULL,
PRIMARY KEY ("id")
"id" serial NOT NULL,
"name" VARCHAR(255) default '' NOT NULL,
"url" VARCHAR(255) default '',
"genre" VARCHAR(255) default '',
"description" VARCHAR(512),
"color" VARCHAR(6),
"background_color" VARCHAR(6),
"live_stream_using_airtime_auth" BOOLEAN default 'f',
"live_stream_using_custom_auth" BOOLEAN default 'f',
"live_stream_user" VARCHAR(255),
"live_stream_pass" VARCHAR(255),
"linked" BOOLEAN default 'f' NOT NULL,
"is_linkable" BOOLEAN default 't' NOT NULL,
"image_path" VARCHAR(255),
PRIMARY KEY ("id")
);
-----------------------------------------------------------------------
COMMENT ON TABLE "cc_show" IS '';
SET search_path TO public;
-----------------------------------------------------------------------------
-- cc_show_instances
-----------------------------------------------------------------------
@ -167,22 +173,28 @@ DROP TABLE IF EXISTS "cc_show_instances" CASCADE;
CREATE TABLE "cc_show_instances"
(
"id" serial NOT NULL,
"starts" TIMESTAMP NOT NULL,
"ends" TIMESTAMP NOT NULL,
"show_id" INTEGER NOT NULL,
"record" INT2 DEFAULT 0,
"rebroadcast" INT2 DEFAULT 0,
"instance_id" INTEGER,
"file_id" INTEGER,
"time_filled" interval DEFAULT '00:00:00',
"created" TIMESTAMP NOT NULL,
"last_scheduled" TIMESTAMP,
"modified_instance" BOOLEAN DEFAULT 'f' NOT NULL,
PRIMARY KEY ("id")
"id" serial NOT NULL,
"description" VARCHAR(512),
"starts" TIMESTAMP NOT NULL,
"ends" TIMESTAMP NOT NULL,
"show_id" INTEGER NOT NULL,
"record" INT2 default 0,
"rebroadcast" INT2 default 0,
"instance_id" INTEGER,
"file_id" INTEGER,
"time_filled" interval default '00:00:00',
"created" TIMESTAMP NOT NULL,
"last_scheduled" TIMESTAMP,
"modified_instance" BOOLEAN default 'f' NOT NULL,
PRIMARY KEY ("id")
);
-----------------------------------------------------------------------
COMMENT ON TABLE "cc_show_instances" IS '';
SET search_path TO public;
-----------------------------------------------------------------------------
-- cc_show_days
-----------------------------------------------------------------------
@ -603,6 +615,7 @@ CREATE TABLE "cc_listener_count"
PRIMARY KEY ("id")
);
<<<<<<< HEAD
-----------------------------------------------------------------------
-- cc_locale
-----------------------------------------------------------------------
@ -618,6 +631,13 @@ CREATE TABLE "cc_locale"
);
-----------------------------------------------------------------------
=======
COMMENT ON TABLE "cc_listener_count" IS '';
SET search_path TO public;
-----------------------------------------------------------------------------
>>>>>>> saas
-- cc_playout_history
-----------------------------------------------------------------------

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More