diff --git a/airtime_mvc/application/controllers/LibraryController.php b/airtime_mvc/application/controllers/LibraryController.php index 2b38349dd..15ae12944 100644 --- a/airtime_mvc/application/controllers/LibraryController.php +++ b/airtime_mvc/application/controllers/LibraryController.php @@ -385,6 +385,15 @@ class LibraryController extends Zend_Controller_Action //TODO move this to the datatables row callback. foreach ($r["aaData"] as &$data) { + foreach ($data as $k => &$v) { + if ($k != "image" && $k != "checkbox") { + $v = htmlspecialchars($v); + } + } + //TODO: Replace the above foreach loop with the line below when ticket + //CC-4896 is completed. + //$data = array_map('htmlspecialchars', $data); + if ($data['ftype'] == 'audioclip') { $file = Application_Model_StoredFile::Recall($data['id']); $scid = $file->getSoundCloudId(); @@ -429,7 +438,7 @@ class LibraryController extends Zend_Controller_Action $formValues = $this->_getParam('data', null); $formdata = array(); foreach ($formValues as $val) { - $formdata[$val["name"]] = $val["value"]; + $formdata[$val["name"]] = htmlspecialchars($val["value"]); } $file->setDbColMetadata($formdata); diff --git a/airtime_mvc/application/controllers/PreferenceController.php b/airtime_mvc/application/controllers/PreferenceController.php index 8617787df..11f036b25 100644 --- a/airtime_mvc/application/controllers/PreferenceController.php +++ b/airtime_mvc/application/controllers/PreferenceController.php @@ -238,7 +238,8 @@ class PreferenceController extends Zend_Controller_Action Application_Model_Preference::SetEnableReplayGain($values["enableReplayGain"]); Application_Model_Preference::setReplayGainModifier($values["replayGainModifier"]); $md = array('schedule' => Application_Model_Schedule::getSchedule()); - Application_Model_RabbitMq::PushSchedule(); + Application_Model_RabbitMq::SendMessageToPypo("update_schedule", $md); + //Application_Model_RabbitMq::PushSchedule(); } Application_Model_StreamSetting::setOffAirMeta($values['offAirMeta']); diff --git a/airtime_mvc/application/controllers/UserController.php b/airtime_mvc/application/controllers/UserController.php index 395156f97..3faa1477f 100644 --- a/airtime_mvc/application/controllers/UserController.php +++ b/airtime_mvc/application/controllers/UserController.php @@ -115,7 +115,7 @@ class UserController extends Zend_Controller_Action $post = $this->getRequest()->getPost(); $users = Application_Model_User::getUsersDataTablesInfo($post); - die(json_encode($users)); + $this->_helper->json->sendJson($users); } public function getUserDataAction() diff --git a/airtime_mvc/application/layouts/scripts/layout.phtml b/airtime_mvc/application/layouts/scripts/layout.phtml index 29d04c0d6..dedda7c88 100644 --- a/airtime_mvc/application/layouts/scripts/layout.phtml +++ b/airtime_mvc/application/layouts/scripts/layout.phtml @@ -24,7 +24,7 @@
diff --git a/airtime_mvc/application/logging/Logging.php b/airtime_mvc/application/logging/Logging.php index dfe7e1fbe..65a8f6dc2 100644 --- a/airtime_mvc/application/logging/Logging.php +++ b/airtime_mvc/application/logging/Logging.php @@ -32,6 +32,8 @@ class Logging { { if (is_array($p_msg) || is_object($p_msg)) { return print_r($p_msg, true); + } else if (is_bool($p_msg)) { + return $p_msg ? "true" : "false"; } else { return $p_msg; } diff --git a/airtime_mvc/application/models/Schedule.php b/airtime_mvc/application/models/Schedule.php index 09f66cd99..b4754d7f9 100644 --- a/airtime_mvc/application/models/Schedule.php +++ b/airtime_mvc/application/models/Schedule.php @@ -696,6 +696,10 @@ SQL; 'replay_gain' => $replay_gain, 'independent_event' => $independent_event, ); + + if ($schedule_item['cue_in'] > $schedule_item['cue_out']) { + $schedule_item['cue_in'] = $schedule_item['cue_out']; + } self::appendScheduleItem($data, $start, $schedule_item); } @@ -906,7 +910,6 @@ SQL; self::createScheduledEvents($data, $range_start, $range_end); self::foldData($data["media"]); - return $data; } diff --git a/airtime_mvc/application/models/Scheduler.php b/airtime_mvc/application/models/Scheduler.php index 2530eb7bf..be9930402 100644 --- a/airtime_mvc/application/models/Scheduler.php +++ b/airtime_mvc/application/models/Scheduler.php @@ -136,13 +136,17 @@ class Application_Model_Scheduler if ($type === "audioclip") { $file = CcFilesQuery::create()->findPK($id, $this->con); + $storedFile = new Application_Model_StoredFile($file->getDbId()); if (is_null($file) || !$file->visible()) { throw new Exception(_("A selected File does not exist!")); } else { $data = $this->fileInfo; $data["id"] = $id; - $data["cliplength"] = $file->getDbLength(); + $data["cliplength"] = $storedFile->getRealClipLength( + $file->getDbCuein(), + $file->getDbCueout()); + $data["cuein"] = $file->getDbCuein(); $data["cueout"] = $file->getDbCueout(); @@ -438,7 +442,6 @@ class Application_Model_Scheduler } foreach ($schedFiles as $file) { - $endTimeDT = $this->findEndTime($nextStartDT, $file['cliplength']); //item existed previously and is being moved. diff --git a/airtime_mvc/application/models/ShowBuilder.php b/airtime_mvc/application/models/ShowBuilder.php index a1ef7c588..72a5f6ab0 100644 --- a/airtime_mvc/application/models/ShowBuilder.php +++ b/airtime_mvc/application/models/ShowBuilder.php @@ -227,7 +227,7 @@ class Application_Model_ShowBuilder $row["endDate"] = $showEndDT->format("Y-m-d"); $row["endTime"] = $showEndDT->format("H:i"); $row["duration"] = floatval($showEndDT->format("U.u")) - floatval($showStartDT->format("U.u")); - $row["title"] = $p_item["show_name"]; + $row["title"] = htmlspecialchars($p_item["show_name"]); $row["instance"] = intval($p_item["si_id"]); $row["image"] = ''; diff --git a/airtime_mvc/application/models/StoredFile.php b/airtime_mvc/application/models/StoredFile.php index bd50f2826..9ca6ff32c 100644 --- a/airtime_mvc/application/models/StoredFile.php +++ b/airtime_mvc/application/models/StoredFile.php @@ -1285,6 +1285,14 @@ SQL; } } } + + public function getRealClipLength($p_cuein, $p_cueout) { + $sql = "SELECT :cueout::INTERVAL - :cuein::INTERVAL"; + + return Application_Common_Database::prepareAndExecute($sql, array( + ':cueout' => $p_cueout, + ':cuein' => $p_cuein), 'column'); + } } class DeleteScheduledFileException extends Exception {} diff --git a/airtime_mvc/application/models/User.php b/airtime_mvc/application/models/User.php index 48a4c3e2f..f35c2fcec 100644 --- a/airtime_mvc/application/models/User.php +++ b/airtime_mvc/application/models/User.php @@ -343,6 +343,8 @@ class Application_Model_User $res['iTotalDisplayRecords']--; $res['iTotalRecords']--; } + + $record = array_map('htmlspecialchars', $record); } $res['aaData'] = array_values($res['aaData']); diff --git a/airtime_mvc/application/views/scripts/form/edit-user.phtml b/airtime_mvc/application/views/scripts/form/edit-user.phtml index cd4b70bd9..79a0081fc 100644 --- a/airtime_mvc/application/views/scripts/form/edit-user.phtml +++ b/airtime_mvc/application/views/scripts/form/edit-user.phtml @@ -1,4 +1,4 @@ -

currentUser) ?>

+

escape($this->currentUser)) ?>

@@ -160,4 +160,4 @@
-
\ No newline at end of file + diff --git a/airtime_mvc/application/views/scripts/form/preferences_watched_dirs.phtml b/airtime_mvc/application/views/scripts/form/preferences_watched_dirs.phtml index 4889892dd..ad8e77797 100644 --- a/airtime_mvc/application/views/scripts/form/preferences_watched_dirs.phtml +++ b/airtime_mvc/application/views/scripts/form/preferences_watched_dirs.phtml @@ -11,7 +11,7 @@ element->getElement('storageFolder')->hasErrors()) : ?> @@ -29,7 +29,7 @@ element->getElement('watchedFolder')->hasErrors()) : ?> diff --git a/airtime_mvc/application/views/scripts/playlist/playlist.phtml b/airtime_mvc/application/views/scripts/playlist/playlist.phtml index f8496d926..a516f2746 100644 --- a/airtime_mvc/application/views/scripts/playlist/playlist.phtml +++ b/airtime_mvc/application/views/scripts/playlist/playlist.phtml @@ -39,7 +39,7 @@ if (isset($this->obj)) {

- obj->getName(); ?> + escape($this->obj->getName()); ?>

length; ?>

diff --git a/airtime_mvc/public/js/airtime/preferences/streamsetting.js b/airtime_mvc/public/js/airtime/preferences/streamsetting.js index 54bb986ca..6e76b693c 100644 --- a/airtime_mvc/public/js/airtime/preferences/streamsetting.js +++ b/airtime_mvc/public/js/airtime/preferences/streamsetting.js @@ -28,7 +28,7 @@ function rebuildStreamURL(ele){ }else{ streamurl = "http://"+host+":"+port+"/" } - div.find("#stream_url").html(streamurl) + div.find("#stream_url").text(streamurl) } function restrictOggBitrate(ele, on){ var div = ele.closest("div") diff --git a/install_minimal/upgrades/airtime-2.3.0/data/upgrade.sql b/install_minimal/upgrades/airtime-2.3.0/data/upgrade.sql index c2d176b23..cd34a28bb 100644 --- a/install_minimal/upgrades/airtime-2.3.0/data/upgrade.sql +++ b/install_minimal/upgrades/airtime-2.3.0/data/upgrade.sql @@ -15,6 +15,8 @@ INSERT INTO cc_stream_setting ("keyname", "value", "type") VALUES ('s3_admin_pas UPDATE cc_music_dirs SET directory = directory || '/' where id in (select id from cc_music_dirs where substr(directory, length(directory)) != '/'); UPDATE cc_files SET filepath = substring(filepath from 2) where id in (select id from cc_files where substring(filepath from 1 for 1) = '/'); +UPDATE cc_files SET cueout = length where cueout = '00:00:00'; + INSERT INTO cc_pref("keystr", "valstr") VALUES('locale', 'en_CA'); INSERT INTO cc_pref("subjid", "keystr", "valstr") VALUES(1, 'user_locale', 'en_CA'); diff --git a/python_apps/api_clients/api_client.py b/python_apps/api_clients/api_client.py index 517870e45..b28a4ca5a 100644 --- a/python_apps/api_clients/api_client.py +++ b/python_apps/api_clients/api_client.py @@ -73,17 +73,26 @@ class ApcUrl(object): else: return self.base_url class ApiRequest(object): - def __init__(self, name, url): + def __init__(self, name, url, logger=None): self.name = name self.url = url self.__req = None + if logger is None: self.logger = logging + else: self.logger = logger def __call__(self,_post_data=None, **kwargs): # TODO : get rid of god damn urllib and replace everything with # grequests or requests at least final_url = self.url.params(**kwargs).url() if _post_data is not None: _post_data = urllib.urlencode(_post_data) - req = urllib2.Request(final_url, _post_data) - response = urllib2.urlopen(req).read() + try: + req = urllib2.Request(final_url, _post_data) + response = urllib2.urlopen(req).read() + except Exception, e: + self.logger.error('Exception: %s', e) + import traceback + top = traceback.format_exc() + self.logger.error("traceback: %s", top) + response = "" # Ghetto hack for now because we don't the content type we are getting # (Pointless to look at mime since it's not being set correctly always) try: return json.loads(response) diff --git a/python_apps/pypo/airtime-liquidsoap-init-d b/python_apps/pypo/airtime-liquidsoap-init-d index 4180d5c67..7096bc59c 100755 --- a/python_apps/pypo/airtime-liquidsoap-init-d +++ b/python_apps/pypo/airtime-liquidsoap-init-d @@ -28,10 +28,10 @@ start () { stop () { monit unmonitor airtime-liquidsoap >/dev/null 2>&1 - /usr/lib/airtime/airtime_virtualenv/bin/python /usr/lib/airtime/pypo/bin/liquidsoap_scripts/liquidsoap_prepare_terminate.py - + #send term signal after 10 seconds + timeout 10 /usr/lib/airtime/airtime_virtualenv/bin/python /usr/lib/airtime/pypo/bin/liquidsoap_scripts/liquidsoap_prepare_terminate.py # Send TERM after 5 seconds, wait at most 30 seconds. - start-stop-daemon --stop --oknodo --retry 5 --quiet --pidfile $PIDFILE + start-stop-daemon --stop --oknodo --retry=TERM/10/KILL/5 --quiet --pidfile $PIDFILE rm -f $PIDFILE } diff --git a/python_apps/pypo/liquidsoap_scripts/liquidsoap_prepare_terminate.py b/python_apps/pypo/liquidsoap_scripts/liquidsoap_prepare_terminate.py index e1dac82b6..2f632d9c7 100644 --- a/python_apps/pypo/liquidsoap_scripts/liquidsoap_prepare_terminate.py +++ b/python_apps/pypo/liquidsoap_scripts/liquidsoap_prepare_terminate.py @@ -6,14 +6,14 @@ try: config = ConfigObj('/etc/airtime/pypo.cfg') LS_HOST = config['ls_host'] LS_PORT = config['ls_port'] - + tn = telnetlib.Telnet(LS_HOST, LS_PORT) tn.write("master_harbor.stop\n") tn.write("live_dj_harbor.stop\n") tn.write('exit\n') tn.read_all() - + except Exception, e: print('Error loading config file: %s', e) sys.exit() - \ No newline at end of file + diff --git a/python_apps/pypo/liquidsoap_scripts/ls_script.liq b/python_apps/pypo/liquidsoap_scripts/ls_script.liq index cd01ad453..489d494a3 100644 --- a/python_apps/pypo/liquidsoap_scripts/ls_script.liq +++ b/python_apps/pypo/liquidsoap_scripts/ls_script.liq @@ -195,28 +195,81 @@ def check_dj_client(user,password) = hd == "True" end -def append_dj_inputs(master_harbor_input_port, master_harbor_input_mount_point, dj_harbor_input_port, dj_harbor_input_mount_point, s) = - if master_harbor_input_port != 0 and master_harbor_input_mount_point != "" and dj_harbor_input_port != 0 and dj_harbor_input_mount_point != "" then - master_dj = mksafe(audio_to_stereo(input.harbor(id="master_harbor", master_harbor_input_mount_point, port=master_harbor_input_port, auth=check_master_dj_client, - max=40., on_connect=master_dj_connect, on_disconnect=master_dj_disconnect))) - dj_live = mksafe(audio_to_stereo(input.harbor(id="live_dj_harbor", dj_harbor_input_mount_point, port=dj_harbor_input_port, auth=check_dj_client, - max=40., on_connect=live_dj_connect, on_disconnect=live_dj_disconnect))) +def append_dj_inputs(master_harbor_input_port, + master_harbor_input_mount_point, + dj_harbor_input_port, + dj_harbor_input_mount_point, + s) = + if master_harbor_input_port != 0 + and master_harbor_input_mount_point != "" + and dj_harbor_input_port != 0 + and dj_harbor_input_mount_point != "" then + + master_dj = mksafe( + audio_to_stereo( + input.harbor(id="master_harbor", + master_harbor_input_mount_point, + port=master_harbor_input_port, + auth=check_master_dj_client, + max=40., + on_connect=master_dj_connect, + on_disconnect=master_dj_disconnect))) + + dj_live = mksafe( + audio_to_stereo( + input.harbor(id="live_dj_harbor", + dj_harbor_input_mount_point, + port=dj_harbor_input_port, + auth=check_dj_client, + max=40., + on_connect=live_dj_connect, + on_disconnect=live_dj_disconnect))) ignore(output.dummy(master_dj, fallible=true)) ignore(output.dummy(dj_live, fallible=true)) - switch(id="master_dj_switch", track_sensitive=false, transitions=[transition, transition, transition], [({!master_dj_enabled},master_dj), ({!live_dj_enabled},dj_live), ({true}, s)]) + + switch(id="master_dj_switch", + track_sensitive=false, + transitions=[transition, transition, transition], + [({!master_dj_enabled},master_dj), + ({!live_dj_enabled},dj_live), + ({true}, s)]) + elsif master_harbor_input_port != 0 and master_harbor_input_mount_point != "" then - master_dj = mksafe(audio_to_stereo(input.harbor(id="master_harbor", master_harbor_input_mount_point, port=master_harbor_input_port, auth=check_master_dj_client, - max=40., on_connect=master_dj_connect, on_disconnect=master_dj_disconnect))) + master_dj = mksafe( + audio_to_stereo( + input.harbor(id="master_harbor", + master_harbor_input_mount_point, + port=master_harbor_input_port, + auth=check_master_dj_client, + max=40., + on_connect=master_dj_connect, + on_disconnect=master_dj_disconnect))) + ignore(output.dummy(master_dj, fallible=true)) - switch(id="master_dj_switch", track_sensitive=false, transitions=[transition, transition], [({!master_dj_enabled},master_dj), ({true}, s)]) + switch(id="master_dj_switch", + track_sensitive=false, + transitions=[transition, transition], + [({!master_dj_enabled},master_dj), ({true}, s)]) + elsif dj_harbor_input_port != 0 and dj_harbor_input_mount_point != "" then - dj_live = mksafe(audio_to_stereo(input.harbor(id="live_dj_harbor", dj_harbor_input_mount_point, port=dj_harbor_input_port, auth=check_dj_client, - max=40., on_connect=live_dj_connect, on_disconnect=live_dj_disconnect))) + dj_live = mksafe( + audio_to_stereo( + input.harbor(id="live_dj_harbor", + dj_harbor_input_mount_point, + port=dj_harbor_input_port, + auth=check_dj_client, + max=40., + on_connect=live_dj_connect, + on_disconnect=live_dj_disconnect))) ignore(output.dummy(dj_live, fallible=true)) - switch(id="live_dj_switch", track_sensitive=false, transitions=[transition, transition], [({!live_dj_enabled},dj_live), ({true}, s)]) + + switch(id="live_dj_switch", + track_sensitive=false, + transitions=[transition, transition], + [({!live_dj_enabled},dj_live), ({true}, s)]) else s end diff --git a/python_apps/pypo/pypofetch.py b/python_apps/pypo/pypofetch.py index 1448c65da..b0cbdc69a 100644 --- a/python_apps/pypo/pypofetch.py +++ b/python_apps/pypo/pypofetch.py @@ -135,6 +135,7 @@ class PypoFetch(Thread): try: lock.acquire() tn = telnetlib.Telnet(LS_HOST, LS_PORT) + self.logger.info(command) tn.write(command) tn.write('exit\n') tn.read_all() @@ -143,6 +144,24 @@ class PypoFetch(Thread): finally: lock.release() + @staticmethod + def telnet_send(logger, lock, commands): + try: + lock.acquire() + + tn = telnetlib.Telnet(LS_HOST, LS_PORT) + for i in commands: + logger.info(i) + tn.write(i) + + tn.write('exit\n') + tn.read_all() + except Exception, e: + logger.error(str(e)) + finally: + lock.release() + + @staticmethod def switch_source(logger, lock, sourcename, status): logger.debug('Switching source: %s to "%s" status', sourcename, status) @@ -159,17 +178,26 @@ class PypoFetch(Thread): else: command += "stop\n" - try: - lock.acquire() + PypoFetch.telnet_send(logger, lock, [command]) - tn = telnetlib.Telnet(LS_HOST, LS_PORT) - tn.write(command) - tn.write('exit\n') - tn.read_all() - except Exception, e: - logger.error(str(e)) - finally: - lock.release() + + #TODO: Merge this with switch_source + def switch_source_temp(self, sourcename, status): + self.logger.debug('Switching source: %s to "%s" status', sourcename, status) + command = "streams." + if sourcename == "master_dj": + command += "master_dj_" + elif sourcename == "live_dj": + command += "live_dj_" + elif sourcename == "scheduled_play": + command += "scheduled_play_" + + if status == "on": + command += "start\n" + else: + command += "stop\n" + + return command """ grabs some information that are needed to be set on bootstrap time @@ -182,11 +210,18 @@ class PypoFetch(Thread): self.logger.error('Unable to get bootstrap info.. Exiting pypo...') else: self.logger.debug('info:%s', info) + commands = [] for k, v in info['switch_status'].iteritems(): - self.switch_source(self.logger, self.telnet_lock, k, v) - self.update_liquidsoap_stream_format(info['stream_label']) - self.update_liquidsoap_station_name(info['station_name']) - self.update_liquidsoap_transition_fade(info['transition_fade']) + commands.append(self.switch_source_temp(k, v)) + + stream_format = info['stream_label'] + station_name = info['station_name'] + fade = info['transition_fade'] + + commands.append(('vars.stream_metadata_type %s\n' % stream_format).encode('utf-8')) + commands.append(('vars.station_name %s\n' % station_name).encode('utf-8')) + commands.append(('vars.default_dj_fade %s\n' % fade).encode('utf-8')) + PypoFetch.telnet_send(self.logger, self.telnet_lock, commands) def restart_liquidsoap(self): @@ -330,8 +365,13 @@ class PypoFetch(Thread): # updated. current_time = time.time() boot_up_time_command = "vars.bootup_time " + str(current_time) + "\n" + self.logger.info(boot_up_time_command) tn.write(boot_up_time_command) - tn.write("streams.connection_status\n") + + connection_status = "streams.connection_status\n" + self.logger.info(connection_status) + tn.write(connection_status) + tn.write('exit\n') output = tn.read_all() @@ -356,6 +396,7 @@ class PypoFetch(Thread): if(status == "true"): self.api_client.notify_liquidsoap_status("OK", stream_id, str(fake_time)) + def update_liquidsoap_stream_format(self, stream_format): # Push stream metadata to liquidsoap # TODO: THIS LIQUIDSOAP STUFF NEEDS TO BE MOVED TO PYPO-PUSH!!!