diff --git a/airtime_mvc/application/controllers/ApiController.php b/airtime_mvc/application/controllers/ApiController.php index 028b43e86..221c42c2a 100644 --- a/airtime_mvc/application/controllers/ApiController.php +++ b/airtime_mvc/application/controllers/ApiController.php @@ -449,11 +449,11 @@ class ApiController extends Zend_Controller_Action if (is_null($file)) { $file = StoredFile::Insert($md); - } else { + } + else { $this->view->error = "File already exists in Airtime."; return; } - } else if ($mode == "modify") { $filepath = $md['MDATA_KEY_FILEPATH']; diff --git a/airtime_mvc/application/models/MusicDir.php b/airtime_mvc/application/models/MusicDir.php index 2af522169..133ceb134 100644 --- a/airtime_mvc/application/models/MusicDir.php +++ b/airtime_mvc/application/models/MusicDir.php @@ -60,7 +60,7 @@ class MusicDir { RabbitMq::PushSchedule(); } - + /** * Checks if p_dir1 is the ancestor of p_dir2. Returns * true if it is the ancestor, false otherwise. Note that @@ -77,7 +77,7 @@ class MusicDir { if (strlen($p_dir1) > strlen($p_dir2)){ return false; } - + return substr($p_dir2, 0, strlen($p_dir1)) == $p_dir1; } @@ -85,15 +85,15 @@ class MusicDir { * Checks whether the path provided is a valid path. A valid path * is defined as not being nested within an existing watched directory, * or vice-versa. Throws a NestedDirectoryException if invalid. - * + * * @param string $p_path * The path we want to validate * @return void - */ + */ public static function isPathValid($p_path){ $dirs = self::getWatchedDirs(); $dirs[] = self::getStorDir(); - + foreach ($dirs as $dirObj){ $dir = $dirObj->getDirectory(); $diff = strlen($dir) - strlen($p_path); @@ -108,7 +108,7 @@ class MusicDir { } else { /* diff < 0*/ if (self::isAncestorDir($dir, $p_path)){ throw new NestedDirectoryException("'$p_path' is nested within existing watched directory: '$dir'"); - } + } } } } @@ -121,10 +121,10 @@ class MusicDir { $dir = new CcMusicDirs(); $dir->setType($p_type); $p_path = realpath($p_path)."/"; - + try { - /* isPathValid() checks if path is a substring or a superstring of an + /* isPathValid() checks if path is a substring or a superstring of an * existing dir and if not, throws NestedDirectoryException */ self::isPathValid($p_path); $dir->setDirectory($p_path); @@ -143,7 +143,41 @@ class MusicDir { public static function addWatchedDir($p_path) { $res = self::addDir($p_path, "watched"); - if($res['code'] == 0){ + if ($res['code'] == 0){ + + //convert "linked" files (Airtime <= 1.8.2) to watched files. + $propel_link_dir = CcMusicDirsQuery::create() + ->filterByType('link') + ->findOne(); + + //newly added watched directory object + $propel_new_watch = CcMusicDirsQuery::create() + ->filterByDirectory(realpath($p_path)."/") + ->findOne(); + + //any files of the deprecated "link" type. + $link_files = CcFilesQuery::create() + ->setFormatter(ModelCriteria::FORMAT_ON_DEMAND) + ->filterByDbDirectory($propel_link_dir->getId()) + ->find(); + + $newly_watched_dir = $propel_new_watch->getDirectory(); + + foreach ($link_files as $link_file) { + $link_filepath = $link_file->getDbFilepath(); + + //convert "link" file into a watched file. + if ((strlen($newly_watched_dir) < strlen($link_filepath)) && (substr($link_filepath, 0, strlen($newly_watched_dir)) === $newly_watched_dir)) { + + //get the filepath path not including the watched directory. + $sub_link_filepath = substr($link_filepath, strlen($newly_watched_dir)); + + $link_file->setDbDirectory($propel_new_watch->getId()); + $link_file->setDbFilepath($sub_link_filepath); + $link_file->save(); + } + } + $data = array(); $data["directory"] = $p_path; RabbitMq::SendMessageToMediaMonitor("new_watch", $data); @@ -227,6 +261,7 @@ class MusicDir { public static function getWatchedDirFromFilepath($p_filepath) { $dirs = CcMusicDirsQuery::create() + ->filterByType(array("watched", "stor")) ->find(); foreach($dirs as $dir) { diff --git a/airtime_mvc/application/models/StoredFile.php b/airtime_mvc/application/models/StoredFile.php index 1f6f905bd..d4ca18214 100644 --- a/airtime_mvc/application/models/StoredFile.php +++ b/airtime_mvc/application/models/StoredFile.php @@ -507,6 +507,7 @@ class StoredFile { } else if (isset($p_filepath)) { $path_info = MusicDir::splitFilePath($p_filepath); + if (is_null($path_info)) { return null; } diff --git a/install_minimal/DoctrineMigrations/Version20110711161043.php b/install_minimal/DoctrineMigrations/Version20110711161043.php index c21f097fb..4a0bed554 100644 --- a/install_minimal/DoctrineMigrations/Version20110711161043.php +++ b/install_minimal/DoctrineMigrations/Version20110711161043.php @@ -16,23 +16,23 @@ class Version20110711161043 extends AbstractMigration public function up(Schema $schema) { /* 1) update cc_files table to include to "directory" column */ - $this->_addSql("INSERT INTO cc_music_dirs (type, directory) VALUES ('stor', '/srv/airtime/stor');"); - - $this->_addSql("INSERT INTO cc_music_dirs (type, directory) VALUES ('upgrade', '');"); + $this->_addSql("INSERT INTO cc_music_dirs (type, directory) VALUES ('stor', '/srv/airtime/stor/');"); + + $this->_addSql("INSERT INTO cc_music_dirs (type, directory) VALUES ('link', '');"); $cc_music_dirs = $schema->getTable('cc_music_dirs'); - + /* 2) create a foreign key relationship from cc_files to cc_music_dirs */ $cc_files = $schema->getTable('cc_files'); - $cc_files->addColumn('directory', 'integer', array('default'=> 2)); + $cc_files->addColumn('directory', 'integer', array('notnull' => 0, 'default'=> NULL)); $cc_files->addNamedForeignKeyConstraint('cc_music_dirs_folder_fkey', $cc_music_dirs, array('directory'), array('id'), array('onDelete' => 'CASCADE')); - + /* 3) create a foreign key relationship from cc_schedule to cc_files */ $cc_schedule = $schema->getTable('cc_schedule'); $cc_schedule->addNamedForeignKeyConstraint('cc_files_folder_fkey', $cc_files, array('file_id'), array('id'), array('onDelete' => 'CASCADE')); } - + public function down(Schema $schema) { diff --git a/install_minimal/upgrades/airtime-1.9.0/airtime-upgrade.php b/install_minimal/upgrades/airtime-1.9.0/airtime-upgrade.php index ca6c1208c..1127b23bf 100644 --- a/install_minimal/upgrades/airtime-1.9.0/airtime-upgrade.php +++ b/install_minimal/upgrades/airtime-1.9.0/airtime-upgrade.php @@ -8,9 +8,13 @@ set_include_path(__DIR__.'/../../../airtime_mvc/library' . PATH_SEPARATOR . get_include_path()); set_include_path(__DIR__.'/../../../airtime_mvc/library/pear' . PATH_SEPARATOR . get_include_path()); +set_include_path(__DIR__.'/../../../airtime_mvc/application/models' . PATH_SEPARATOR . get_include_path()); require_once 'conf.php'; require_once 'DB.php'; +require_once 'propel/runtime/lib/Propel.php'; +Propel::init(__DIR__."/../../../airtime_mvc/application/configs/airtime-conf.php"); + const CONF_DIR_BINARIES = "/usr/lib/airtime"; class AirtimeInstall{ @@ -33,7 +37,7 @@ class AirtimeInstall{ chown($file, $CC_CONFIG['webServerUser']); chgrp($file, $CC_CONFIG['webServerUser']); } - + public static function CreateSymlinksToUtils() { echo "* Creating /usr/bin symlinks".PHP_EOL; @@ -51,14 +55,14 @@ class AirtimeInstall{ $dir = CONF_DIR_BINARIES."/utils/airtime-check-system"; exec("ln -s $dir /usr/bin/airtime-check-system"); } - + public static function RemoveSymlinks() { exec("rm -f /usr/bin/airtime-import"); exec("rm -f /usr/bin/airtime-update-db-settings"); exec("rm -f /usr/bin/airtime-check-system"); } - + public static function DbTableExists($p_name) { global $CC_DBC; @@ -69,7 +73,7 @@ class AirtimeInstall{ } return true; } - + public static function BypassMigrations($dir, $version) { $appDir = AirtimeInstall::GetAirtimeSrcDir(); @@ -89,22 +93,22 @@ class AirtimeInstall{ "--no-interaction migrations:migrate $version"; system($command); } - + public static function CreateCronFile(){ // Create CRON task to run every day. Time of day is initialized to a random time. $hour = rand(0,23); $minute = rand(0,59); - + $fp = fopen('/etc/cron.d/airtime-crons','w'); fwrite($fp, "$minute $hour * * * root /usr/lib/airtime/utils/phone_home_stat\n"); fclose($fp); } - + public static function GetAirtimeSrcDir() { return __DIR__."/../../../airtime_mvc"; } - + public static function InsertCountryDataIntoDatabase(){ $sql = "INSERT INTO cc_country (isocode, name) VALUES ('AFG', 'Afghanistan '); INSERT INTO cc_country (isocode, name) VALUES ('ALA', 'Ă…land Islands'); @@ -346,7 +350,7 @@ class AirtimeInstall{ INSERT INTO cc_country (isocode, name) VALUES ('ZWE', 'Zimbabwe ');"; echo "* Inserting data into country table".PHP_EOL; - Airtime190Upgrade::execSqlQuery($sql); + Airtime190Upgrade::execSqlQuery($sql); } } @@ -359,7 +363,7 @@ class AirtimeIni{ const CONF_FILE_MEDIAMONITOR = "/etc/airtime/media-monitor.cfg"; const CONF_FILE_API_CLIENT = "/etc/airtime/api_client.cfg"; const CONF_FILE_MONIT = "/etc/monit/conf.d/airtime-monit.cfg"; - + /** * This function updates an INI style config file. * @@ -395,7 +399,7 @@ class AirtimeIni{ } fclose($fp); } - + public static function CreateMonitFile(){ if (!copy(__DIR__."/../../../python_apps/monit/airtime-monit.cfg", AirtimeIni::CONF_FILE_MONIT)){ echo "Could not copy airtime-monit.cfg to /etc/monit/conf.d/. Exiting."; @@ -453,7 +457,7 @@ class AirtimeIni{ } } } - + public static function upgradeConfigFiles(){ $configFiles = array(AirtimeIni::CONF_FILE_AIRTIME, @@ -485,7 +489,7 @@ class AirtimeIni{ exit(1); } } - + $AIRTIME_SRC = realpath(__DIR__.'/../../../airtime_mvc'); $AIRTIME_PYTHON_APPS = realpath(__DIR__.'/../../../python_apps'); @@ -530,7 +534,7 @@ class Airtime190Upgrade{ } /* Removes pypo, media-monitor, show-recorder and utils from system. These will - * be reinstalled by the main airtime-upgrade script. + * be reinstalled by the main airtime-upgrade script. */ public static function UninstallBinaries() { @@ -559,7 +563,7 @@ class Airtime190Upgrade{ echo "* Failed sql query: $sql".PHP_EOL; echo "* Message {$result->getMessage()}".PHP_EOL; } - + return $result; } @@ -583,16 +587,19 @@ class Airtime190Upgrade{ */ public static function installMediaMonitor($values){ + $propel_stor_dir = CcMusicDirsQuery::create() + ->filterByType('stor') + ->findOne(); + + $propel_link_dir = CcMusicDirsQuery::create() + ->filterByType('link') + ->findOne(); + /* Handle Database Changes. */ $stor_dir = realpath($values['general']['base_files_dir']."/stor")."/"; echo "* Inserting stor directory location $stor_dir into music_dirs table".PHP_EOL; - $sql = "UPDATE cc_music_dirs SET directory='$stor_dir' WHERE type='stor'"; - echo $sql.PHP_EOL; - Airtime190Upgrade::execSqlQuery($sql); - - $sql = "SELECT id FROM cc_music_dirs WHERE type='stor'"; - echo $sql.PHP_EOL; - $rows = Airtime190Upgrade::execSqlQuery($sql); + $propel_stor_dir->setDirectory($stor_dir); + $propel_stor_dir->save(); echo "Creating media-monitor log file".PHP_EOL; mkdir("/var/log/airtime/media-monitor/", 755, true); @@ -605,11 +612,11 @@ class Airtime190Upgrade{ if (!copy(__DIR__."/../../../python_apps/api_clients/api_client.cfg", AirtimeIni::CONF_FILE_API_CLIENT)){ echo "Could not copy api_client.cfg to /etc/airtime/. Exiting."; } - + AirtimeIni::UpdateIniValue(AirtimeIni::CONF_FILE_API_CLIENT, "api_key", $values["general"]["api_key"]); - + echo "Reorganizing files in stor directory".PHP_EOL; - + $cwd = __DIR__; $mediaMonitorUpgradePath = __DIR__."/media-monitor-upgrade.py"; $command = "cd $cwd && su -c \"python $mediaMonitorUpgradePath\""; @@ -618,13 +625,39 @@ class Airtime190Upgrade{ $oldAndNewFileNames = json_decode($output[0]); + $stor_dir_id = $propel_stor_dir->getId(); foreach ($oldAndNewFileNames as $pair){ $relPathNew = pg_escape_string(substr($pair[1], strlen($stor_dir))); $absPathOld = pg_escape_string($pair[0]); - $sql = "UPDATE cc_files SET filepath = '$relPathNew', directory=1 WHERE filepath = '$absPathOld'"; + $sql = "UPDATE cc_files SET filepath = '$relPathNew', directory=$stor_dir_id WHERE filepath = '$absPathOld'"; echo $sql.PHP_EOL; Airtime190Upgrade::execSqlQuery($sql); } + + echo "Upgrading Linked Files".PHP_EOL; + + //HANDLE LINKED FILES HERE. + + $db_files = CcFilesQuery::create() + ->setFormatter(ModelCriteria::FORMAT_ON_DEMAND) + ->filterByDbDirectory(NULL) + ->find(); + + //Check to see if the file still exists. (Could have still some entries under the stor dir or linked files that don't exist) + $link_dir_id = $propel_link_dir->getId(); + foreach($db_files as $db_file) { + $filepath = $db_file->getDbFilepath(); + echo $filepath.PHP_EOL; + + if (!file_exists($filepath)) { + $db_file->delete(); + echo "Removed Missing File: ".$filepath.PHP_EOL; + } + else { + $db_file->setDbDirectory($link_dir_id); + $db_file->save(); + } + } } } diff --git a/install_minimal/upgrades/airtime-1.9.0/media-monitor-upgrade.py b/install_minimal/upgrades/airtime-1.9.0/media-monitor-upgrade.py index 6dce39c26..f7adcfc52 100644 --- a/install_minimal/upgrades/airtime-1.9.0/media-monitor-upgrade.py +++ b/install_minimal/upgrades/airtime-1.9.0/media-monitor-upgrade.py @@ -7,6 +7,8 @@ import sys import os import json import ConfigParser +import pwd +import grp import os.path @@ -24,10 +26,26 @@ mmconfig = AirtimeMediaConfig(logger) config = ConfigParser.RawConfigParser() config.read('/etc/airtime/airtime.conf') stor_dir = config.get('general', 'base_files_dir') + "/stor" +organize_dir = stor_dir + '/organize' + +try: + os.makedirs(organize_dir) + omask = os.umask(0) + + uid = pwd.getpwnam('pypo')[2] + gid = grp.getgrnam('www-data')[2] + + os.chown(organize_dir, uid, gid) + os.chmod(organize_dir, 02777) + +except Exception, e: + print e +finally: + os.umask(omask) mmconfig.storage_directory = os.path.normpath(stor_dir) mmconfig.imported_directory = os.path.normpath(stor_dir + '/imported') -mmconfig.organize_directory = os.path.normpath(stor_dir + '/organize') +mmconfig.organize_directory = os.path.normpath(organize_dir) mmc = MediaMonitorCommon(mmconfig)