diff --git a/airtime_mvc/application/controllers/ApiController.php b/airtime_mvc/application/controllers/ApiController.php index 96466c84c..3517be709 100644 --- a/airtime_mvc/application/controllers/ApiController.php +++ b/airtime_mvc/application/controllers/ApiController.php @@ -121,7 +121,7 @@ class ApiController extends Zend_Controller_Action //make sure to exit here so that no other output is sent. exit; } else { - $logger->err('Resource in database, but not in storage: '.$filepath.' '.is_file($filepath)); + $logger->err('Resource in database, but not in storage: "'.$filepath.'"'); } } else { $logger->err('$media != null && !PEAR::isError($media)'); diff --git a/airtime_mvc/application/controllers/LibraryController.php b/airtime_mvc/application/controllers/LibraryController.php index ac84ac7f7..e40504d56 100644 --- a/airtime_mvc/application/controllers/LibraryController.php +++ b/airtime_mvc/application/controllers/LibraryController.php @@ -207,25 +207,4 @@ class LibraryController extends Zend_Controller_Action } } - - } - - - - - - - - - - - - - - - - - - - diff --git a/airtime_mvc/application/models/StoredFile.php b/airtime_mvc/application/models/StoredFile.php index fca9c2130..13a01f234 100644 --- a/airtime_mvc/application/models/StoredFile.php +++ b/airtime_mvc/application/models/StoredFile.php @@ -824,12 +824,16 @@ class StoredFile { public static function listAllFiles($dir_id){ global $CC_DBC; - $sql = "SELECT m.directory || '/' || f.filepath as fp" - ." FROM CC_MUSIC_DIRS m" - ." LEFT JOIN CC_FILES f" - ." ON m.id = f.directory" - ." WHERE m.id = f.directory" - ." AND m.id = $dir_id"; + // $sql = "SELECT m.directory || '/' || f.filepath as fp" + // ." FROM CC_MUSIC_DIRS m" + // ." LEFT JOIN CC_FILES f" + // ." ON m.id = f.directory" + // ." WHERE m.id = f.directory" + // ." AND m.id = $dir_id"; + $sql = "SELECT filepath as fp" + ." FROM CC_FILES" + ." WHERE directory = $dir_id"; + $rows = $CC_DBC->getAll($sql); $results = array(); @@ -839,6 +843,5 @@ class StoredFile { return $results; } - } diff --git a/python_apps/api_clients/api_client.py b/python_apps/api_clients/api_client.py index cb3edbc00..e1e25b085 100644 --- a/python_apps/api_clients/api_client.py +++ b/python_apps/api_clients/api_client.py @@ -417,6 +417,10 @@ class AirTimeApiClient(ApiClientInterface): return response + #returns a list of all db files for a given directory in JSON format: + #{"files":["path/to/file1", "path/to/file2"]} + #Note that these are relative paths to the given directory. The full + #path is not returned. def list_all_db_files(self, dir_id): logger = logging.getLogger() try: diff --git a/python_apps/media-monitor/airtimefilemonitor/airtimemediamonitorbootstrap.py b/python_apps/media-monitor/airtimefilemonitor/airtimemediamonitorbootstrap.py index 3840d4607..d0b8df2fe 100644 --- a/python_apps/media-monitor/airtimefilemonitor/airtimemediamonitorbootstrap.py +++ b/python_apps/media-monitor/airtimefilemonitor/airtimemediamonitorbootstrap.py @@ -31,7 +31,7 @@ class AirtimeMediaMonitorBootstrap(): def get_list_of_watched_dirs(self): json = self.api_client.list_all_watched_dirs() - return json["dirs"] + return json["dirs"] def check_for_diff(self, dir_id, dir): #set to hold new and/or modified files. We use a set to make it ok if files are added @@ -46,14 +46,11 @@ class AirtimeMediaMonitorBootstrap(): for file in files['files']: db_known_files_set.add(file) - - command = "find %s -type f -iname '*.ogg' -o -iname '*.mp3' -readable" % dir - stdout = self.execCommandAndReturnStdOut(command) - new_files = stdout.split('\n') + new_files = self.pe.scan_dir_for_new_files(dir) all_files_set = set() for file_path in new_files: if len(file_path.strip(" \n")) > 0: - all_files_set.add(file_path) + all_files_set.add(file_path[len(dir)+1:]) if os.path.exists("/var/tmp/airtime/.media_monitor_boot"): @@ -65,12 +62,13 @@ class AirtimeMediaMonitorBootstrap(): command = "find %s -type f -iname '*.ogg' -o -iname '*.mp3' -readable" % dir stdout = self.execCommandAndReturnStdOut(command) - - new_files = stdout.split('\n') - + stdout = unicode(stdout, "utf_8") + + new_files = stdout.splitlines() + for file_path in new_files: if len(file_path.strip(" \n")) > 0: - new_and_modified_files.add(file_path) + new_and_modified_files.add(file_path[len(dir)+1:]) #new_and_modified_files gives us a set of files that were either copied or modified #since the last time media-monitor was running. These files were collected based on @@ -91,13 +89,15 @@ class AirtimeMediaMonitorBootstrap(): open("/var/tmp/airtime/.media_monitor_boot","w") for file_path in deleted_files_set: - self.pe.handle_removed_file(False, file_path) + self.pe.handle_removed_file(False, "%s/%s" % (dir, file_path)) for file_path in new_files_set: + file_path = "%s/%s" % (dir, file_path) if os.path.exists(file_path): self.pe.handle_created_file(False, os.path.basename(file_path), file_path) for file_path in modified_files_set: + file_path = "%s/%s" % (dir, file_path) if os.path.exists(file_path): self.pe.handle_modified_file(False, os.path.basename(file_path), file_path) diff --git a/python_apps/media-monitor/airtimefilemonitor/airtimenotifier.py b/python_apps/media-monitor/airtimefilemonitor/airtimenotifier.py index 55973527c..8f58192cc 100644 --- a/python_apps/media-monitor/airtimefilemonitor/airtimenotifier.py +++ b/python_apps/media-monitor/airtimefilemonitor/airtimenotifier.py @@ -66,13 +66,10 @@ class AirtimeNotifier(Notifier): elif m['event_type'] == "new_watch": mm = self.proc_fun() - if mm.has_correct_permissions(m['directory']): - self.logger.info("AIRTIME NOTIFIER add watched folder event " + m['directory']) - self.walk_newly_watched_directory(m['directory']) + self.logger.info("AIRTIME NOTIFIER add watched folder event " + m['directory']) + self.walk_newly_watched_directory(m['directory']) - mm.watch_directory(m['directory']) - else: - self.logger.warn("filepath '%s' has does not have sufficient read permissions. Ignoring.", full_filepath) + mm.watch_directory(m['directory']) elif m['event_type'] == "remove_watch": watched_directory = m['directory'].encode('utf-8') diff --git a/python_apps/media-monitor/airtimefilemonitor/airtimeprocessevent.py b/python_apps/media-monitor/airtimefilemonitor/airtimeprocessevent.py index 08689dd25..6b0526468 100644 --- a/python_apps/media-monitor/airtimefilemonitor/airtimeprocessevent.py +++ b/python_apps/media-monitor/airtimefilemonitor/airtimeprocessevent.py @@ -75,12 +75,25 @@ class AirtimeProcessEvent(ProcessEvent): else: return False - #file needs to be readable by all users, and directories - #up to this file needs to be readable AND executable by all - #users. + #check if file is readable by "nobody" def has_correct_permissions(self, filepath): - st = os.stat(filepath) - return bool(st.st_mode & stat.S_IROTH) + #drop root permissions and become "nobody" + os.seteuid(65534) + + try: + open(filepath) + readable = True + except IOError: + self.logger.warn("File does not have correct permissions: '%s'", filepath) + readable = False + except Exception, e: + self.logger.error("Unexpected exception thrown: %s", e) + readable = False + finally: + #reset effective user to root + os.seteuid(0) + + return readable def set_needed_file_permissions(self, item, is_dir): @@ -98,8 +111,7 @@ class AirtimeProcessEvent(ProcessEvent): os.chmod(item, 0666) except Exception, e: - self.logger.error("Failed to change file's owner/group/permissions.") - self.logger.error(item) + self.logger.error("Failed to change file's owner/group/permissions. %s", e) finally: os.umask(omask) @@ -247,7 +259,7 @@ class AirtimeProcessEvent(ProcessEvent): def organize_new_file(self, pathname): - self.logger.info("Processing new file: %s", pathname) + self.logger.info(u"Organizing new file: %s", pathname) file_md = self.md_manager.get_md_from_file(pathname) if file_md is not None: @@ -255,7 +267,7 @@ class AirtimeProcessEvent(ProcessEvent): # file_md['MDATA_KEY_CREATOR'] == "AIRTIMERECORDERSOURCEFABRIC".encode('utf-8') filepath = self.create_file_path(pathname, file_md) - self.logger.debug("Moving from %s to %s", pathname, filepath) + self.logger.debug(u"Moving from %s to %s", pathname, filepath) self.move_file(pathname, filepath) else: self.logger.warn("File %s, has invalid metadata", pathname) @@ -306,6 +318,20 @@ class AirtimeProcessEvent(ProcessEvent): else: #show dragged from unwatched folder into a watched folder. Do not "organize". self.file_events.append({'mode': self.config.MODE_CREATE, 'filepath': event.pathname, 'is_recorded_show': False}) + else: + #When we move a directory into a watched_dir, we only get a notification that the dir was created, + #and no additional information about files that came along with that directory. + #need to scan the entire directory for files. + files = self.scan_dir_for_new_files(event.pathname) + if self.is_parent_directory(event.pathname, self.config.organize_directory): + for file in files: + self.organize_new_file(file) + else: + for file in files: + self.file_events.append({'mode': self.config.MODE_CREATE, 'filepath': file, 'is_recorded_show': False}) + + + def process_IN_DELETE(self, event): self.logger.info("process_IN_DELETE: %s", event) @@ -337,6 +363,14 @@ class AirtimeProcessEvent(ProcessEvent): f = open(file, 'w') f.write(string) f.close() + + def scan_dir_for_new_files(self, dir): + command = 'find "%s" -type f -iname "*.ogg" -o -iname "*.mp3" -readable' % dir.replace('"', '\\"') + self.logger.debug(command) + stdout = self.execCommandAndReturnStdOut(command) + stdout = unicode(stdout, "utf_8") + + return stdout.splitlines() def notifier_loop_callback(self, notifier): if len(self.file_events) > 0: diff --git a/python_apps/pypo/liquidsoap_scripts/ls_script.liq b/python_apps/pypo/liquidsoap_scripts/ls_script.liq index c4834b421..72113680c 100644 --- a/python_apps/pypo/liquidsoap_scripts/ls_script.liq +++ b/python_apps/pypo/liquidsoap_scripts/ls_script.liq @@ -53,7 +53,7 @@ s = map_metadata(append_title, s) if output_sound_device then - ignore(out(s)) + ignore(output.alsa(s)) end if output_icecast_mp3 then