Merge branch 'devel' of dev.sourcefabric.org:airtime into devel

This commit is contained in:
Martin Konecny 2012-01-16 13:58:45 -05:00
commit 54ee177f7d
73 changed files with 8423 additions and 518 deletions

View file

@ -26,6 +26,8 @@ class ApiController extends Zend_Controller_Action
->addActionContext('update-liquidsoap-status', 'json')
->addActionContext('library-init', 'json')
->addActionContext('live-chat', 'json')
->addActionContext('update-file-system-mount', 'json')
->addActionContext('handle-watched-dir-missing', 'json')
->initContext();
}
@ -561,19 +563,26 @@ class ApiController extends Zend_Controller_Action
// update import timestamp
Application_Model_Preference::SetImportTimestamp();
if ($mode == "create") {
$filepath = $md['MDATA_KEY_FILEPATH'];
$filepath = str_replace("\\", "", $filepath);
$filepath = str_replace("//", "/", $filepath);
$file = Application_Model_StoredFile::RecallByFilepath($filepath);
if (is_null($file)) {
$file = Application_Model_StoredFile::Insert($md);
}
else {
$this->view->error = "File already exists in Airtime.";
return;
// path already exist
if($file->getFileExistsFlag()){
// file marked as exists
$this->view->error = "File already exists in Airtime.";
return;
}else{
// file marked as not exists
$file->setFileExistsFlag(true);
}
}
}
else if ($mode == "modify") {
@ -812,5 +821,102 @@ class ApiController extends Zend_Controller_Action
"numEntries"=>Application_Model_Preference::GetLibraryNumEntries()
);
}
// handles addition/deletion of mount point which watched dirs reside
public function updateFileSystemMountAction(){
global $CC_CONFIG;
$request = $this->getRequest();
$api_key = $request->getParam('api_key');
if (!in_array($api_key, $CC_CONFIG["apiKey"]))
{
header('HTTP/1.0 401 Unauthorized');
print 'You are not allowed to access this resource.';
exit;
}
$params = $request->getParams();
$added_list = empty($params['added_dir'])?array():explode(',',$params['added_dir']);
$removed_list = empty($params['removed_dir'])?array():explode(',',$params['removed_dir']);
// get all watched dirs
$watched_dirs = Application_Model_MusicDir::getWatchedDirs(null,null);
foreach( $added_list as $ad){
foreach( $watched_dirs as $dir ){
$dirPath = $dir->getDirectory();
$ad .= '/';
// if mount path itself was watched
if($dirPath == $ad){
Application_Model_MusicDir::addWatchedDir($dirPath, false);
break;
}
// if dir contains any dir in removed_list( if watched dir resides on new mounted path )
else if(substr($dirPath, 0, strlen($ad)) === $ad && $dir->getExistsFlag() == false){
Application_Model_MusicDir::addWatchedDir($dirPath, false);
break;
}
// is new mount point within the watched dir?
// pyinotify doesn't notify anyhing in this case, so we add this mount point as
// watched dir
else if(substr($ad, 0, strlen($dirPath)) === $dirPath){
// bypass nested loop check
Application_Model_MusicDir::addWatchedDir($ad, false, true);
break;
}
}
}
foreach( $removed_list as $rd){
foreach( $watched_dirs as $dir ){
$dirPath = $dir->getDirectory();
$rd .= '/';
// if dir contains any dir in removed_list( if watched dir resides on new mounted path )
if(substr($dirPath, 0, strlen($rd)) === $rd && $dir->getExistsFlag() == true){
Application_Model_MusicDir::removeWatchedDir($dirPath, false);
break;
}
// is new mount point within the watched dir?
// pyinotify doesn't notify anyhing in this case, so we walk through all files within
// this watched dir in DB and mark them deleted.
// In case of h) of use cases, due to pyinotify behaviour of noticing mounted dir, we need to
// compare agaisnt all files in cc_files table
else if(substr($rd, 0, strlen($dirPath)) === $dirPath ){
$watchDir = Application_Model_MusicDir::getDirByPath($rd);
// get all the files that is under $dirPath
$files = Application_Model_StoredFile::listAllFiles($dir->getId(), true);
foreach($files as $f){
// if the file is from this mount
if(substr( $f->getFilePath(),0,strlen($rd) ) === $rd){
$f->delete();
}
}
if($watchDir){
Application_Model_MusicDir::removeWatchedDir($rd, false);
}
break;
}
}
}
}
// handles case where watched dir is missing
public function handleWatchedDirMissingAction(){
global $CC_CONFIG;
$request = $this->getRequest();
$api_key = $request->getParam('api_key');
if (!in_array($api_key, $CC_CONFIG["apiKey"]))
{
header('HTTP/1.0 401 Unauthorized');
print 'You are not allowed to access this resource.';
exit;
}
$dir = base64_decode($request->getParam('dir'));
Application_Model_MusicDir::removeWatchedDir($dir, false);
}
}

View file

@ -0,0 +1,90 @@
<?php
class AuthController extends Zend_Controller_Action
{
public function init()
{
}
public function passwordRestoreAction()
{
//uses separate layout without a navigation.
$this->_helper->layout->setLayout('bare');
$form = new Application_Form_PasswordRestore();
$request = $this->getRequest();
if ($request->isPost() && $form->isValid($request->getPost())) {
$user = CcSubjsQuery::create()
->filterByDbEmail($form->email->getValue())
->findOne();
if (!empty($user)) {
$auth = new Application_Model_Auth();
$auth->sendPasswordRestoreLink($user, $this->view);
$this->_helper->redirector('password-restore-after', 'auth');
}
else {
$form->email->addError($this->view->translate("Given email not found."));
}
}
$this->view->form = $form;
}
public function passwordRestoreAfterAction()
{
//uses separate layout without a navigation.
$this->_helper->layout->setLayout('bare');
}
public function passwordChangeAction()
{
//uses separate layout without a navigation.
$this->_helper->layout->setLayout('bare');
$request = $this->getRequest();
$token = $request->getParam("token", false);
$user_id = $request->getParam("user_id", 0);
$form = new Application_Form_PasswordChange();
$auth = new Application_Model_Auth();
$user = CcSubjsQuery::create()->findPK($user_id);
//check validity of token
if (!$auth->checkToken($user_id, $token, 'password.restore')) {
echo "token not valid";
//$this->_helper->redirector('index', 'login');
}
if ($request->isPost() && $form->isValid($request->getPost())) {
$user->setDbPass(md5($form->password->getValue()));
$user->save();
$auth->invalidateTokens($user, 'password.restore');
$zend_auth = Zend_Auth::getInstance();
$zend_auth->clearIdentity();
$authAdapter = Application_Model_Auth::getAuthAdapter();
$authAdapter->setIdentity($user->getDbLogin())
->setCredential($form->password->getValue());
$result = $zend_auth->authenticate($authAdapter);
//all info about this user from the login table omit only the password
$userInfo = $authAdapter->getResultRowObject(null, 'password');
//the default storage is a session with namespace Zend_Auth
$authStorage = $zend_auth->getStorage();
$authStorage->write($userInfo);
$this->_helper->redirector('index', 'nowplaying');
}
$this->view->form = $form;
}
}

View file

@ -11,6 +11,7 @@ class LibraryController extends Zend_Controller_Action
$ajaxContext = $this->_helper->getHelper('AjaxContext');
$ajaxContext->addActionContext('contents', 'json')
->addActionContext('delete', 'json')
->addActionContext('delete-group', 'json')
->addActionContext('context-menu', 'json')
->addActionContext('get-file-meta-data', 'html')
->addActionContext('upload-file-soundcloud', 'json')
@ -31,12 +32,16 @@ class LibraryController extends Zend_Controller_Action
$this->view->headScript()->appendFile($baseUrl.'/js/datatables/js/jquery.dataTables.js','text/javascript');
$this->view->headScript()->appendFile($baseUrl.'/js/datatables/plugin/dataTables.pluginAPI.js','text/javascript');
$this->view->headScript()->appendFile($baseUrl.'/js/datatables/plugin/dataTables.fnSetFilteringDelay.js','text/javascript');
$this->view->headScript()->appendFile($baseUrl.'/js/datatables/plugin/dataTables.ColVis.js','text/javascript');
$this->view->headScript()->appendFile($baseUrl.'/js/datatables/plugin/dataTables.ColReorder.js','text/javascript');
$this->view->headScript()->appendFile($baseUrl.'/js/datatables/plugin/dataTables.FixedColumns.js','text/javascript');
$this->view->headScript()->appendFile($baseUrl.'/js/airtime/library/library.js','text/javascript');
$this->view->headScript()->appendFile($baseUrl.'/js/airtime/library/advancedsearch.js','text/javascript');
$this->view->headLink()->appendStylesheet($baseUrl.'/css/media_library.css');
$this->view->headLink()->appendStylesheet($baseUrl.'/css/contextmenu.css');
$this->view->headLink()->appendStylesheet($baseUrl.'/css/datatables/css/ColVis.css');
$this->view->headLink()->appendStylesheet($baseUrl.'/css/datatables/css/ColReorder.css');
$this->_helper->layout->setLayout('library');
$this->_helper->viewRenderer->setResponseSegment('library');
@ -178,27 +183,66 @@ class LibraryController extends Zend_Controller_Action
$this->view->id = $id;
}
}
public function deleteGroupAction()
{
$ids = $this->_getParam('ids');
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
$user = new Application_Model_User($userInfo->id);
if ($user->isAdmin()) {
if (!is_null($ids)) {
foreach ($ids as $key => $id) {
$file = Application_Model_StoredFile::Recall($id);
if (PEAR::isError($file)) {
$this->view->message = $file->getMessage();
return;
}
else if(is_null($file)) {
$this->view->message = "file doesn't exist";
return;
}
$res = $file->delete();
if (PEAR::isError($res)) {
$this->view->message = $res->getMessage();
return;
}
else {
$res = settype($res, "integer");
$data = array("filepath" => $file->getFilePath(), "delete" => $res);
Application_Model_RabbitMq::SendMessageToMediaMonitor("file_delete", $data);
}
}
$this->view->ids = $ids;
}
}
}
public function contentsAction()
{
$post = $this->getRequest()->getPost();
$datatables = Application_Model_StoredFile::searchFilesForPlaylistBuilder($post);
//format clip lengh to 1 decimal
foreach($datatables["aaData"] as &$data){
if($data[6] == 'audioclip'){
$file = Application_Model_StoredFile::Recall($data[0]);
if($data['ftype'] == 'audioclip'){
$file = Application_Model_StoredFile::Recall($data['id']);
$scid = $file->getSoundCloudId();
if($scid == "-2"){
$data[1] .= '<span id="'.$data[0].'" class="small-icon progress"></span>';
$data['track_title'] .= '<span id="'.$data['id'].'" class="small-icon progress"></span>';
}else if($scid == "-3"){
$data[1] .= '<span id="'.$data[0].'" class="small-icon sc-error"></span>';
$data['track_title'] .= '<span id="'.$data['id'].'" class="small-icon sc-error"></span>';
}else if(!is_null($scid)){
$data[1] .= '<span id="'.$data[0].'" class="small-icon soundcloud"></span>';
$data['track_title'] .= '<span id="'.$data['id'].'" class="small-icon soundcloud"></span>';
}
}
$sec = Application_Model_Playlist::playlistTimeToSeconds($data[5]);
$data[5] = Application_Model_Playlist::secondsToPlaylistTime($sec);
$sec = Application_Model_Playlist::playlistTimeToSeconds($data['length']);
$data['length'] = Application_Model_Playlist::secondsToPlaylistTime($sec);
}
die(json_encode($datatables));

View file

@ -43,7 +43,7 @@ class LoginController extends Zend_Controller_Action
if(Application_Model_Subjects::getLoginAttempts($username) >= 3 && $form->getElement('captcha') == NULL){
$form->addRecaptcha();
}else{
$authAdapter = $this->getAuthAdapter();
$authAdapter = Application_Model_Auth::getAuthAdapter();
//pass to the adapter the submitted username and password
$authAdapter->setIdentity($username)
@ -92,25 +92,6 @@ class LoginController extends Zend_Controller_Action
Zend_Auth::getInstance()->clearIdentity();
$this->_redirect('login/index');
}
/**
* Gets the adapter for authentication against a database table
*
* @return object
*/
protected function getAuthAdapter()
{
$dbAdapter = Zend_Db_Table::getDefaultAdapter();
$authAdapter = new Zend_Auth_Adapter_DbTable($dbAdapter);
$authAdapter->setTableName('cc_subjs')
->setIdentityColumn('login')
->setCredentialColumn('pass')
->setCredentialTreatment('MD5(?)');
return $authAdapter;
}
}

View file

@ -8,18 +8,20 @@ class PlaylistController extends Zend_Controller_Action
{
$ajaxContext = $this->_helper->getHelper('AjaxContext');
$ajaxContext->addActionContext('add-item', 'json')
->addActionContext('delete-item', 'json')
->addActionContext('set-fade', 'json')
->addActionContext('set-cue', 'json')
->addActionContext('move-item', 'json')
->addActionContext('close', 'json')
->addActionContext('new', 'json')
->addActionContext('edit', 'json')
->addActionContext('delete-active', 'json')
->addActionContext('delete', 'json')
->addActionContext('delete-item', 'json')
->addActionContext('add-group', 'json')
->addActionContext('delete-group', 'json')
->addActionContext('set-fade', 'json')
->addActionContext('set-cue', 'json')
->addActionContext('move-item', 'json')
->addActionContext('close', 'json')
->addActionContext('new', 'json')
->addActionContext('edit', 'json')
->addActionContext('delete-active', 'json')
->addActionContext('delete', 'json')
->addActionContext('set-playlist-fades', 'json')
->addActionContext('set-playlist-name', 'json')
->addActionContext('set-playlist-description', 'json')
->addActionContext('set-playlist-description', 'json')
->initContext();
$this->pl_sess = new Zend_Session_Namespace(UI_PLAYLIST_SESSNAME);
@ -209,6 +211,59 @@ class PlaylistController extends Zend_Controller_Action
unset($this->view->pl);
}
public function addGroupAction()
{
$ids = $this->_getParam('ids');
$pos = $this->_getParam('pos', null);
if (!is_null($ids)) {
$pl = $this->getPlaylist();
if ($pl === false) {
$this->view->playlist_error = true;
return false;
}
foreach ($ids as $key => $value) {
$res = $pl->addAudioClip($value);
if (PEAR::isError($res)) {
$this->view->message = $res->getMessage();
break;
}
}
$this->view->pl = $pl;
$this->view->html = $this->view->render('playlist/update.phtml');
$this->view->name = $pl->getName();
$this->view->length = $pl->getLength();
$this->view->description = $pl->getDescription();
return;
}
$this->view->message = "a file is not chosen";
}
public function deleteGroupAction()
{
$ids = $this->_getParam('ids', null);
foreach ($ids as $key => $id) {
$pl = Application_Model_Playlist::Recall($id);
if ($pl !== FALSE) {
Application_Model_Playlist::Delete($id);
$pl_sess = $this->pl_sess;
if($pl_sess->id === $id){
unset($pl_sess->id);
}
} else {
$this->view->playlist_error = true;
return false;
}
}
$this->view->ids = $ids;
$this->view->html = $this->view->render('playlist/index.phtml');
}
public function setCueAction()
{
$pos = $this->_getParam('pos');

View file

@ -41,11 +41,11 @@ class ScheduleController extends Zend_Controller_Action
$baseUrl = $request->getBaseUrl();
$this->view->headScript()->appendFile($baseUrl.'/js/contextmenu/jjmenu.js','text/javascript');
$this->view->headScript()->appendFile($baseUrl.'/js/datatables/js/jquery.dataTables.js','text/javascript');
$this->view->headScript()->appendFile($baseUrl.'/js/datatables/plugin/dataTables.pluginAPI.js','text/javascript');
$this->view->headScript()->appendFile($baseUrl.'/js/datatables/js/jquery.dataTables.js','text/javascript');
$this->view->headScript()->appendFile($baseUrl.'/js/datatables/plugin/dataTables.pluginAPI.js','text/javascript');
$this->view->headScript()->appendFile($baseUrl.'/js/fullcalendar/fullcalendar.js','text/javascript');
$this->view->headScript()->appendFile($baseUrl.'/js/timepicker/jquery.ui.timepicker-0.0.6.js','text/javascript');
$this->view->headScript()->appendFile($baseUrl.'/js/colorpicker/js/colorpicker.js','text/javascript');
$this->view->headScript()->appendFile($baseUrl.'/js/colorpicker/js/colorpicker.js','text/javascript');
//full-calendar-functions.js requires this variable, so that datePicker widget can be offset to server time instead of client time
$this->view->headScript()->appendScript("var timezoneOffset = ".date("Z")."; //in seconds");
@ -55,10 +55,10 @@ class ScheduleController extends Zend_Controller_Action
$this->view->headScript()->appendFile($baseUrl.'/js/airtime/schedule/schedule.js','text/javascript');
$this->view->headScript()->appendFile($baseUrl.'/js/meioMask/jquery.meio.mask.js','text/javascript');
$this->view->headLink()->appendStylesheet($baseUrl.'/css/jquery-ui-timepicker.css');
$this->view->headLink()->appendStylesheet($baseUrl.'/css/jquery-ui-timepicker.css');
$this->view->headLink()->appendStylesheet($baseUrl.'/css/fullcalendar.css');
$this->view->headLink()->appendStylesheet($baseUrl.'/css/colorpicker/css/colorpicker.css');
$this->view->headLink()->appendStylesheet($baseUrl.'/css/add-show.css');
$this->view->headLink()->appendStylesheet($baseUrl.'/css/colorpicker/css/colorpicker.css');
$this->view->headLink()->appendStylesheet($baseUrl.'/css/add-show.css');
$this->view->headLink()->appendStylesheet($baseUrl.'/css/contextmenu.css');
Application_Model_Schedule::createNewFormSections($this->view);
@ -67,6 +67,8 @@ class ScheduleController extends Zend_Controller_Action
$user = new Application_Model_User($userInfo->id);
$this->view->isAdmin = $user->isAdmin();
$this->view->isProgramManager = $user->isUserType('P');
$this->view->headScript()->appendScript("var weekStart = ".Application_Model_Preference::GetWeekStartDay().";");
}
public function eventFeedAction()
@ -233,9 +235,15 @@ class ScheduleController extends Zend_Controller_Action
if ($showStartDateHelper->getTimestamp() <= $epochNow &&
$epochNow < $showEndDateHelper->getTimestamp() &&
$user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER))) {
if ($show->isRecorded()) {
$menu[] = array('action' => array('type' => 'fn',
'callback' => "window['confirmCancelRecordedShow']($id)"),
'title' => 'Cancel Current Show');
} else {
$menu[] = array('action' => array('type' => 'fn',
'callback' => "window['confirmCancelShow']($id)"),
'title' => 'Cancel Current Show');
}
}
if ($epochNow < $showStartDateHelper->getTimestamp()) {
@ -339,15 +347,15 @@ class ScheduleController extends Zend_Controller_Action
return false;
}
$playlists = $show->searchPlaylistsForShow($post);
foreach( $playlists['aaData'] as &$data){
// calling two functions to format time to 1 decimal place
$sec = Application_Model_Playlist::playlistTimeToSeconds($data[4]);
$data[4] = Application_Model_Playlist::secondsToPlaylistTime($sec);
}
$playlists = $show->searchPlaylistsForShow($post);
foreach( $playlists['aaData'] as &$data){
// calling two functions to format time to 1 decimal place
$sec = Application_Model_Playlist::playlistTimeToSeconds($data['length']);
$data['length'] = Application_Model_Playlist::secondsToPlaylistTime($sec);
}
//for datatables
die(json_encode($playlists));
//for datatables
die(json_encode($playlists));
}
public function removeGroupAction()
@ -443,7 +451,10 @@ class ScheduleController extends Zend_Controller_Action
"Rebroadcast of show \"$originalShowName\" from "
.$originalDateTime->format("l, F jS")." at ".$originalDateTime->format("G:i");
}
$this->view->showContent = $show->getShowListContent();
$this->view->showLength = $show->getShowLength();
$this->view->timeFilled = $show->getTimeScheduled();
$this->view->percentFilled = $show->getPercentScheduled();
$this->view->showContent = $show->getShowListContent();
$this->view->dialog = $this->view->render('schedule/show-content-dialog.phtml');
unset($this->view->showContent);
}

View file

@ -110,8 +110,8 @@ class Zend_Controller_Plugin_Acl extends Zend_Controller_Plugin_Abstract
{
$controller = strtolower($request->getControllerName());
if ($controller == 'api'){
if (in_array($controller, array("api", "auth"))){
$this->setRoleName("G");
}
else if (!Zend_Auth::getInstance()->hasIdentity()){