From b01921abea9dc8dacf60f7409a26f94a5278b413 Mon Sep 17 00:00:00 2001 From: Martin Konecny Date: Fri, 4 May 2012 19:27:35 -0400 Subject: [PATCH 01/17] CC-3683: Upgraded database not equivalent to fresh install database part 1 -using raw sql statements generated by apgdiff --- .../upgrades/airtime-2.1.0/DbUpgrade.php | 16 ++- .../airtime-2.1.0/airtime-upgrade.php | 6 +- .../upgrades/airtime-2.1.0/data/upgrade.sql | 111 ++++++++++++++++++ 3 files changed, 128 insertions(+), 5 deletions(-) create mode 100644 install_minimal/upgrades/airtime-2.1.0/data/upgrade.sql diff --git a/install_minimal/upgrades/airtime-2.1.0/DbUpgrade.php b/install_minimal/upgrades/airtime-2.1.0/DbUpgrade.php index cc999ccdf..c1e702f45 100644 --- a/install_minimal/upgrades/airtime-2.1.0/DbUpgrade.php +++ b/install_minimal/upgrades/airtime-2.1.0/DbUpgrade.php @@ -5,14 +5,22 @@ */ class AirtimeDatabaseUpgrade{ - public static function start(){ + public static function start($p_dbValues){ echo "* Updating Database".PHP_EOL; - self::task0(); + self::task0($p_dbValues); self::task1(); } - private static function task0(){ - UpgradeCommon::MigrateTablesToVersion(__DIR__, '20120411174904'); + private static function task0($p_dbValues){ + //UpgradeCommon::MigrateTablesToVersion(__DIR__, '20120411174904'); + + $username = $p_dbValues['database']['dbuser']; + $password = $p_dbValues['database']['dbpass']; + $host = $p_dbValues['database']['host']; + $database = $p_dbValues['database']['dbname']; + $dir = __DIR__; + + passthru("export PGPASSWORD=$password && psql -h $host -U $username -f $dir/data/upgrade.sql $database"); $sql = "INSERT INTO cc_pref(\"keystr\", \"valstr\") VALUES('scheduled_play_switch', 'on')"; UpgradeCommon::queryDb($sql); diff --git a/install_minimal/upgrades/airtime-2.1.0/airtime-upgrade.php b/install_minimal/upgrades/airtime-2.1.0/airtime-upgrade.php index 627e5ce2c..5265b0c6b 100644 --- a/install_minimal/upgrades/airtime-2.1.0/airtime-upgrade.php +++ b/install_minimal/upgrades/airtime-2.1.0/airtime-upgrade.php @@ -49,9 +49,13 @@ require_once 'ConfFileUpgrade.php'; require_once 'DbUpgrade.php'; require_once 'MiscUpgrade.php'; + +$filename = "/etc/airtime/airtime.conf"; +$values = parse_ini_file($filename, true); + UpgradeCommon::connectToDatabase(); UpgradeCommon::SetDefaultTimezone(); AirtimeConfigFileUpgrade::start(); -AirtimeDatabaseUpgrade::start(); +AirtimeDatabaseUpgrade::start($values); AirtimeMiscUpgrade::start(); diff --git a/install_minimal/upgrades/airtime-2.1.0/data/upgrade.sql b/install_minimal/upgrades/airtime-2.1.0/data/upgrade.sql new file mode 100644 index 000000000..0ae9a8c5b --- /dev/null +++ b/install_minimal/upgrades/airtime-2.1.0/data/upgrade.sql @@ -0,0 +1,111 @@ +DROP TRIGGER calculate_position ON cc_playlistcontents; + +DROP FUNCTION calculate_position(); + +DROP VIEW cc_playlisttimes; + +CREATE FUNCTION airtime_to_int(chartoconvert character varying) RETURNS integer + AS + 'SELECT CASE WHEN trim($1) SIMILAR TO ''[0-9]+'' THEN CAST(trim($1) AS integer) ELSE NULL END;' + LANGUAGE SQL + IMMUTABLE + RETURNS NULL ON NULL INPUT; + +ALTER TABLE cc_files + DROP CONSTRAINT cc_music_dirs_folder_fkey; + +ALTER TABLE cc_playlist + DROP CONSTRAINT cc_playlist_editedby_fkey; + +CREATE SEQUENCE cc_subjs_token_id_seq + START WITH 1 + INCREMENT BY 1 + NO MAXVALUE + NO MINVALUE + CACHE 1; + +CREATE TABLE cc_subjs_token ( + id integer DEFAULT nextval('cc_subjs_token_id_seq'::regclass) NOT NULL, + user_id integer NOT NULL, + "action" character varying(255) NOT NULL, + token character varying(40) NOT NULL, + created timestamp without time zone NOT NULL +); + +ALTER TABLE cc_files + ADD COLUMN utime timestamp(6) without time zone, + ADD COLUMN lptime timestamp(6) without time zone, + ADD COLUMN file_exists boolean DEFAULT true, + ALTER COLUMN bit_rate TYPE integer USING airtime_to_int(bit_rate) /* TYPE change - table: cc_files original: character varying(32) new: integer */, + ALTER COLUMN sample_rate TYPE integer USING airtime_to_int(bit_rate) /* TYPE change - table: cc_files original: character varying(32) new: integer */, + ALTER COLUMN length TYPE interval /* TYPE change - table: cc_files original: time without time zone new: interval */, + ALTER COLUMN length SET DEFAULT '00:00:00'::interval; + +ALTER TABLE cc_music_dirs + ADD COLUMN "exists" boolean DEFAULT true, + ADD COLUMN watched boolean DEFAULT true; + +ALTER TABLE cc_playlist + DROP COLUMN "state", + DROP COLUMN currentlyaccessing, + DROP COLUMN editedby, + DROP COLUMN creator, + ADD COLUMN utime timestamp(6) without time zone, + ADD COLUMN creator_id integer, + ADD COLUMN length interval DEFAULT '00:00:00'::interval; + +ALTER TABLE cc_playlistcontents + ALTER COLUMN cliplength TYPE interval /* TYPE change - table: cc_playlistcontents original: time without time zone new: interval */, + ALTER COLUMN cliplength SET DEFAULT '00:00:00'::interval, + ALTER COLUMN cuein TYPE interval /* TYPE change - table: cc_playlistcontents original: time without time zone new: interval */, + ALTER COLUMN cuein SET DEFAULT '00:00:00'::interval, + ALTER COLUMN cueout TYPE interval /* TYPE change - table: cc_playlistcontents original: time without time zone new: interval */, + ALTER COLUMN cueout SET DEFAULT '00:00:00'::interval; + +ALTER TABLE cc_schedule + DROP COLUMN playlist_id, + DROP COLUMN group_id, + DROP COLUMN schedule_group_played, + ADD COLUMN playout_status smallint DEFAULT 1 NOT NULL, + ALTER COLUMN clip_length TYPE interval /* TYPE change - table: cc_schedule original: time without time zone new: interval */, + ALTER COLUMN clip_length SET DEFAULT '00:00:00'::interval, + ALTER COLUMN cue_in TYPE interval /* TYPE change - table: cc_schedule original: time without time zone new: interval */, + ALTER COLUMN cue_in SET DEFAULT '00:00:00'::interval, + ALTER COLUMN cue_out TYPE interval /* TYPE change - table: cc_schedule original: time without time zone new: interval */, + ALTER COLUMN cue_out SET DEFAULT '00:00:00'::interval; + +ALTER TABLE cc_show + ADD COLUMN live_stream_using_airtime_auth boolean DEFAULT false, + ADD COLUMN live_stream_using_custom_auth boolean DEFAULT false, + ADD COLUMN live_stream_user character varying(255), + ADD COLUMN live_stream_pass character varying(255); + +ALTER TABLE cc_show_instances + ADD COLUMN created timestamp without time zone, + ADD COLUMN last_scheduled timestamp without time zone, + ALTER COLUMN time_filled TYPE interval /* TYPE change - table: cc_show_instances original: time without time zone new: interval */, + ALTER COLUMN time_filled SET DEFAULT '00:00:00'::interval; + +UPDATE cc_show_instances SET created = now(); + +ALTER TABLE cc_show_instances + ALTER COLUMN created SET NOT NULL; + +ALTER TABLE cc_subjs_token + ADD CONSTRAINT cc_subjs_token_pkey PRIMARY KEY (id); + +ALTER TABLE cc_files + ADD CONSTRAINT cc_music_dirs_folder_fkey FOREIGN KEY (directory) REFERENCES cc_music_dirs(id); + +ALTER TABLE cc_playlist + ADD CONSTRAINT cc_playlist_createdby_fkey FOREIGN KEY (creator_id) REFERENCES cc_subjs(id); + +ALTER TABLE cc_subjs_token + ADD CONSTRAINT cc_subjs_token_idx UNIQUE (token); + +ALTER TABLE cc_subjs_token + ADD CONSTRAINT cc_subjs_token_userid_fkey FOREIGN KEY (user_id) REFERENCES cc_subjs(id) ON DELETE CASCADE; + +CREATE INDEX cc_files_file_exists_idx ON cc_files USING btree (file_exists); + +DROP FUNCTION airtime_to_int(chartoconvert character varying); From 240756f98bf71e771c9cf04e6f4d5178fa0a60f1 Mon Sep 17 00:00:00 2001 From: Martin Konecny Date: Fri, 4 May 2012 19:50:16 -0400 Subject: [PATCH 02/17] CC-3767: Pypo push crashed --- python_apps/pypo/pypopush.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/python_apps/pypo/pypopush.py b/python_apps/pypo/pypopush.py index 6e8592c68..56736c107 100644 --- a/python_apps/pypo/pypopush.py +++ b/python_apps/pypo/pypopush.py @@ -129,7 +129,8 @@ class PypoPush(Thread): tn.write('exit\n') tn.read_all() except Exception, e: - self.logger.error(str(e)) + self.logger.error("Error connecting to Liquidsoap: %s", e) + response = [] finally: self.telnet_lock.release() From 9324d5d24afb609eecf0bf3aac23e7e3198ab0c5 Mon Sep 17 00:00:00 2001 From: Martin Konecny Date: Fri, 4 May 2012 19:51:08 -0400 Subject: [PATCH 03/17] CC-3683: Upgraded database not equivalent to fresh install database part 1 -using raw sql statements generated by apgdiff --- install_minimal/upgrades/airtime-2.1.0/DbUpgrade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install_minimal/upgrades/airtime-2.1.0/DbUpgrade.php b/install_minimal/upgrades/airtime-2.1.0/DbUpgrade.php index c1e702f45..ab40c2afd 100644 --- a/install_minimal/upgrades/airtime-2.1.0/DbUpgrade.php +++ b/install_minimal/upgrades/airtime-2.1.0/DbUpgrade.php @@ -20,7 +20,7 @@ class AirtimeDatabaseUpgrade{ $database = $p_dbValues['database']['dbname']; $dir = __DIR__; - passthru("export PGPASSWORD=$password && psql -h $host -U $username -f $dir/data/upgrade.sql $database"); + passthru("export PGPASSWORD=$password && psql -h $host -U $username -f $dir/data/upgrade.sql $database > /dev/null"); $sql = "INSERT INTO cc_pref(\"keystr\", \"valstr\") VALUES('scheduled_play_switch', 'on')"; UpgradeCommon::queryDb($sql); From d80dece0bca3756135ac5399d3facdf2167661d6 Mon Sep 17 00:00:00 2001 From: Martin Konecny Date: Fri, 4 May 2012 19:56:20 -0400 Subject: [PATCH 04/17] CC-3683: Upgraded database not equivalent to fresh install database part 1 -hide useless "NOTICE" statements --- install_minimal/upgrades/airtime-2.1.0/DbUpgrade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install_minimal/upgrades/airtime-2.1.0/DbUpgrade.php b/install_minimal/upgrades/airtime-2.1.0/DbUpgrade.php index ab40c2afd..1b78982fe 100644 --- a/install_minimal/upgrades/airtime-2.1.0/DbUpgrade.php +++ b/install_minimal/upgrades/airtime-2.1.0/DbUpgrade.php @@ -20,7 +20,7 @@ class AirtimeDatabaseUpgrade{ $database = $p_dbValues['database']['dbname']; $dir = __DIR__; - passthru("export PGPASSWORD=$password && psql -h $host -U $username -f $dir/data/upgrade.sql $database > /dev/null"); + passthru("export PGPASSWORD=$password && psql -h $host -U $username -f $dir/data/upgrade.sql $database > /dev/null | grep -v \"will create implicit index\""); $sql = "INSERT INTO cc_pref(\"keystr\", \"valstr\") VALUES('scheduled_play_switch', 'on')"; UpgradeCommon::queryDb($sql); From bc8cdc8a2d49b165474c750ae9922cbc7f7f318a Mon Sep 17 00:00:00 2001 From: Martin Konecny Date: Fri, 4 May 2012 20:13:21 -0400 Subject: [PATCH 05/17] CC-3683: Upgraded database not equivalent to fresh install database part 1 -hide useless "NOTICE" statements --- install_minimal/upgrades/airtime-2.1.0/DbUpgrade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install_minimal/upgrades/airtime-2.1.0/DbUpgrade.php b/install_minimal/upgrades/airtime-2.1.0/DbUpgrade.php index 1b78982fe..f2a5ab012 100644 --- a/install_minimal/upgrades/airtime-2.1.0/DbUpgrade.php +++ b/install_minimal/upgrades/airtime-2.1.0/DbUpgrade.php @@ -20,7 +20,7 @@ class AirtimeDatabaseUpgrade{ $database = $p_dbValues['database']['dbname']; $dir = __DIR__; - passthru("export PGPASSWORD=$password && psql -h $host -U $username -f $dir/data/upgrade.sql $database > /dev/null | grep -v \"will create implicit index\""); + passthru("export PGPASSWORD=$password && psql -h $host -U $username -q -f $dir/data/upgrade.sql $database"); $sql = "INSERT INTO cc_pref(\"keystr\", \"valstr\") VALUES('scheduled_play_switch', 'on')"; UpgradeCommon::queryDb($sql); From 5aea66a5c4be4768ad87ead9344bb35c6b9fe4ae Mon Sep 17 00:00:00 2001 From: Martin Konecny Date: Fri, 4 May 2012 20:18:11 -0400 Subject: [PATCH 06/17] CC-3683: Upgraded database not equivalent to fresh install database part 1 -hide useless "NOTICE" statements --- install_minimal/upgrades/airtime-2.1.0/DbUpgrade.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/install_minimal/upgrades/airtime-2.1.0/DbUpgrade.php b/install_minimal/upgrades/airtime-2.1.0/DbUpgrade.php index f2a5ab012..8f2d006e1 100644 --- a/install_minimal/upgrades/airtime-2.1.0/DbUpgrade.php +++ b/install_minimal/upgrades/airtime-2.1.0/DbUpgrade.php @@ -9,6 +9,7 @@ class AirtimeDatabaseUpgrade{ echo "* Updating Database".PHP_EOL; self::task0($p_dbValues); self::task1(); + echo " * Complete".PHP_EOL; } private static function task0($p_dbValues){ @@ -20,7 +21,7 @@ class AirtimeDatabaseUpgrade{ $database = $p_dbValues['database']['dbname']; $dir = __DIR__; - passthru("export PGPASSWORD=$password && psql -h $host -U $username -q -f $dir/data/upgrade.sql $database"); + passthru("export PGPASSWORD=$password && psql -h $host -U $username -q -f $dir/data/upgrade.sql $database 2>&1 | grep -v \"will create implicit index\""); $sql = "INSERT INTO cc_pref(\"keystr\", \"valstr\") VALUES('scheduled_play_switch', 'on')"; UpgradeCommon::queryDb($sql); From bb5deda09d12fd227303acd43d63ad2f022f606f Mon Sep 17 00:00:00 2001 From: Martin Konecny Date: Sat, 5 May 2012 21:34:09 -0400 Subject: [PATCH 07/17] Various fixes for installer -create zendphp.log before web files are available -run airtime.php script earlier so DB is created before web files are available -zendphp.log should have 644 permissions, not 755 --- install_minimal/airtime-install | 13 +++++++++++++ install_minimal/include/AirtimeInstall.php | 4 ++-- install_minimal/include/airtime-copy-files.sh | 16 +++++++++++++++- install_minimal/include/airtime-initialize.sh | 16 ---------------- install_minimal/include/airtime-install.php | 7 +------ 5 files changed, 31 insertions(+), 25 deletions(-) diff --git a/install_minimal/airtime-install b/install_minimal/airtime-install index 70efa614e..da7663a5f 100755 --- a/install_minimal/airtime-install +++ b/install_minimal/airtime-install @@ -160,6 +160,19 @@ if [ "$DO_UPGRADE" -eq "1" ]; then php --php-ini ${SCRIPTPATH}/airtime-php.ini ${SCRIPTPATH}/include/airtime-upgrade.php $@ fi +set +e +if [ "$DO_UPGRADE" -eq "0" ]; then + php --php-ini ${SCRIPTPATH}/airtime-php.ini ${SCRIPTPATH}/include/airtime-install.php $@ + result=$? + + if [ "$result" -ne "0" ]; then + #There was an error, exit with error code. + echo "There was an error during install. Exit code $result" + exit 1 + fi +fi +set -e + $SCRIPTPATH/include/airtime-copy-files.sh $SCRIPTPATH/include/airtime-initialize.sh $@ diff --git a/install_minimal/include/AirtimeInstall.php b/install_minimal/include/AirtimeInstall.php index 4dc8555a8..7186c0833 100644 --- a/install_minimal/include/AirtimeInstall.php +++ b/install_minimal/include/AirtimeInstall.php @@ -261,7 +261,7 @@ class AirtimeInstall // Put Propel sql files in Database //$command = AirtimeInstall::CONF_DIR_WWW."/library/propel/generator/bin/propel-gen ".AirtimeInstall::CONF_DIR_WWW."/build/ insert-sql 2>/dev/null"; - $dir = AirtimeInstall::CONF_DIR_WWW."/build/sql/"; + $dir = self::GetAirtimeSrcDir()."/build/sql/"; $files = array("schema.sql", "sequences.sql", "views.sql", "triggers.sql", "defaultdata.sql"); foreach ($files as $f){ @@ -453,7 +453,7 @@ class AirtimeInstall } touch($file); - chmod($file, 0755); + chmod($file, 0644); chown($file, $CC_CONFIG['webServerUser']); chgrp($file, $CC_CONFIG['webServerUser']); } diff --git a/install_minimal/include/airtime-copy-files.sh b/install_minimal/include/airtime-copy-files.sh index b46b1d621..236cf5f98 100755 --- a/install_minimal/include/airtime-copy-files.sh +++ b/install_minimal/include/airtime-copy-files.sh @@ -35,11 +35,18 @@ AIRTIMEROOT=$SCRIPTPATH/../../ echo "* Creating /etc/airtime" mkdir -p /etc/airtime -#if [ "$DO_UPGRADE" -eq "0" ]; then if [ ! -e /etc/airtime/airtime.conf ]; then + #config file airtime.conf exists, but Airtime is not installed cp $AIRTIMEROOT/airtime_mvc/build/airtime.conf /etc/airtime fi +#if [ -e /etc/airtime/airtime.conf -a "$DO_UPGRADE" -eq "0" ]; then + #config file airtime.conf exists, but Airtime is not installed +# mv /etc/airtime/airtime.conf airtime.conf.bak +# cp $AIRTIMEROOT/airtime_mvc/build/airtime.conf /etc/airtime +#fi + + echo "* Creating /etc/monit/conf.d/monit-airtime-generic.cfg" mkdir -p /etc/monit/conf.d/ if [ ! -e /etc/monit/conf.d/monit-airtime-generic.cfg ]; then @@ -78,6 +85,13 @@ ln -sf /usr/lib/airtime/utils/airtime-log /usr/bin/airtime-log ln -sf /usr/lib/airtime/utils/airtime-test-soundcard /usr/bin/airtime-test-soundcard ln -sf /usr/lib/airtime/utils/airtime-test-stream /usr/bin/airtime-test-stream +echo "* Creating /var/log/airtime" +mkdir -p /var/log/airtime +chmod a+x /var/log/airtime +touch /var/log/airtime/zendphp.log +chown www-data:www-data /var/log/airtime/zendphp.log +chmod 644 /var/log/airtime/zendphp.log + if [ "$web" = "t" ]; then echo "* Creating /usr/share/airtime" rm -rf "/usr/share/airtime" diff --git a/install_minimal/include/airtime-initialize.sh b/install_minimal/include/airtime-initialize.sh index d3d6cdfed..761f09cc3 100755 --- a/install_minimal/include/airtime-initialize.sh +++ b/install_minimal/include/airtime-initialize.sh @@ -14,22 +14,6 @@ SCRIPTPATH=`dirname $SCRIPT` AIRTIMEROOT=$SCRIPTPATH/../../ -#virtualenv_bin="/usr/lib/airtime/airtime_virtualenv/bin/" -#. ${virtualenv_bin}activate - -set +e -if [ "$DO_UPGRADE" -eq "0" ]; then - php --php-ini ${SCRIPTPATH}/../airtime-php.ini ${SCRIPTPATH}/airtime-install.php $@ - result=$? - - if [ "$result" -ne "0" ]; then - #There was an error, exit with error code. - echo "There was an error during install. Exit code $result" - exit 1 - fi -fi -set -e - if [ "$mediamonitor" = "t" ]; then python $AIRTIMEROOT/python_apps/media-monitor/install/media-monitor-initialize.py fi diff --git a/install_minimal/include/airtime-install.php b/install_minimal/include/airtime-install.php index 6ff0aa492..a17937348 100644 --- a/install_minimal/include/airtime-install.php +++ b/install_minimal/include/airtime-install.php @@ -3,9 +3,6 @@ * @package Airtime * @copyright 2011 Sourcefabric O.P.S. * @license http://www.gnu.org/licenses/gpl.txt - * - * Checks if a previous version of Airtime is currently installed and upgrades Airtime if so. - * Performs a new install (new configs, database install) otherwise. */ require_once(__DIR__.'/AirtimeIni.php'); require_once(__DIR__.'/AirtimeInstall.php'); @@ -56,7 +53,7 @@ if ($overwrite) { } // Update the build.properties file to point to the correct directory. -AirtimeIni::UpdateIniValue(AirtimeInstall::CONF_DIR_WWW.'/build/build.properties', 'project.home', AirtimeInstall::CONF_DIR_WWW); +//AirtimeIni::UpdateIniValue(AirtimeInstall::CONF_DIR_WWW.'/build/build.properties', 'project.home', AirtimeInstall::CONF_DIR_WWW); require_once(AirtimeInstall::GetAirtimeSrcDir().'/application/configs/conf.php'); @@ -74,6 +71,4 @@ if ($db_install) { } } -AirtimeInstall::CreateZendPhpLogFile(); - /* FINISHED AIRTIME PHP INSTALLER */ From 5204da45021ed54cf0fb91cbb15e0af2b03bee05 Mon Sep 17 00:00:00 2001 From: Martin Konecny Date: Sat, 5 May 2012 22:28:52 -0400 Subject: [PATCH 08/17] -new logging class -don't log errors to stdout -log all errors to /var/log/airtime/zendphp.log --- .../application/logging/AirtimeLog.php | 109 ++++++++++++++++++ airtime_mvc/application/logging/Logging.php | 13 ++- airtime_mvc/public/index.php | 4 +- 3 files changed, 122 insertions(+), 4 deletions(-) create mode 100644 airtime_mvc/application/logging/AirtimeLog.php diff --git a/airtime_mvc/application/logging/AirtimeLog.php b/airtime_mvc/application/logging/AirtimeLog.php new file mode 100644 index 000000000..6691f51e9 --- /dev/null +++ b/airtime_mvc/application/logging/AirtimeLog.php @@ -0,0 +1,109 @@ +_errorHandlerMap[$errno])) { + $priority = $this->_errorHandlerMap[$errno]; + } else { + $priority = Zend_Log::INFO; + } + $this->log($errstr, $priority, array('errno'=>$errno, 'file'=>$errfile, 'line'=>$errline, 'context'=>$errcontext)); + } + + if ($this->_origErrorHandler !== null) { + return call_user_func($this->_origErrorHandler, $errno, $errstr, $errfile, $errline, $errcontext); + } + return false; + } + + /** + * Register Logging system as an error handler to log php errors + * Note: it still calls the original error handler if set_error_handler is able to return it. + * + * Errors will be mapped as: + * E_NOTICE, E_USER_NOTICE => NOTICE + * E_WARNING, E_CORE_WARNING, E_USER_WARNING => WARN + * E_ERROR, E_USER_ERROR, E_CORE_ERROR, E_RECOVERABLE_ERROR => ERR + * E_DEPRECATED, E_STRICT, E_USER_DEPRECATED => DEBUG + * (unknown/other) => INFO + * + * @link http://www.php.net/manual/en/function.set-error-handler.php Custom error handler + * + * @return Zend_Log + */ + public function registerErrorHandler() + { + // Only register once. Avoids loop issues if it gets registered twice. + if ($this->_registeredErrorHandler) { + return $this; + } + + $this->_origErrorHandler = set_error_handler(array($this, 'errorHandler')); + + // Contruct a default map of phpErrors to Zend_Log priorities. + // Some of the errors are uncatchable, but are included for completeness + $this->_errorHandlerMap = array( + E_NOTICE => Zend_Log::NOTICE, + E_USER_NOTICE => Zend_Log::NOTICE, + E_WARNING => Zend_Log::WARN, + E_CORE_WARNING => Zend_Log::WARN, + E_USER_WARNING => Zend_Log::WARN, + E_ERROR => Zend_Log::ERR, + E_USER_ERROR => Zend_Log::ERR, + E_CORE_ERROR => Zend_Log::ERR, + E_RECOVERABLE_ERROR => Zend_Log::ERR, + E_STRICT => Zend_Log::DEBUG, + ); + // PHP 5.3.0+ + if (defined('E_DEPRECATED')) { + $this->_errorHandlerMap['E_DEPRECATED'] = Zend_Log::DEBUG; + } + if (defined('E_USER_DEPRECATED')) { + $this->_errorHandlerMap['E_USER_DEPRECATED'] = Zend_Log::DEBUG; + } + + $this->_registeredErrorHandler = true; + return $this; + } +} diff --git a/airtime_mvc/application/logging/Logging.php b/airtime_mvc/application/logging/Logging.php index 5c25b831f..50e6b610e 100644 --- a/airtime_mvc/application/logging/Logging.php +++ b/airtime_mvc/application/logging/Logging.php @@ -6,9 +6,18 @@ class Logging { private static $_path; public static function getLogger(){ - if (!isset(self::$logger)) { + if (!isset(self::$_logger)) { $writer = new Zend_Log_Writer_Stream(self::$_path); - self::$_logger = new Zend_Log($writer); + + if (Zend_Version::compareVersion("1.11") > 0){ + //Running Zend version 1.10 or lower. Need to instantiate our + //own Zend Log class with backported code from 1.11. + require_once __DIR__."/AirtimeLog.php"; + self::$_logger = new Airtime_Zend_Log($writer); + } else { + self::$_logger = new Zend_Log($writer); + } + self::$_logger->registerErrorHandler(); } return self::$_logger; } diff --git a/airtime_mvc/public/index.php b/airtime_mvc/public/index.php index f4fc46922..e496f133c 100644 --- a/airtime_mvc/public/index.php +++ b/airtime_mvc/public/index.php @@ -1,8 +1,8 @@ Date: Sat, 5 May 2012 22:29:16 -0400 Subject: [PATCH 09/17] -catch all exceptions in Preference model and make header 503 --- airtime_mvc/application/models/Preference.php | 195 +++++++++--------- 1 file changed, 102 insertions(+), 93 deletions(-) diff --git a/airtime_mvc/application/models/Preference.php b/airtime_mvc/application/models/Preference.php index 90e87b9b2..f0341e879 100644 --- a/airtime_mvc/application/models/Preference.php +++ b/airtime_mvc/application/models/Preference.php @@ -3,102 +3,109 @@ class Application_Model_Preference { - public static function SetValue($key, $value, $isUserValue = false){ - global $CC_CONFIG; - $con = Propel::getConnection(); - - //called from a daemon process - if(!class_exists("Zend_Auth", false) || !Zend_Auth::getInstance()->hasIdentity()) { - $id = NULL; - } - else { - $auth = Zend_Auth::getInstance(); - $id = $auth->getIdentity()->id; - } - - $key = pg_escape_string($key); - $value = pg_escape_string($value); - - //Check if key already exists - $sql = "SELECT COUNT(*) FROM cc_pref" - ." WHERE keystr = '$key'"; - - //For user specific preference, check if id matches as well - if($isUserValue) { - $sql .= " AND subjid = '$id'"; - } - - $result = $con->query($sql)->fetchColumn(0); - - if($value == "") { - $value = "NULL"; - }else { - $value = "'$value'"; - } - - if($result == 1) { - // result found - if(is_null($id) || !$isUserValue) { - // system pref - $sql = "UPDATE cc_pref" - ." SET subjid = NULL, valstr = $value" - ." WHERE keystr = '$key'"; - } else { - // user pref - $sql = "UPDATE cc_pref" - . " SET valstr = $value" - . " WHERE keystr = '$key' AND subjid = $id"; - } - } else { - // result not found - if(is_null($id) || !$isUserValue) { - // system pref - $sql = "INSERT INTO cc_pref (keystr, valstr)" - ." VALUES ('$key', $value)"; - } else { - // user pref - $sql = "INSERT INTO cc_pref (subjid, keystr, valstr)" - ." VALUES ($id, '$key', $value)"; - } - } + public static function SetValue($key, $value, $isUserValue = false){ try { - $con->exec($sql); - } catch (Exception $e){ - Logging::log("Could not connect to database."); - header('HTTP/1.0 503 Service Unavailable'); - exit; - } - } + $con = Propel::getConnection(); - public static function GetValue($key, $isUserValue = false){ - global $CC_CONFIG; - $con = Propel::getConnection(); + //called from a daemon process + if(!class_exists("Zend_Auth", false) || !Zend_Auth::getInstance()->hasIdentity()) { + $id = NULL; + } + else { + $auth = Zend_Auth::getInstance(); + $id = $auth->getIdentity()->id; + } - //Check if key already exists - $sql = "SELECT COUNT(*) FROM cc_pref" - ." WHERE keystr = '$key'"; - //For user specific preference, check if id matches as well - if ($isUserValue) { - $auth = Zend_Auth::getInstance(); - if($auth->hasIdentity()) { - $id = $auth->getIdentity()->id; - $sql .= " AND subjid = '$id'"; - } - } - $result = $con->query($sql)->fetchColumn(0); - if ($result == 0) - return ""; - else { - $sql = "SELECT valstr FROM cc_pref" + $key = pg_escape_string($key); + $value = pg_escape_string($value); + + //Check if key already exists + $sql = "SELECT COUNT(*) FROM cc_pref" ." WHERE keystr = '$key'"; - //For user specific preference, check if id matches as well - if($isUserValue && $auth->hasIdentity()) { - $sql .= " AND subjid = '$id'"; - } - + //For user specific preference, check if id matches as well + if($isUserValue) { + $sql .= " AND subjid = '$id'"; + } + $result = $con->query($sql)->fetchColumn(0); - return ($result !== false) ? $result : ""; + + if($value == "") { + $value = "NULL"; + }else { + $value = "'$value'"; + } + + if($result == 1) { + // result found + if(is_null($id) || !$isUserValue) { + // system pref + $sql = "UPDATE cc_pref" + ." SET subjid = NULL, valstr = $value" + ." WHERE keystr = '$key'"; + } else { + // user pref + $sql = "UPDATE cc_pref" + . " SET valstr = $value" + . " WHERE keystr = '$key' AND subjid = $id"; + } + } else { + // result not found + if(is_null($id) || !$isUserValue) { + // system pref + $sql = "INSERT INTO cc_pref (keystr, valstr)" + ." VALUES ('$key', $value)"; + } else { + // user pref + $sql = "INSERT INTO cc_pref (subjid, keystr, valstr)" + ." VALUES ($id, '$key', $value)"; + } + } + + $con->exec($sql); + + } catch (Exception $e){ + header('HTTP/1.0 503 Service Unavailable'); + Logging::log("Could not connect to database."); + exit; + } + + } + + public static function GetValue($key, $isUserValue = false){ + try { + $con = Propel::getConnection(); + + //Check if key already exists + $sql = "SELECT COUNT(*) FROM cc_pref" + ." WHERE keystr = '$key'"; + //For user specific preference, check if id matches as well + if ($isUserValue) { + $auth = Zend_Auth::getInstance(); + if($auth->hasIdentity()) { + $id = $auth->getIdentity()->id; + $sql .= " AND subjid = '$id'"; + } + } + $result = $con->query($sql)->fetchColumn(0); + if ($result == 0) + return ""; + else { + $sql = "SELECT valstr FROM cc_pref" + ." WHERE keystr = '$key'"; + + //For user specific preference, check if id matches as well + if($isUserValue && $auth->hasIdentity()) { + $sql .= " AND subjid = '$id'"; + } + + $result = $con->query($sql)->fetchColumn(0); + return ($result !== false) ? $result : ""; + } + } catch (Exception $e) { + header('HTTP/1.0 503 Service Unavailable'); + Logging::log("Could not connect to database."); + exit; } } @@ -567,10 +574,12 @@ class Application_Model_Preference public static function GetAirtimeVersion(){ if (defined('APPLICATION_ENV') && APPLICATION_ENV == "development" && function_exists('exec')){ - return self::GetValue("system_version")."+".exec("git rev-parse --short HEAD"); - } else { - return self::GetValue("system_version"); + $version = exec("git rev-parse --short HEAD 2>/dev/null", $out, $return_code); + if ($return_code == 0){ + return self::GetValue("system_version")."+".$version; + } } + return self::GetValue("system_version"); } public static function GetLatestVersion(){ From adee58bcbcaf3c1a5e82c3626388a48420e81bb4 Mon Sep 17 00:00:00 2001 From: Martin Konecny Date: Sat, 5 May 2012 22:29:31 -0400 Subject: [PATCH 10/17] -better handling of timezones --- airtime_mvc/application/Bootstrap.php | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/airtime_mvc/application/Bootstrap.php b/airtime_mvc/application/Bootstrap.php index 1e5fc3b2d..fe5634682 100644 --- a/airtime_mvc/application/Bootstrap.php +++ b/airtime_mvc/application/Bootstrap.php @@ -12,21 +12,26 @@ require_once "DateHelper.php"; require_once "OsPath.php"; require_once __DIR__.'/controllers/plugins/RabbitMqPlugin.php'; + +//DateTime in PHP 5.3.0+ need a default timezone set. Set to UTC initially +//in case Application_Model_Preference::GetTimezone fails and creates needs to create +//a log entry. This log entry requires a call to date(), which then complains that +//timezone isn't set. Setting a default timezone allows us to create a a graceful log +//that getting the real timezone failed, without PHP complaining that it cannot log because +//there is no timezone :|. +date_default_timezone_set('UTC'); +date_default_timezone_set(Application_Model_Preference::GetTimezone()); + global $CC_CONFIG; $CC_CONFIG['airtime_version'] = Application_Model_Preference::GetAirtimeVersion(); require_once __DIR__."/configs/navigation.php"; -//DateTime in PHP 5.3.0+ need a default timezone set. -date_default_timezone_set(Application_Model_Preference::GetTimezone()); - Zend_Validate::setDefaultNamespaces("Zend"); $front = Zend_Controller_Front::getInstance(); $front->registerPlugin(new RabbitMqPlugin()); -//Logging::debug($_SERVER['REQUEST_URI']); - /* The bootstrap class should only be used to initialize actions that return a view. Actions that return JSON will not use the bootstrap class! */ class Bootstrap extends Zend_Application_Bootstrap_Bootstrap From 4ad3286db274bb5842e3560efa44d1e5c5f760bf Mon Sep 17 00:00:00 2001 From: Martin Konecny Date: Sun, 6 May 2012 15:34:41 -0400 Subject: [PATCH 11/17] CC-3769: PHP 5.3.2 issue with DateTime::createFromFormat and format string "U.u" --- airtime_mvc/application/models/Scheduler.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/airtime_mvc/application/models/Scheduler.php b/airtime_mvc/application/models/Scheduler.php index 364e24cc6..744d65c9e 100644 --- a/airtime_mvc/application/models/Scheduler.php +++ b/airtime_mvc/application/models/Scheduler.php @@ -25,6 +25,12 @@ class Application_Model_Scheduler { $this->epochNow = microtime(true); $this->nowDT = DateTime::createFromFormat("U.u", $this->epochNow, new DateTimeZone("UTC")); + + if ($this->nowDT === false){ + // DateTime::createFromFormat does not support millisecond string formatting in PHP 5.3.2 (Ubuntu 10.04). + // In PHP 5.3.3 (Ubuntu 10.10), this has been fixed. + $this->nowDT = DateTime::createFromFormat("U", time(), new DateTimeZone("UTC")); + } $this->user = Application_Model_User::GetCurrentUser(); } @@ -190,6 +196,12 @@ class Application_Model_Scheduler { $endEpoch = bcadd($startEpoch , (string) $durationSeconds, 6); $dt = DateTime::createFromFormat("U.u", $endEpoch, new DateTimeZone("UTC")); + + if ($dt === false) { + //PHP 5.3.2 problem + $dt = DateTime::createFromFormat("U", intval($endEpoch), new DateTimeZone("UTC")); + } + return $dt; } From 6135660d0f1b42c0cbc1590214421bb64c017b4a Mon Sep 17 00:00:00 2001 From: Martin Konecny Date: Sun, 6 May 2012 20:05:14 -0400 Subject: [PATCH 12/17] CC-3771: year column in cc_files sometimes has values greater than 2^31-1, which causes postgresql to fail when trying to convert this to a year. --- airtime_mvc/application/models/StoredFile.php | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/airtime_mvc/application/models/StoredFile.php b/airtime_mvc/application/models/StoredFile.php index a6044c868..bb3bfed0b 100644 --- a/airtime_mvc/application/models/StoredFile.php +++ b/airtime_mvc/application/models/StoredFile.php @@ -91,6 +91,27 @@ class Application_Model_StoredFile { } else { $dbMd = array(); + + if (isset($p_md["year"])){ + // We need to make sure to clean this value before inserting into database. + // If value is outside of range [-2^31, 2^31-1] then postgresl will throw error + // when trying to retrieve this value. We could make sure number is within these bounds, + // but simplest is to do substring to 4 digits (both values are garbage, but at least our + // new garbage value won't cause errors). If the value is 2012-01-01, then substring to + // 4 digits is an OK result. + // CC-3771 + + $year = $p_md["year"]; + + if (strlen($year) > 4){ + $year = substr($year, 0, 4); + } + if (!is_numeric($year)){ + $year = 0; + } + $p_md["year"] = $year; + } + foreach ($p_md as $mdConst => $mdValue) { $dbMd[constant($mdConst)] = $mdValue; } From 77bffcd8e9c21c881c2d3b669271c7386ce666f5 Mon Sep 17 00:00:00 2001 From: Martin Konecny Date: Sun, 6 May 2012 20:30:49 -0400 Subject: [PATCH 13/17] join function should be static --- airtime_mvc/application/common/OsPath.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/airtime_mvc/application/common/OsPath.php b/airtime_mvc/application/common/OsPath.php index 957545dc4..d9d9b6eff 100644 --- a/airtime_mvc/application/common/OsPath.php +++ b/airtime_mvc/application/common/OsPath.php @@ -45,7 +45,7 @@ class Application_Common_OsPath{ /* Similar to the os.path.join python method * http://stackoverflow.com/a/1782990/276949 */ - function join() { + public static function join() { $args = func_get_args(); $paths = array(); From bd6686a24348d343fde3dd798fc1dca946b84562 Mon Sep 17 00:00:00 2001 From: Martin Konecny Date: Sun, 6 May 2012 20:45:52 -0400 Subject: [PATCH 14/17] CC-3771: year column in cc_files sometimes has values greater than 2^31-1, which causes postgresql to fail when trying to convert this to a year. fixed --- airtime_mvc/application/models/StoredFile.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/airtime_mvc/application/models/StoredFile.php b/airtime_mvc/application/models/StoredFile.php index bb3bfed0b..d699b47d1 100644 --- a/airtime_mvc/application/models/StoredFile.php +++ b/airtime_mvc/application/models/StoredFile.php @@ -92,7 +92,7 @@ class Application_Model_StoredFile { else { $dbMd = array(); - if (isset($p_md["year"])){ + if (isset($p_md["MDATA_KEY_YEAR"])){ // We need to make sure to clean this value before inserting into database. // If value is outside of range [-2^31, 2^31-1] then postgresl will throw error // when trying to retrieve this value. We could make sure number is within these bounds, @@ -101,7 +101,7 @@ class Application_Model_StoredFile { // 4 digits is an OK result. // CC-3771 - $year = $p_md["year"]; + $year = $p_md["MDATA_KEY_YEAR"]; if (strlen($year) > 4){ $year = substr($year, 0, 4); @@ -109,9 +109,9 @@ class Application_Model_StoredFile { if (!is_numeric($year)){ $year = 0; } - $p_md["year"] = $year; + $p_md["MDATA_KEY_YEAR"] = $year; } - + foreach ($p_md as $mdConst => $mdValue) { $dbMd[constant($mdConst)] = $mdValue; } From a4b949cc2f9c9c779d212da63dac54880b1d5de4 Mon Sep 17 00:00:00 2001 From: Naomi Aro Date: Mon, 7 May 2012 14:28:21 +0200 Subject: [PATCH 15/17] CC-3753 : Cannot cancel record show on Timeline view --- airtime_mvc/application/models/ShowBuilder.php | 5 +++-- airtime_mvc/public/js/airtime/showbuilder/builder.js | 9 +++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/airtime_mvc/application/models/ShowBuilder.php b/airtime_mvc/application/models/ShowBuilder.php index aab62d3f2..7b9f2cba6 100644 --- a/airtime_mvc/application/models/ShowBuilder.php +++ b/airtime_mvc/application/models/ShowBuilder.php @@ -250,6 +250,7 @@ class Application_Model_ShowBuilder { //show is empty or is a special kind of show (recording etc) else if (intval($p_item["si_record"]) === 1) { $row["record"] = true; + $row["instance"] = intval($p_item["si_id"]); } else { $row["empty"] = true; @@ -261,7 +262,7 @@ class Application_Model_ShowBuilder { $row["rebroadcast"] = true; } - if ($this->currentShow = true) { + if ($this->currentShow === true) { $row["currentShow"] = true; } @@ -297,7 +298,7 @@ class Application_Model_ShowBuilder { $row["refresh"] = floatval($showEndDT->format("U.u")) - $this->epoch_now; - if ($this->currentShow = true) { + if ($this->currentShow === true) { $row["currentShow"] = true; } diff --git a/airtime_mvc/public/js/airtime/showbuilder/builder.js b/airtime_mvc/public/js/airtime/showbuilder/builder.js index c2d6292b9..761e2662a 100644 --- a/airtime_mvc/public/js/airtime/showbuilder/builder.js +++ b/airtime_mvc/public/js/airtime/showbuilder/builder.js @@ -834,7 +834,8 @@ var AIRTIME = (function(AIRTIME){ $toolbar.find('.sb-button-cancel') .click(function() { var $tr, - data; + data, + msg = 'Cancel Current Show?'; if (AIRTIME.button.isDisabled('sb-button-cancel') === true) { return; @@ -845,7 +846,11 @@ var AIRTIME = (function(AIRTIME){ if ($tr.hasClass('sb-current-show')) { data = $tr.data("aData"); - if (confirm('Cancel Current Show?')) { + if (data.record === true) { + msg = 'Erase current show and stop recording?'; + } + + if (confirm(msg)) { var url = "/Schedule/cancel-current-show"; $.ajax({ url: url, From 1cc84c1c85a01aa78f0d3aab12b36c7ed6fe2615 Mon Sep 17 00:00:00 2001 From: Naomi Aro Date: Mon, 7 May 2012 14:48:33 +0200 Subject: [PATCH 16/17] CC-3761 : Calendar->Update Show:Try to input wrong number of Colour, Browser hangs --- airtime_mvc/application/forms/AddShowStyle.php | 11 +++++++++++ airtime_mvc/public/css/styles.css | 1 + 2 files changed, 12 insertions(+) diff --git a/airtime_mvc/application/forms/AddShowStyle.php b/airtime_mvc/application/forms/AddShowStyle.php index 4f43159e5..8fe158faf 100644 --- a/airtime_mvc/application/forms/AddShowStyle.php +++ b/airtime_mvc/application/forms/AddShowStyle.php @@ -18,6 +18,12 @@ class Application_Form_AddShowStyle extends Zend_Form_SubForm 'viewScript' => 'form/add-show-style.phtml', 'class' => 'big' )))); + + $bg->setValidators(array( + 'Hex', + array('stringLength', false, array(6, 6)) + )); + // Add show color input $this->addElement('text', 'add_show_color', array( @@ -32,6 +38,11 @@ class Application_Form_AddShowStyle extends Zend_Form_SubForm 'viewScript' => 'form/add-show-style.phtml', 'class' => 'big' )))); + + $c->setValidators(array( + 'Hex', + array('stringLength', false, array(6, 6)) + )); } public function disable(){ diff --git a/airtime_mvc/public/css/styles.css b/airtime_mvc/public/css/styles.css index c58c3d3e4..e93b18d27 100644 --- a/airtime_mvc/public/css/styles.css +++ b/airtime_mvc/public/css/styles.css @@ -1400,6 +1400,7 @@ ul.errors li { background:#c6b4b4; margin-bottom:2px; border:1px solid #c83f3f; + list-style: none; } div.success{ From a79514c8ee2d24e02a5218d35f9b92f1a74ea898 Mon Sep 17 00:00:00 2001 From: Naomi Aro Date: Mon, 7 May 2012 15:24:06 +0200 Subject: [PATCH 17/17] CC-3687 : Remove context menus from recorded shows since they are blank. --- airtime_mvc/application/models/ShowBuilder.php | 8 ++++++++ airtime_mvc/public/js/airtime/showbuilder/builder.js | 7 ++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/airtime_mvc/application/models/ShowBuilder.php b/airtime_mvc/application/models/ShowBuilder.php index 7b9f2cba6..cc3844f6d 100644 --- a/airtime_mvc/application/models/ShowBuilder.php +++ b/airtime_mvc/application/models/ShowBuilder.php @@ -251,6 +251,14 @@ class Application_Model_ShowBuilder { else if (intval($p_item["si_record"]) === 1) { $row["record"] = true; $row["instance"] = intval($p_item["si_id"]); + + $showStartDT = new DateTime($p_item["si_starts"], new DateTimeZone("UTC")); + $showEndDT = new DateTime($p_item["si_ends"], new DateTimeZone("UTC")); + + $startsEpoch = floatval($showStartDT->format("U.u")); + $endsEpoch = floatval($showEndDT->format("U.u")); + + $this->getScheduledStatus($startsEpoch, $endsEpoch, $row); } else { $row["empty"] = true; diff --git a/airtime_mvc/public/js/airtime/showbuilder/builder.js b/airtime_mvc/public/js/airtime/showbuilder/builder.js index 761e2662a..9f75f157b 100644 --- a/airtime_mvc/public/js/airtime/showbuilder/builder.js +++ b/airtime_mvc/public/js/airtime/showbuilder/builder.js @@ -936,7 +936,7 @@ var AIRTIME = (function(AIRTIME){ //begin context menu initialization. $.contextMenu({ - selector: '.sb-content table tbody tr:not(.sb-empty, .sb-footer, .sb-header) td:not(.sb-checkbox, .sb-image)', + selector: '.sb-content table tbody tr:not(.sb-empty, .sb-footer, .sb-header, .sb-record) td:not(.sb-checkbox, .sb-image)', trigger: "left", ignoreRightClick: true, @@ -1023,10 +1023,11 @@ var AIRTIME = (function(AIRTIME){ processMenuItems(json.items); } }); - - return { + + return { items: items }; + } }); };