diff --git a/filebrowser.module b/filebrowser.module index 49ea5e1..bbeddc8 100644 --- a/filebrowser.module +++ b/filebrowser.module @@ -256,7 +256,7 @@ function filebrowser_view($node, $teaser = FALSE, $page = FALSE) { array_shift($url_parts); $meta->subdir .= implode('/', $url_parts) . '/'; } - $curr_dir = $node->file_path . $meta->subdir; + $meta->curr_dir = $curr_dir = $node->file_path . $meta->subdir; $dir_url = $meta->real_path . $meta->subdir; // Are we in a subdirectory? $is_subdir = $page?$meta->subdir != '/':FALSE; @@ -306,7 +306,7 @@ function filebrowser_view($node, $teaser = FALSE, $page = FALSE) { } // Store the descript.ion or file.bbs file for grabbing meta data from . - $file_metadata = array(); + $file_metadata = filebrowser_get_fileinfo($curr_dir); $files = array(); $folders = array(); $meta->total_size = 0; @@ -314,14 +314,9 @@ function filebrowser_view($node, $teaser = FALSE, $page = FALSE) { while (($file = readdir($dh)) !== false && is_readable($curr_dir . $file)) { $full_path = $curr_dir . $file; if (is_file($full_path)) { - - // Check for meta files if we need info. - if (empty($file_metadata) && in_array($file, array('descript.ion', 'file.bbs'))) { - $file_metadata = filebrowser_get_fileinfo($full_path, $curr_dir); - } - // Handle files that should not be shown. if (strpos($node->file_blacklist, $file) !== FALSE || + (in_array($file, $file_metadata['blacklist'])) || ($file[0] == '.' && strpos($node->file_blacklist, '.*') !== FALSE)) { continue; } @@ -331,6 +326,7 @@ function filebrowser_view($node, $teaser = FALSE, $page = FALSE) { 'path' => $full_path, 'url' => $node->private_downloads == '1'?url($dir_url . $file):$base_url . '/' . $full_path, 'status' => MARK_READ, + 'date' => filectime($full_path), 'size' => 0 ); @@ -387,27 +383,28 @@ function filebrowser_view($node, $teaser = FALSE, $page = FALSE) { } // Add in metadata from description files. - if (!empty($file_metadata)) { + if (!empty($file_metadata['descriptions'])) { // For files foreach ($files as $filename => $row) { - if (isset($file_metadata[$filename])) { - $files[$filename]['description'] = $file_metadata[$filename]; + if (isset($file_metadata['descriptions'][$filename])) { + $files[$filename]['description'] = $file_metadata['descriptions'][$filename]; } } // For directories. if ($node->explore_subdirs) { foreach ($folders as $dir_name => $data) { - if (isset($file_metadata[$dir_name])) { - $folders[$dir_name]['description'] = $file_metadata[$dir_name]; + if (isset($file_metadata['descriptions'][$dir_name])) { + $folders[$dir_name]['description'] = $file_metadata['descriptions'][$dir_name]; } } } } // Display metadata for the current directory at the top of the page. - if (isset($file_metadata['.'])) { - $meta->folder_desc = $file_metadata['.']; + if (isset($file_metadata['descriptions']['.'])) { + $meta->folder_desc = $file_metadata['descriptions']['.']; } + $meta->file_metadata = $file_metadata; $node->content['filebrowser'] = array( '#value' => theme('filebrowser_dir_listing', $files, $folders, $meta), '#weight' => 1, @@ -417,37 +414,82 @@ function filebrowser_view($node, $teaser = FALSE, $page = FALSE) { } /** - * Loads file metainformation from the specified file. Also + * Loads file metainformation from the specified directory. Also * allows the file to specify a *callback* with which the * descriptions are parsed, so more metainformation can be * presented on the output. */ -function filebrowser_get_fileinfo($info_file_path = NULL, $subfolder = '') { +function filebrowser_get_fileinfo($info_file_path = NULL) { static $metacols = array(); + $file = array(); + foreach (array('descript.ion', 'file.bbs', '.htaccess') as $filename) { + $info_file = $info_file_path . '/'. $filename; + if (!is_readable($info_file)) continue; + $file = file($info_file); + break; + } // Build meta information list. - $metainfo = array(); - if (is_readable($info_file_path) && ($file = file($info_file_path))) { - foreach ($file as $line) { - // Skip empty and commented lines. - if (trim($line) == '' || strpos(trim($line), '#') === 0) { - continue; + $metainfo = array( + 'descriptions' => array(), + 'blacklist' => array(), + 'columns' => array( + 'icon' => array('suppress' => FALSE), + 'name' => array('data' => t('Name'), 'field' => 'name', 'suppress' => FALSE, 'sort' => 'asc'), + 'size' => array('data' => t('Size'), 'field' => 'size', 'suppress' => FALSE), + 'date' => array('data' => t('Last modified'), 'field' => 'date', 'suppress' => FALSE), + 'description' => array('data' => t('Description'), 'field' => 'description', 'suppress' => FALSE), + ), + ); + foreach ($file as $line) { + // Skip empty and commented lines. + if (trim($line) == '' || strpos(trim($line), '#') === 0) { + continue; + } + + // Use PCRE regular expressions to parse file. + $matches = array(); + if (preg_match('/^\s*AddDescription\s+"(.*)"\s+(.*)$/m', $line, $matches)) { + $metainfo['descriptions'][$matches[2]] = $matches[1]; + } + else if (preg_match('/^\s*HeaderName\s+(.*)$/', $line, $matches)) { + $metainfo['blacklist'][] = $metainfo['header'] = $matches[1]; + } + else if (preg_match('/^\s*ReadmeName\s+(.*)$/', $line, $matches)) { + $metainfo['blacklist'][] = $metainfo['footer'] = $matches[1]; + } + else if (preg_match('/^\s*IndexOrderDefault\s+(Ascending|Descending)\s+(.*)$/', $line, $matches)) { + $column = strtolower($matches[2]); + if (!array_key_exists($column, $metainfo['columns'])) continue; + $metainfo['columns'][$column]['sort'] = 'Ascending' == $matches[1]? 'asc' : 'desc'; + } + else if (preg_match('/^\s*IndexIgnore\s+(.*)$/', $line, $matches)) { + $metainfo['blacklist'] = array_merge($metainfo['blacklist'], explode(' ', $matches[1])); + } + else if (preg_match('/^\s*IndexOptions\s+(.*)$/', $line, $matches)) { + if (preg_match_all('/([-+]?)Suppress([a-zA-Z]+)/', $matches[1], $matches)) { + foreach ($matches[0] as $id => $match) { + $column = strtolower($matches[2][$id]); + if (!array_key_exists($column, $metainfo['columns'])) continue; + $metainfo['columns'][$column]['suppress'] = '-' == $matches[1][$id]? FALSE : TRUE; + } } - - // Use PCRE regular expressions to parse file. - $matches = array(); - preg_match('/"([^"]+)"\s+(.*)|(\S+)\s+(.*)/', $line, $matches); + } + else if (preg_match('/"([^"]+)"\s+(.*)|(\S+)\s+(.*)/', $line, $matches)) { $name = !empty($matches[1])?$matches[1]:$matches[3]; $description = !empty($matches[2])?$matches[2]:$matches[4]; - - if (isset($metainfo[$name])) { - $metainfo[$name] .= ' ' . trim($description); + + if (isset($metainfo['descriptions'][$name])) { + $metainfo['descriptions'][$name] .= ' ' . trim($description); } else { - $metainfo[$name] = trim($description); + $metainfo['descriptions'][$name] = trim($description); } } } + foreach ($metainfo['columns'] as $name => $column) { + if ($column['suppress']) unset($metainfo['columns'][$name]); + } return $metainfo; } @@ -543,18 +585,21 @@ function filebrowser_get_fileicon($fullpath = NULL, $iconname = NULL) { function theme_filebrowser_dir_listing(&$files, &$folders, $meta) { $output = ''; if (!empty($files) || !empty($folders)) { - $header = array('', array('data' => t('Name'), 'field' => 'name', 'sort' => 'asc'), array('data' => t('Size'), 'field' => 'size')); - $are_descriptions = FALSE; // Deal with files. $table_rows_unsorted = array(); + $columns = $meta->file_metadata['columns']; foreach ($files as $filename => $data) { - $table_rows_unsorted[$filename] = array( - array('data' => filebrowser_get_fileicon($data['path']), 'style' => 'width:1%;'), - '' . $filename . '' . theme('mark', $data['status']), - format_size($data['size']) - ); - if (isset($data['description'])) { + $table_rows_unsorted[$filename] = array(); + if (isset($columns['icon'])) + $table_rows_unsorted[$filename][] = array('data' => filebrowser_get_fileicon($data['path']), 'style' => 'width:1%;'); + if (isset($columns['name'])) + $table_rows_unsorted[$filename][] = '' . $filename . '' . theme('mark', $data['status']); + if (isset($columns['size'])) + $table_rows_unsorted[$filename][] = format_size($data['size']); + if (isset($columns['date'])) + $table_rows_unsorted[$filename][] = format_date($data['date']); + if (isset($columns['description']) and isset($data['description'])) { $are_descriptions = TRUE; $table_rows_unsorted[$filename][] = $data['description']; } @@ -562,29 +607,35 @@ function theme_filebrowser_dir_listing(&$files, &$folders, $meta) { // Deal with folders. foreach ($folders as $foldername => $data) { - $table_rows_unsorted[$foldername] = array( - array('data' => filebrowser_get_fileicon($data['path'], $foldername=='..'?'parent':NULL), 'style' => 'width:1%;'), - l($foldername, $data['url']) . theme('mark', $data['status']), - '' - ); - if (isset($data['description'])) { + $table_rows_unsorted[$foldername] = array(); + if (isset($columns['icon'])) + $table_rows_unsorted[$foldername][] = array('data' => filebrowser_get_fileicon($data['path'], $foldername=='..'?'parent':NULL), 'style' => 'width:1%;'); + if (isset($columns['name'])) + $table_rows_unsorted[$foldername][] = l($foldername, $data['url']) . theme('mark', $data['status']); + if (isset($columns['size'])) + $table_rows_unsorted[$foldername][] = ''; + if (isset($columns['date'])) + $table_rows_unsorted[$foldername][] = ''; + if (isset($columns['description']) and isset($data['description'])) { $are_descriptions = TRUE; $table_rows_unsorted[$foldername][] = $data['description']; } } - // We found some descriptions for files or folders, so fix up the table for it. if ($are_descriptions) { - $header[] = array('data' => t('Description'), 'field' => 'description'); - foreach ($table_rows_unsorted as $filename => $data) { - if (count($data) < 4) { - $table_rows_unsorted[$filename][] = ''; - } - } + $total_columns = count($meta->file_metadata['columns']); + foreach ($table_rows_unsorted as $filename => $data) { + if (count($data) < $total_columns) { + $table_rows_unsorted[$filename][] = ''; + } + } + } + else { + unset($meta->file_metadata['columns']['description']); } // Handle any and all sorting. - $ts = tablesort_init($header); + $ts = tablesort_init($meta->file_metadata['columns']); // Sort things by name or size in ascending order. // Grab some keys to sort. $files_order = array_values($files); @@ -606,13 +657,18 @@ function theme_filebrowser_dir_listing(&$files, &$folders, $meta) { } // Concatenate them all together. + if (array_key_exists('header', $meta->file_metadata)) { + $output .= file_get_contents($meta->curr_dir .'/'. $meta->file_metadata['header']); + } $output .= '

' . t('Displaying %dir', array('%dir' => $meta->subdir)) . '

'; if (isset($meta->folder_desc)) { - $output .= '

' . $meta->folder_desc . '

'; + $output .= '

' . $meta->folder_desc . '

'; } - $output .= theme('table', $header, $rows, array('id' => 'filebrowser-file-listing')); + $output .= theme('table', $meta->file_metadata['columns'], $rows, array('id' => 'filebrowser-file-listing')); $output .= '

' . t('Contains @fc totaling @ds in size.', array('@fc' => format_plural(count($files), '1 file', '@count files'), '@ds' => format_size($meta->total_size))) . '

'; - + if (array_key_exists('footer', $meta->file_metadata)) { + $output .= file_get_contents($meta->curr_dir .'/'. $meta->file_metadata['footer']); + } } else { $output .= '

' . t('This directory is empty.') . '

'; @@ -634,4 +690,16 @@ function filebrowser_size_sort($a, $b) { function filebrowser_name_sort($a, $b) { return strcmp($a['name'], $b['name']); -} \ No newline at end of file +} + +function filebrowser_description_sort($a, $b) { + return strcmp($a['description'], $b['description']); +} + +function filebrowser_date_sort($a, $b) { + if ($a['date'] == $b['date']) { + return 0; + } + return ($a['date'] > $b['date']) ? -1 : 1; +} +