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

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 '';