From 598b18b65a0bdd068f9f5f231e8bc30874f5928c Mon Sep 17 00:00:00 2001 From: Duncan Sommerville Date: Fri, 24 Oct 2014 15:11:27 -0400 Subject: [PATCH 1/7] Added live-info-v2 and station metadata api calls --- airtime_mvc/application/common/DateHelper.php | 192 ++++++--- airtime_mvc/application/common/OsPath.php | 13 + .../application/controllers/ApiController.php | 371 ++++++++++++++---- airtime_mvc/application/models/Schedule.php | 92 +++-- airtime_mvc/application/models/Show.php | 222 ++++++++--- 5 files changed, 669 insertions(+), 221 deletions(-) diff --git a/airtime_mvc/application/common/DateHelper.php b/airtime_mvc/application/common/DateHelper.php index 07ef3bd18..ba280d285 100644 --- a/airtime_mvc/application/common/DateHelper.php +++ b/airtime_mvc/application/common/DateHelper.php @@ -70,18 +70,18 @@ class Application_Common_DateHelper public static function getUserTimezoneOffset() { - $userTimezone = new DateTimeZone(Application_Model_Preference::GetUserTimezone()); - $now = new DateTime("now", $userTimezone); - - return $now->format("Z"); + $userTimezone = new DateTimeZone(Application_Model_Preference::GetUserTimezone()); + $now = new DateTime("now", $userTimezone); + + return $now->format("Z"); } public static function getStationTimezoneOffset() { - $stationTimezone = new DateTimeZone(Application_Model_Preference::GetDefaultTimezone()); - $now = new DateTime("now", $stationTimezone); - - return $now->format("Z"); + $stationTimezone = new DateTimeZone(Application_Model_Preference::GetDefaultTimezone()); + $now = new DateTime("now", $stationTimezone); + + return $now->format("Z"); } /** @@ -90,12 +90,12 @@ class Application_Common_DateHelper */ public static function getTodayStationStartDateTime() { - $stationTimezone = new DateTimeZone(Application_Model_Preference::GetDefaultTimezone()); - $now = new DateTime("now", $stationTimezone); - - $now->setTime(0, 0, 0); - - return $now; + $stationTimezone = new DateTimeZone(Application_Model_Preference::GetDefaultTimezone()); + $now = new DateTime("now", $stationTimezone); + + $now->setTime(0, 0, 0); + + return $now; } /** @@ -104,13 +104,13 @@ class Application_Common_DateHelper */ public static function getTodayStationEndDateTime() { - $stationTimezone = new DateTimeZone(Application_Model_Preference::GetDefaultTimezone()); - $now = new DateTime("now", $stationTimezone); - - $now->add(new DateInterval("P1D")); - $now->setTime(0, 0, 0); - - return $now; + $stationTimezone = new DateTimeZone(Application_Model_Preference::GetDefaultTimezone()); + $now = new DateTime("now", $stationTimezone); + + $now->add(new DateInterval("P1D")); + $now->setTime(0, 0, 0); + + return $now; } /** @@ -119,17 +119,17 @@ class Application_Common_DateHelper */ public static function getWeekStartDateTime() { - $now = self::getTodayStationStartDateTime(); - + $now = self::getTodayStationStartDateTime(); + // our week starts on monday, but php week starts on sunday. $day = $now->format('w'); if ($day == 0) { - $day = 7; + $day = 7; } $dayDiff = $day - 1; if ($dayDiff > 0) { - $now->sub(new DateInterval("P{$dayDiff}D")); + $now->sub(new DateInterval("P{$dayDiff}D")); } return $now; @@ -250,13 +250,13 @@ class Application_Common_DateHelper * @return string in $format default Y-m-d H:i:s in station timezone */ public static function UTCStringToStationTimezoneString($datetime, $format="Y-m-d H:i:s") { - $stationTimezone = new DateTimeZone(Application_Model_Preference::GetDefaultTimezone()); - $utcTimezone = new DateTimeZone("UTC"); - - $d = new DateTime($datetime, $utcTimezone); - $d->setTimezone($stationTimezone); - - return $d->format($format); + $stationTimezone = new DateTimeZone(Application_Model_Preference::GetDefaultTimezone()); + $utcTimezone = new DateTimeZone("UTC"); + + $d = new DateTime($datetime, $utcTimezone); + $d->setTimezone($stationTimezone); + + return $d->format($format); } /* @@ -265,13 +265,13 @@ class Application_Common_DateHelper * @return string Y-m-d H:i:s in user's timezone */ public static function UTCStringToUserTimezoneString($datetime, $format="Y-m-d H:i:s") { - $userTimezone = new DateTimeZone(Application_Model_Preference::GetUserTimezone()); - $utcTimezone = new DateTimeZone("UTC"); - - $d = new DateTime($datetime, $utcTimezone); - $d->setTimezone($userTimezone); - - return $d->format($format); + $userTimezone = new DateTimeZone(Application_Model_Preference::GetUserTimezone()); + $utcTimezone = new DateTimeZone("UTC"); + + $d = new DateTime($datetime, $utcTimezone); + $d->setTimezone($userTimezone); + + return $d->format($format); } /* @@ -280,13 +280,13 @@ class Application_Common_DateHelper * @return string Y-m-d H:i:s in UTC timezone */ public static function UserTimezoneStringToUTCString($datetime, $format="Y-m-d H:i:s") { - $userTimezone = new DateTimeZone(Application_Model_Preference::GetUserTimezone()); - $utcTimezone = new DateTimeZone("UTC"); - - $d = new DateTime($datetime, $userTimezone); - $d->setTimezone($utcTimezone); + $userTimezone = new DateTimeZone(Application_Model_Preference::GetUserTimezone()); + $utcTimezone = new DateTimeZone("UTC"); + + $d = new DateTime($datetime, $userTimezone); + $d->setTimezone($utcTimezone); - return $d->format($format); + return $d->format($format); } /** @@ -299,19 +299,99 @@ class Application_Common_DateHelper */ public static function convertTimestamps(&$rows, $columnsToConvert, $domain="station") { - if (!is_array($rows)) { - return; - } - - $converter = "UTCStringTo".ucfirst($domain)."TimezoneString"; - - foreach ($rows as &$row) { - foreach ($columnsToConvert as $column) { - $row[$column] = self::$converter($row[$column]); - } - } + if (!is_array($rows)) { + return; + } + + $converter = "UTCStringTo".ucfirst($domain)."TimezoneString"; + + foreach ($rows as &$row) { + foreach ($columnsToConvert as $column) { + $row[$column] = self::$converter($row[$column]); + } + } } + /** + * Convert the columns given in the array $columnsToConvert in the + * database result $rows to local timezone. + * + * @param array $rows arrays of arrays containing database query result + * @param array $columnsToConvert array of column names to convert + * @param string $timezone convert to the given timezone. + * @param string $format time format to convert to + */ + public static function convertTimestampsToTimezone(&$rows, $columnsToConvert, $timezone, $format="Y-m-d H:i:s") + { + $timezone = strtolower($timezone); + // Check that the timezone is valid and rows is an array + if (!is_array($rows)) { + return; + } + + foreach ($rows as &$row) { + if (is_array($row)) { + foreach ($columnsToConvert as $column) { + if (array_key_exists($column, $row)) { + $newTimezone = new DateTimeZone($timezone); + $utcTimezone = new DateTimeZone("UTC"); + + $d = new DateTime($row[$column], $utcTimezone); + $d->setTimezone($newTimezone); + $row[$column] = $d->format($format); + } + } + self::convertTimestampsToTimezone($row, $columnsToConvert, $timezone, $format); + } + } + } + + /** + * Return the end date time in the given timezone + * + * @return DateTime + */ + public static function getEndDateTime($timezoneString, $days) + { + $timezone = new DateTimeZone($timezoneString); + $now = new DateTime("now", $timezone); + + $now->add(new DateInterval("P".$days."D")); + $now->setTime(0, 0, 0); + + return $now; + } + + /** + * Return a formatted string representing the + * given datetime in the given timezone + * + * @param unknown $datetime the time to convert + * @param unknown $timezone the timezone to convert to + * @param string $format the formatted string + */ + public static function UTCStringToTimezoneString($datetime, $timezone, $format="Y-m-d H:i:s") { + $d = new DateTime($datetime, new DateTimeZone("UTC")); + $timezone = strtolower($timezone); + $newTimezone = new DateTimeZone($timezone); + $d->setTimezone($newTimezone); + + return $d->format($format); + } + + /** + * Return the timezone offset in seconds for the given timezone + * + * @param unknown $userDefinedTimezone the timezone used to determine the offset + */ + public static function getTimezoneOffset($userDefinedTimezone) { + $now = new DateTimeZone($userDefinedTimezone); + + $d = new DateTime("now", $now); + return $d->format("Z"); + } + + /** * This function is used for calculations! Don't modify for display purposes! * diff --git a/airtime_mvc/application/common/OsPath.php b/airtime_mvc/application/common/OsPath.php index f052187ba..0921b773e 100644 --- a/airtime_mvc/application/common/OsPath.php +++ b/airtime_mvc/application/common/OsPath.php @@ -80,4 +80,17 @@ class Application_Common_OsPath{ return $baseUrl; } + + public static function formatDirectoryWithDirectorySeparators($dir) + { + if ($dir[0] != "/") { + $dir = "/".$dir; + } + + if ($dir[strlen($dir) -1] != "/") { + $dir = $dir."/"; + } + + return $dir; + } } diff --git a/airtime_mvc/application/controllers/ApiController.php b/airtime_mvc/application/controllers/ApiController.php index 4ce7a5583..4001f7d50 100644 --- a/airtime_mvc/application/controllers/ApiController.php +++ b/airtime_mvc/application/controllers/ApiController.php @@ -5,7 +5,8 @@ class ApiController extends Zend_Controller_Action public function init() { - $ignoreAuth = array("live-info", "week-info"); + $ignoreAuth = array("live-info", "live-info-v2", "week-info", + "station-metadata", "station-logo"); $params = $this->getRequest()->getParams(); if (!in_array($params['action'], $ignoreAuth)) { @@ -245,77 +246,198 @@ 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 - - $request = $this->getRequest(); + + // 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); + $type = $request->getParam('type'); - /* This is some *extremely* lazy programming that needs to bi fixed. For some reason + $limit = $request->getParam('limit'); + if ($limit == "" || !is_numeric($limit)) { + $limit = "5"; + } + /* This is some *extremely* lazy programming that needs to be fixed. For some reason * we are using two entirely different codepaths for very similar functionality (type = endofday * vs type = interval). Needs to be fixed for 2.3 - MK */ if ($type == "endofday") { - $limit = $request->getParam('limit'); - if ($limit == "" || !is_numeric($limit)) { - $limit = "5"; - } - + // make getNextShows use end of day $end = Application_Common_DateHelper::getTodayStationEndDateTime(); $end->setTimezone(new DateTimeZone("UTC")); $utcTimeEnd = $end->format("Y-m-d H:i:s"); + $result = array( - "env" => APPLICATION_ENV, - "schedulerTime" => $utcTimeNow, - "currentShow" => Application_Model_Show::getCurrentShow($utcTimeNow), - "nextShow" => Application_Model_Show::getNextShows($utcTimeNow, $limit, $utcTimeEnd) + "env" => APPLICATION_ENV, + "schedulerTime" => $utcTimeNow, + "currentShow" => Application_Model_Show::getCurrentShow($utcTimeNow), + "nextShow" => Application_Model_Show::getNextShows($utcTimeNow, $limit, $utcTimeEnd) ); + } else { + $result = Application_Model_Schedule::GetPlayOrderRangeOld($limit); } - else { - $result = Application_Model_Schedule::GetPlayOrderRange(); - - // XSS exploit prevention - $result["previous"]["name"] = htmlspecialchars($result["previous"]["name"]); - $result["current"]["name"] = htmlspecialchars($result["current"]["name"]); - $result["next"]["name"] = htmlspecialchars($result["next"]["name"]); - } - + // XSS exploit prevention - foreach ($result["currentShow"] as &$current) { - $current["name"] = htmlspecialchars($current["name"]); - } - foreach ($result["nextShow"] as &$next) { - $next["name"] = htmlspecialchars($next["name"]); - } + $this->convertSpecialChars($result, array("name", "url")); + // apply user-defined timezone, or default to station + Application_Common_DateHelper::convertTimestampsToTimezone( + $result['currentShow'], + array("starts", "ends", "start_timestamp","end_timestamp"), + $timezone + ); + Application_Common_DateHelper::convertTimestampsToTimezone( + $result['nextShow'], + array("starts", "ends", "start_timestamp","end_timestamp"), + $timezone + ); - //For consistency, all times here are being sent in the station timezone, which - //seems to be what we've normalized everything to. - - //Convert the UTC scheduler time ("now") to the station timezone. - $result["schedulerTime"] = Application_Common_DateHelper::UTCStringToStationTimezoneString($result["schedulerTime"]); - $result["timezone"] = Application_Common_DateHelper::getStationTimezoneAbbreviation(); - $result["timezoneOffset"] = Application_Common_DateHelper::getStationTimezoneOffset(); - - //Convert from UTC to station time for Web Browser. - Application_Common_DateHelper::convertTimestamps($result["currentShow"], - array("starts", "ends", "start_timestamp", "end_timestamp"), - "station"); - Application_Common_DateHelper::convertTimestamps($result["nextShow"], - array("starts", "ends", "start_timestamp", "end_timestamp"), - "station"); - - //used by caller to determine if the airtime they are running or widgets in use is out of date. + //Convert the UTC scheduler time ("now") to the user-defined timezone. + $result["schedulerTime"] = Application_Common_DateHelper::UTCStringToTimezoneString($result["schedulerTime"], $timezone); + $result["timezone"] = $upcase ? strtoupper($timezone) : $timezone; + $result["timezoneOffset"] = Application_Common_DateHelper::getTimezoneOffset($timezone); + + // used by caller to determine if the airtime they are running or widgets in use is out of date. $result['AIRTIME_API_VERSION'] = AIRTIME_API_VERSION; header("Content-Type: application/json"); - + + if (version_compare(phpversion(), '5.4.0', '<')) { + $js = json_encode($result); + } else { + $js = json_encode($result, JSON_PRETTY_PRINT); + } // If a callback is not given, then just provide the raw JSON. - echo isset($_GET['callback']) ? $_GET['callback'].'('.json_encode($result).')' : json_encode($result); + 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; } } + + /** + * Retrieve the currently playing show as well as upcoming shows. + * Number of shows returned and the time interval in which to + * get the next shows can be configured as GET parameters. + * + * Possible parameters: + * days - How many days to retrieve. + * Default is 2 (today + tomorrow). + * shows - How many shows to retrieve + * Default is 5. + * timezone - The timezone to send the times in + * Defaults to the station timezone + */ + public function liveInfoV2Action() + { + if (Application_Model_Preference::GetAllow3rdPartyApi()) { + // 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)) { + $daysToRetrieve = "2"; + } + 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); + + // used by caller to determine if the airtime they are running or widgets in use is out of date. + $result["station"]["AIRTIME_API_VERSION"] = AIRTIME_API_VERSION; + header("Content-Type: application/json"); + + if (version_compare(phpversion(), '5.4.0', '<')) { + $js = json_encode($result); + } else { + $js = json_encode($result, JSON_PRETTY_PRINT); + } + // If a callback is not given, then just provide the raw JSON. + echo isset($_GET['callback']) ? $_GET['callback'].'('.$js.')' : $js; + } else { + header('HTTP/1.0 401 Unauthorized'); + print _('You are not allowed to access this resource. '); + exit; + } + } + + /** + * 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) + { + $delimiter = "/"; + // if the user passes in a timezone in standard form ("Continent/City") + // we need to fix the downcased string by upcasing each word delimited by a / + if (strpos($userDefinedTimezone, $delimiter) !== false) { + $userDefinedTimezone = implode($delimiter, array_map('ucfirst', explode($delimiter, $userDefinedTimezone))); + } + // if the timezone defined by the user exists, use that + if (array_key_exists($userDefinedTimezone, timezone_abbreviations_list())) { + $timezone = $userDefinedTimezone; + $upcase = true; + } else if (in_array($userDefinedTimezone, timezone_identifiers_list())) { + $timezone = $userDefinedTimezone; + } + } + + /** + * 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) + { + Application_Common_DateHelper::convertTimestampsToTimezone( + $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; + } public function weekInfoAction() { @@ -328,50 +450,55 @@ class ApiController extends Zend_Controller_Action $weekStartDateTime = Application_Common_DateHelper::getWeekStartDateTime(); $dow = array("monday", "tuesday", "wednesday", "thursday", "friday", - "saturday", "sunday", "nextmonday", "nexttuesday", "nextwednesday", - "nextthursday", "nextfriday", "nextsaturday", "nextsunday"); + "saturday", "sunday", "nextmonday", "nexttuesday", "nextwednesday", + "nextthursday", "nextfriday", "nextsaturday", "nextsunday"); $result = array(); + + // default to the station timezone + $timezone = Application_Model_Preference::GetDefaultTimezone(); + $userDefinedTimezone = strtolower($this->getRequest()->getParam("timezone")); + // if the timezone defined by the user exists, use that + if (array_key_exists($userDefinedTimezone, timezone_abbreviations_list())) { + $timezone = $userDefinedTimezone; + } $utcTimezone = new DateTimeZone("UTC"); - $stationTimezone = new DateTimeZone(Application_Model_Preference::GetDefaultTimezone()); - + $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($stationTimezone); - $weekStartDateTime->add(new DateInterval('P1D')); - - //convert back to UTC to get the actual timestamp used for search. - $weekStartDateTime->setTimezone($utcTimezone); - + + //have to be in station timezone when adding 1 day for daylight savings. + $weekStartDateTime->setTimezone(new DateTimeZone($timezone)); + $weekStartDateTime->add(new DateInterval('P1D')); + + //convert back to UTC to get the actual timestamp used for search. + $weekStartDateTime->setTimezone($utcTimezone); + $utcDayEnd = $weekStartDateTime->format("Y-m-d H:i:s"); $shows = Application_Model_Show::getNextShows($utcDayStart, "ALL", $utcDayEnd); $utcDayStart = $utcDayEnd; - Application_Common_DateHelper::convertTimestamps( - $shows, + // convert to user-defined timezone, or default to station + Application_Common_DateHelper::convertTimestampsToTimezone( + $shows, array("starts", "ends", "start_timestamp","end_timestamp"), - "station" - ); + $timezone + ); - $result[$dow[$i]] = $shows; + $result[$dow[$i]] = $shows; } // XSS exploit prevention - foreach ($dow as $d) { - foreach ($result[$d] as &$show) { - $show["name"] = htmlspecialchars($show["name"]); - $show["url"] = htmlspecialchars($show["url"]); - } - } - + $this->convertSpecialChars($result, array("name", "url")); + //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'].'('.json_encode($result).')' : json_encode($result); + echo isset($_GET['callback']) ? $_GET['callback'].'('.$js.')' : $js; } else { header('HTTP/1.0 401 Unauthorized'); print _('You are not allowed to access this resource. '); @@ -427,6 +554,94 @@ 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() { @@ -1043,8 +1258,8 @@ class ApiController extends Zend_Controller_Action if (!is_null($media_id) && $media_id > 0) { if (isset($data_arr->title)) { - - $data_title = substr($data_arr->title, 0, 1024); + + $data_title = substr($data_arr->title, 0, 1024); $previous_metadata = CcWebstreamMetadataQuery::create() ->orderByDbStartTime('desc') @@ -1060,9 +1275,9 @@ class ApiController extends Zend_Controller_Action } if ($do_insert) { - - $startDT = new DateTime("now", new DateTimeZone("UTC")); - + + $startDT = new DateTime("now", new DateTimeZone("UTC")); + $webstream_metadata = new CcWebstreamMetadata(); $webstream_metadata->setDbInstanceId($media_id); $webstream_metadata->setDbStartTime($startDT); diff --git a/airtime_mvc/application/models/Schedule.php b/airtime_mvc/application/models/Schedule.php index 669cb6e2b..7dd3943fd 100644 --- a/airtime_mvc/application/models/Schedule.php +++ b/airtime_mvc/application/models/Schedule.php @@ -56,43 +56,79 @@ SQL; return $real_streams; } + /** * Returns data related to the scheduled items. - * - * @param int $p_prev - * @param int $p_next - * @return date */ - public static function GetPlayOrderRange($p_prev = 1, $p_next = 1) + 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. - - 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"); + // Everything in this function must be done in UTC. You will get a swift kick in the pants if you mess that up. - return array(); + // when timeEnd is unspecified, return to the default behaviour - set a range of 48 hours from current time + if (!$utcTimeEnd) { + $end = new DateTime(); + $end->add(new DateInterval("P2D")); // Add 2 days + $end->setTimezone(new DateTimeZone("UTC")); + $utcTimeEnd = $end->format("Y-m-d H:i:s"); } $utcNow = new DateTime("now", new DateTimeZone("UTC")); - - $shows = Application_Model_Show::getPrevCurrentNext($utcNow); + + $shows = Application_Model_Show::getPrevCurrentNext($utcNow, $utcTimeEnd, $showsToRetrieve); + $previousShowID = count($shows['previousShow'])>0?$shows['previousShow'][0]['instance_id']:null; + $currentShowID = count($shows['currentShow'])>0?$shows['currentShow']['instance_id']:null; + $nextShowID = count($shows['nextShow'])>0?$shows['nextShow'][0]['instance_id']:null; + $results = self::GetPrevCurrentNext($previousShowID, $currentShowID, $nextShowID, $utcNow); + + $range = array( + "station" => array ( + "env" => APPLICATION_ENV, + "schedulerTime" => $utcNow->format("Y-m-d H:i:s") + ), + //Previous, current, next songs! + "tracks" => array( + "previous" => $results['previous'], + "current" => $results['current'], + "next" => $results['next'] + ), + //Current and next shows + "shows" => array ( + "previous" => $shows['previousShow'], + "current" => $shows['currentShow'], + "next" => $shows['nextShow'] + ) + ); + + return $range; + } + + /** + * Old version of the function for backwards compatibility + */ + public static function GetPlayOrderRangeOld() + { + // Everything in this function must be done in UTC. You will get a swift kick in the pants if you mess that up. + + $utcNow = new DateTime("now", new DateTimeZone("UTC")); + + $shows = Application_Model_Show::getPrevCurrentNextOld($utcNow); $previousShowID = count($shows['previousShow'])>0?$shows['previousShow'][0]['instance_id']:null; $currentShowID = count($shows['currentShow'])>0?$shows['currentShow'][0]['instance_id']:null; $nextShowID = count($shows['nextShow'])>0?$shows['nextShow'][0]['instance_id']:null; $results = self::GetPrevCurrentNext($previousShowID, $currentShowID, $nextShowID, $utcNow); - - $range = array("env"=>APPLICATION_ENV, - "schedulerTime"=> $utcNow->format("Y-m-d H:i:s"), - //Previous, current, next songs! - "previous"=>$results['previous'] !=null?$results['previous']:(count($shows['previousShow'])>0?$shows['previousShow'][0]:null), - "current"=>$results['current'] !=null?$results['current']:((count($shows['currentShow'])>0 && $shows['currentShow'][0]['record'] == 1)?$shows['currentShow'][0]:null), - "next"=> $results['next'] !=null?$results['next']:(count($shows['nextShow'])>0?$shows['nextShow'][0]:null), - //Current and next shows - "currentShow"=>$shows['currentShow'], - "nextShow"=>$shows['nextShow'], + + $range = array( + "env" => APPLICATION_ENV, + "schedulerTime" => $utcNow->format("Y-m-d H:i:s"), + //Previous, current, next songs! + "previous"=>$results['previous'] !=null?$results['previous']:(count($shows['previousShow'])>0?$shows['previousShow'][0]:null), + "current"=>$results['current'] !=null?$results['current']:((count($shows['currentShow'])>0 && $shows['currentShow'][0]['record'] == 1)?$shows['currentShow'][0]:null), + "next"=> $results['next'] !=null?$results['next']:(count($shows['nextShow'])>0?$shows['nextShow'][0]:null), + //Current and next shows + "currentShow"=>$shows['currentShow'], + "nextShow"=>$shows['nextShow'] ); - + return $range; } @@ -111,7 +147,7 @@ SQL; $timeZone = new DateTimeZone("UTC"); //This function works entirely in UTC. assert(get_class($utcNow) === "DateTime"); assert($utcNow->getTimeZone() == $timeZone); - + if ($p_previousShowID == null && $p_currentShowID == null && $p_nextShowID == null) { return; } @@ -170,15 +206,15 @@ SQL; $results['next'] = null; for ($i = 0; $i < $numberOfRows; ++$i) { - + // if the show is overbooked, then update the track end time to the end of the show time. if ($rows[$i]['ends'] > $rows[$i]["show_ends"]) { $rows[$i]['ends'] = $rows[$i]["show_ends"]; } - + $curShowStartTime = new DateTime($rows[$i]['starts'], $timeZone); $curShowEndTime = new DateTime($rows[$i]['ends'], $timeZone); - + if (($curShowStartTime <= $utcNow) && ($curShowEndTime >= $utcNow)) { if ($i - 1 >= 0) { $results['previous'] = array("name"=>$rows[$i-1]["artist_name"]." - ".$rows[$i-1]["track_title"], diff --git a/airtime_mvc/application/models/Show.php b/airtime_mvc/application/models/Show.php index 61ebb8888..1f7452adf 100644 --- a/airtime_mvc/application/models/Show.php +++ b/airtime_mvc/application/models/Show.php @@ -1106,14 +1106,14 @@ SQL; } /** - * Gets the current show, previous and next with an 2day window from - * the given timeNow, so timeNow-2days and timeNow+2days. + * Gets the current show, previous and next with an n-day window from + * the given timeNow, so timeNow-2days and timeNow+$daysToRetrieve days. * * @param $utcNow A DateTime object containing the current time in UTC. - * @return An array (with stupid sub-arrays) containing the previous show id, - * current show id, and next show id. + * @return An array containing the previous show, + * current show, and next show. */ - public static function getPrevCurrentNext($utcNow) + public static function getPrevCurrentNext($utcNow, $utcEndStr, $showsToRetrieve) { $timeZone = new DateTimeZone("UTC"); //This function works entirely in UTC. assert(get_class($utcNow) === "DateTime"); @@ -1121,16 +1121,108 @@ SQL; $CC_CONFIG = Config::getConfig(); $con = Propel::getConnection(); - // + + // This will fetch the currently playing show first, then any + // upcoming shows within our interval, and finally move on to + // previous shows in the past 2 days. + $sql = <<= :timeNow::timestamp - INTERVAL '2 days' + AND si.starts < :timeEnd::timestamp + AND modified_instance != TRUE +ORDER BY + CASE + WHEN si.ends > :timeNow::timestamp + AND si.starts < :timeNow::timestamp THEN 1 + WHEN si.starts > :timeNow::timestamp THEN 2 + ELSE 3 + END +LIMIT :lim +SQL; + + $stmt = $con->prepare($sql); + + $utcNowStr = $utcNow->format("Y-m-d H:i:s"); + $stmt->bindValue(':timeNow', $utcNowStr); + $stmt->bindValue(':timeEnd', $utcEndStr); + $stmt->bindValue(':lim', $showsToRetrieve); + + if ($stmt->execute()) { + // use PDO::FETCH_ASSOC to only get the associative values + // note that fetchAll() defaults to PDO::FETCH_BOTH, which we don't want + $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); + } else { + $msg = implode(',', $stmt->errorInfo()); + throw new Exception("Error: $msg"); + } + + $numberOfRows = count($rows); + + $results['previousShow'] = array(); + $results['currentShow'] = null; + $results['nextShow'] = array(); + + for ($i = 0; $i < $numberOfRows; ++$i) { + // all shows start/end times are stored in the database as UTC. + $showStartTime = new DateTime($rows[$i]['starts'], $timeZone); + $showEndTime = new DateTime($rows[$i]['ends'], $timeZone); + + // Find the show that is within the current time. + if (($showStartTime <= $utcNow) && ($showEndTime > $utcNow)) { + $results['currentShow'] = $rows[$i]; + } else if ($showEndTime < $utcNow ) { + array_push($results['previousShow'], $rows[$i]); + } else if ($showStartTime > $utcNow) { + array_push($results['nextShow'], $rows[$i]); + } + } + + return $results; + } + + /** + * Gets the current show, previous and next with an 2day window from + * the given timeNow, so timeNow-2days and timeNow+2days. + * + * @param $utcNow A DateTime object containing the current time in UTC. + * @return An array (with stupid sub-arrays) containing the previous show id, + * current show id, and next show id. + */ + public static function getPrevCurrentNextOld($utcNow) + { + $timeZone = new DateTimeZone("UTC"); //This function works entirely in UTC. + assert(get_class($utcNow) === "DateTime"); + assert($utcNow->getTimeZone() == $timeZone); + + $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 = <<prepare($sql); - + $utcNowStr = $utcNow->format("Y-m-d H:i:s"); $stmt->bindValue(':timeNow1', $utcNowStr); $stmt->bindValue(':timeNow2', $utcNowStr); - + if ($stmt->execute()) { - $rows = $stmt->fetchAll(); + $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); } else { $msg = implode(',', $stmt->errorInfo()); throw new Exception("Error: $msg"); } - + $numberOfRows = count($rows); - + $results['previousShow'] = array(); $results['currentShow'] = array(); $results['nextShow'] = array(); - + for ($i = 0; $i < $numberOfRows; ++$i) { //All shows start/end times are stored in the database as UTC. $showStartTime = new DateTime($rows[$i]['starts'], $timeZone); $showEndTime = new DateTime($rows[$i]['ends'], $timeZone); - + //Find the show that is within the current time. - if (($showStartTime <= $utcNow) && ($showEndTime > $utcNow)) - { + if (($showStartTime <= $utcNow) && ($showEndTime > $utcNow)) + { if ($i-1 >= 0) { $results['previousShow'][0] = array( - "id" => $rows[$i-1]['id'], - "instance_id" => $rows[$i-1]['instance_id'], - "name" => $rows[$i-1]['name'], - "url" => $rows[$i-1]['url'], - "start_timestamp" => $rows[$i-1]['start_timestamp'], - "end_timestamp" => $rows[$i-1]['end_timestamp'], - "starts" => $rows[$i-1]['starts'], - "ends" => $rows[$i-1]['ends'], - "record" => $rows[$i-1]['record'], - "type" => "show"); + "id" => $rows[$i-1]['id'], + "instance_id" => $rows[$i-1]['instance_id'], + "instance_description" => $rows[$i-1]['instance_description'], + "name" => $rows[$i-1]['name'], + "description" => $rows[$i-1]['description'], + "url" => $rows[$i-1]['url'], + "start_timestamp" => $rows[$i-1]['start_timestamp'], + "end_timestamp" => $rows[$i-1]['end_timestamp'], + "starts" => $rows[$i-1]['starts'], + "ends" => $rows[$i-1]['ends'], + "record" => $rows[$i-1]['record'], + "image_path" => $rows[$i-1]['image_path'], + "type" => "show"); } - + $results['currentShow'][0] = $rows[$i]; - + if (isset($rows[$i+1])) { $results['nextShow'][0] = array( - "id" => $rows[$i+1]['id'], - "instance_id" => $rows[$i+1]['instance_id'], - "name" => $rows[$i+1]['name'], - "url" => $rows[$i+1]['url'], - "start_timestamp" => $rows[$i+1]['start_timestamp'], - "end_timestamp" => $rows[$i+1]['end_timestamp'], - "starts" => $rows[$i+1]['starts'], - "ends" => $rows[$i+1]['ends'], - "record" => $rows[$i+1]['record'], - "type" => "show"); + "id" => $rows[$i+1]['id'], + "instance_id" => $rows[$i+1]['instance_id'], + "instance_description" => $rows[$i+1]['instance_description'], + "name" => $rows[$i+1]['name'], + "description" => $rows[$i+1]['description'], + "url" => $rows[$i+1]['url'], + "start_timestamp" => $rows[$i+1]['start_timestamp'], + "end_timestamp" => $rows[$i+1]['end_timestamp'], + "starts" => $rows[$i+1]['starts'], + "ends" => $rows[$i+1]['ends'], + "record" => $rows[$i+1]['record'], + "image_path" => $rows[$i+1]['image_path'], + "type" => "show"); } break; } @@ -1208,34 +1306,40 @@ SQL; //if we hit this we know we've gone to far and can stop looping. if ($showStartTime > $utcNow) { $results['nextShow'][0] = array( - "id" => $rows[$i]['id'], - "instance_id" => $rows[$i]['instance_id'], - "name" => $rows[$i]['name'], - "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'], - "type" => "show"); + "id" => $rows[$i]['id'], + "instance_id" => $rows[$i]['instance_id'], + "instance_description" => $rows[$i]['instance_description'], + "name" => $rows[$i]['name'], + "description" => $rows[$i]['description'], + "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"); break; } } //If we didn't find a a current show because the time didn't fit we may still have //found a previous show so use it. if (count($results['previousShow']) == 0 && isset($previousShowIndex)) { - $results['previousShow'][0] = array( - "id" => $rows[$previousShowIndex]['id'], - "instance_id" => $rows[$previousShowIndex]['instance_id'], - "name" => $rows[$previousShowIndex]['name'], - "start_timestamp" => $rows[$previousShowIndex]['start_timestamp'], - "end_timestamp" => $rows[$previousShowIndex]['end_timestamp'], - "starts" => $rows[$previousShowIndex]['starts'], - "ends" => $rows[$previousShowIndex]['ends'], - "record" => $rows[$previousShowIndex]['record'], - "type" => "show"); + $results['previousShow'][0] = array( + "id" => $rows[$previousShowIndex]['id'], + "instance_id" => $rows[$previousShowIndex]['instance_id'], + "instance_description" => $rows[$previousShowIndex]['instance_description'], + "name" => $rows[$previousShowIndex]['name'], + "description" => $rows[$previousShowIndex]['description'], + "start_timestamp" => $rows[$previousShowIndex]['start_timestamp'], + "end_timestamp" => $rows[$previousShowIndex]['end_timestamp'], + "starts" => $rows[$previousShowIndex]['starts'], + "ends" => $rows[$previousShowIndex]['ends'], + "record" => $rows[$previousShowIndex]['record'], + "image_path" => $rows[$previousShowIndex]['image_path'], + "type" => "show"); } - + return $results; } From d467714f84b46d650fd8df37c04f94efbc8d1588 Mon Sep 17 00:00:00 2001 From: Duncan Sommerville Date: Mon, 27 Oct 2014 15:42:30 -0400 Subject: [PATCH 2/7] Fixed bug where timezone wasn't adjusting correctly when adding or editing a show --- airtime_mvc/public/js/airtime/schedule/add-show.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/airtime_mvc/public/js/airtime/schedule/add-show.js b/airtime_mvc/public/js/airtime/schedule/add-show.js index 5e0ad5b37..0d22188c4 100644 --- a/airtime_mvc/public/js/airtime/schedule/add-show.js +++ b/airtime_mvc/public/js/airtime/schedule/add-show.js @@ -346,6 +346,8 @@ function setAddShowEvents(form) { startTimeField.val(json.start.time); endDateField.val(json.end.date); endTimeField.val(json.end.time); + // Change the timezone now that we've updated the times + currentTimezone = newTimezone; }); }); From e6cf1c7cb9a1f5987ac6df215bc812f16dda1b25 Mon Sep 17 00:00:00 2001 From: Duncan Sommerville Date: Mon, 27 Oct 2014 15:52:14 -0400 Subject: [PATCH 3/7] Updated occurrence of GetPlayOrderRange to use old version for backwards compatibility --- airtime_mvc/application/controllers/ScheduleController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/airtime_mvc/application/controllers/ScheduleController.php b/airtime_mvc/application/controllers/ScheduleController.php index a430e15e5..99a17f19a 100644 --- a/airtime_mvc/application/controllers/ScheduleController.php +++ b/airtime_mvc/application/controllers/ScheduleController.php @@ -261,7 +261,7 @@ class ScheduleController extends Zend_Controller_Action public function getCurrentPlaylistAction() { - $range = Application_Model_Schedule::GetPlayOrderRange(); + $range = Application_Model_Schedule::GetPlayOrderRangeOld(); $show = Application_Model_Show::getCurrentShow(); /* Convert all UTC times to localtime before sending back to user. */ From d4e8eed51d8845a9475685b4b1e68caac818f447 Mon Sep 17 00:00:00 2001 From: Duncan Sommerville Date: Mon, 27 Oct 2014 15:52:58 -0400 Subject: [PATCH 4/7] Marked old functions for API calls as deprecated --- airtime_mvc/application/models/Schedule.php | 1 + airtime_mvc/application/models/Show.php | 1 + 2 files changed, 2 insertions(+) diff --git a/airtime_mvc/application/models/Schedule.php b/airtime_mvc/application/models/Schedule.php index 7dd3943fd..334aac4f1 100644 --- a/airtime_mvc/application/models/Schedule.php +++ b/airtime_mvc/application/models/Schedule.php @@ -104,6 +104,7 @@ SQL; /** * Old version of the function for backwards compatibility + * @deprecated */ public static function GetPlayOrderRangeOld() { diff --git a/airtime_mvc/application/models/Show.php b/airtime_mvc/application/models/Show.php index 1f7452adf..b0507dba6 100644 --- a/airtime_mvc/application/models/Show.php +++ b/airtime_mvc/application/models/Show.php @@ -1201,6 +1201,7 @@ SQL; * @param $utcNow A DateTime object containing the current time in UTC. * @return An array (with stupid sub-arrays) containing the previous show id, * current show id, and next show id. + * @deprecated */ public static function getPrevCurrentNextOld($utcNow) { From eae1b4e17ce76ad6d70ba9c79c143ff4f121a98f Mon Sep 17 00:00:00 2001 From: drigato Date: Tue, 28 Oct 2014 10:25:40 -0400 Subject: [PATCH 5/7] CC-5932: Update is_scheduled query is too slow --- airtime_mvc/application/models/StoredFile.php | 55 ++++++++++++------- 1 file changed, 36 insertions(+), 19 deletions(-) diff --git a/airtime_mvc/application/models/StoredFile.php b/airtime_mvc/application/models/StoredFile.php index 009572647..8b2d92773 100644 --- a/airtime_mvc/application/models/StoredFile.php +++ b/airtime_mvc/application/models/StoredFile.php @@ -1368,27 +1368,44 @@ SQL; return $updateIsScheduled; } + /** + * + * Updates the is_scheduled flag to false for tracks that are no longer + * scheduled in the future. We do this by checking the difference between + * all files scheduled in the future and all files with is_scheduled = true. + * The difference of the two result sets is what we need to update. + */ public static function updatePastFilesIsScheduled() { - /* Set the is_scheduled flag to false where it was true in the - * past, and where tracks are not scheduled in the future and do - * not belong to a show that has not ended yet. We need to check - * for show end times in case a track is overbooked, which would - * indicate it is still scheduled in the future - */ - $sql = << now() at time zone 'UTC' - AND i.ends > now() at time zone 'UTC' -) -SQL; - Application_Common_Database::prepareAndExecute($sql, array(), - Application_Common_Database::EXECUTE); + $futureScheduledFilesSelectCriteria = new Criteria(); + $futureScheduledFilesSelectCriteria->addSelectColumn(CcSchedulePeer::FILE_ID); + $futureScheduledFilesSelectCriteria->setDistinct(); + $futureScheduledFilesSelectCriteria->add(CcSchedulePeer::ENDS, gmdate("Y-m-d H:i:s"), Criteria::GREATER_THAN); + $stmt = CcSchedulePeer::doSelectStmt($futureScheduledFilesSelectCriteria); + $filesScheduledInFuture = $stmt->fetchAll(PDO::FETCH_COLUMN, 0); + $count = 0; + foreach ($filesScheduledInFuture as $f) { + $count += 1; + } + + $filesCurrentlySetWithIsScheduledSelectCriteria = new Criteria(); + $filesCurrentlySetWithIsScheduledSelectCriteria->addSelectColumn(CcFilesPeer::ID); + $filesCurrentlySetWithIsScheduledSelectCriteria->add(CcFilesPeer::IS_SCHEDULED, true); + $stmt = CcFilesPeer::doSelectStmt($filesCurrentlySetWithIsScheduledSelectCriteria); + $filesCurrentlySetWithIsScheduled = $stmt->fetchAll(PDO::FETCH_COLUMN, 0); + $count = 0; + foreach ($filesCurrentlySetWithIsScheduled as $t) { + $count += 1; + } + + $diff = array_diff($filesCurrentlySetWithIsScheduled, $filesScheduledInFuture); + + $con = Propel::getConnection(CcFilesPeer::DATABASE_NAME); + $selectCriteria = new Criteria(); + $selectCriteria->add(CcFilesPeer::ID, $diff, Criteria::IN); + $updateCriteria = new Criteria(); + $updateCriteria->add(CcFilesPeer::IS_SCHEDULED, false); + BasePeer::doUpdate($selectCriteria, $updateCriteria, $con); } } From 1d3180cc806d6bad552aa3b649d092a62b4e828a Mon Sep 17 00:00:00 2001 From: drigato Date: Tue, 28 Oct 2014 10:29:25 -0400 Subject: [PATCH 6/7] CC-5932: Update is_scheduled query is too slow Forgot to remove some debugging statements --- airtime_mvc/application/models/StoredFile.php | 8 -------- 1 file changed, 8 deletions(-) diff --git a/airtime_mvc/application/models/StoredFile.php b/airtime_mvc/application/models/StoredFile.php index 8b2d92773..2c97d41d3 100644 --- a/airtime_mvc/application/models/StoredFile.php +++ b/airtime_mvc/application/models/StoredFile.php @@ -1383,20 +1383,12 @@ SQL; $futureScheduledFilesSelectCriteria->add(CcSchedulePeer::ENDS, gmdate("Y-m-d H:i:s"), Criteria::GREATER_THAN); $stmt = CcSchedulePeer::doSelectStmt($futureScheduledFilesSelectCriteria); $filesScheduledInFuture = $stmt->fetchAll(PDO::FETCH_COLUMN, 0); - $count = 0; - foreach ($filesScheduledInFuture as $f) { - $count += 1; - } $filesCurrentlySetWithIsScheduledSelectCriteria = new Criteria(); $filesCurrentlySetWithIsScheduledSelectCriteria->addSelectColumn(CcFilesPeer::ID); $filesCurrentlySetWithIsScheduledSelectCriteria->add(CcFilesPeer::IS_SCHEDULED, true); $stmt = CcFilesPeer::doSelectStmt($filesCurrentlySetWithIsScheduledSelectCriteria); $filesCurrentlySetWithIsScheduled = $stmt->fetchAll(PDO::FETCH_COLUMN, 0); - $count = 0; - foreach ($filesCurrentlySetWithIsScheduled as $t) { - $count += 1; - } $diff = array_diff($filesCurrentlySetWithIsScheduled, $filesScheduledInFuture); From fd39db2e241a903b9557c979b37c5c7fd54036b1 Mon Sep 17 00:00:00 2001 From: Albert Santoni Date: Wed, 29 Oct 2014 17:55:42 -0400 Subject: [PATCH 7/7] Merge pull request #75 - Saas relder csrf delete file --- .../rest/controllers/MediaController.php | 25 ++++++++++++++++--- .../public/js/airtime/library/plupload.js | 2 +- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/airtime_mvc/application/modules/rest/controllers/MediaController.php b/airtime_mvc/application/modules/rest/controllers/MediaController.php index f03b3b7b2..dbbc346ba 100644 --- a/airtime_mvc/application/modules/rest/controllers/MediaController.php +++ b/airtime_mvc/application/modules/rest/controllers/MediaController.php @@ -300,12 +300,18 @@ class Rest_MediaController extends Zend_Rest_Controller } return $id; } - + private function verifyAuth($checkApiKey, $checkSession) { - //Session takes precedence over API key for now: - if ($checkSession && $this->verifySession()) - { + // Session takes precedence over API key for now: + if ($checkSession && $this->verifySession()) { + // CSRF token validation only applies to session based authorization. + if(!$this->verifyCSRFToken($this->_getParam('csrf_token'))){ + $resp = $this->getResponse(); + $resp->setHttpResponseCode(401); + $resp->appendBody("ERROR: Token Missmatch."); + return false; + } return true; } @@ -321,6 +327,17 @@ 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() { diff --git a/airtime_mvc/public/js/airtime/library/plupload.js b/airtime_mvc/public/js/airtime/library/plupload.js index a361fe442..f96ee3157 100644 --- a/airtime_mvc/public/js/airtime/library/plupload.js +++ b/airtime_mvc/public/js/airtime/library/plupload.js @@ -89,7 +89,7 @@ $(document).ready(function() { $.ajax({ type: 'DELETE', - url: '/rest/media/' + file.id, + url: 'rest/media/' + file.id + "?csrf_token=" + $("#csrf").attr('value'), success: function(resp) { self.recentUploadsTable.fnDraw(); },