? LICENSE.txt ? filebrowser.mysql Index: README.txt =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/filebrowser/README.txt,v retrieving revision 1.1 diff -u -r1.1 README.txt --- README.txt 1 Feb 2005 17:29:19 -0000 1.1 +++ README.txt 22 Feb 2005 19:19:41 -0000 @@ -19,18 +19,19 @@ ------------------------------------------------------------------------------ - Copy filebrowser.module to your Drupal modules folder + - Install the database table defined in filebrowser.mysql - Enable the module as usual on Drupal's admin page - Provide the module settings on the administration >> settings >> filebrowser page Configuration ------------------------------------------------------------------------------ - - You need to provide a root folder for filebrowser, from where the - folder lists will be generated. - The icon folder should have icons for file types used. The icons should be named file-txt.png, file-gif.png, etc. The default - icon used is file-default.png if an icon is not present for - a particular file extension. + icon used is file-default.png if an icon is not present for + a particular file extension. + - You need to create 'filebrowser directory' nodes and provide a root folder + for each one, from where the folder lists will be generated. Description file format, and custom format parsing ------------------------------------------------------------------------------ @@ -40,6 +41,7 @@ README.txt Detailed information about the project filebrowser.module Module source code +filebrowser.mysql Database table definition for nodes Multiple descriptions for a file are concatenated into one. You can also have help for a folder, (which is displayed as Drupal help text) with @@ -112,4 +114,7 @@ This module was created for the Hungarian Drupal Homepage as a browser for our local Subversion repository, where we work on the interface -translations. The author of the module is Gabor Hojtsy (goba[at]php.net). \ No newline at end of file +translations. The author of the module is Gabor Hojtsy (goba[at]php.net). +This module was node-ified by Mark Howell (mark(a_t)nullcraft.org) to function +as a client-facing extranet where files could be easily shared and node_access +permissions could be applied to different browsing directories. \ No newline at end of file Index: filebrowser.module =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/filebrowser/filebrowser.module,v retrieving revision 1.1 diff -u -r1.1 filebrowser.module --- filebrowser.module 1 Feb 2005 17:29:19 -0000 1.1 +++ filebrowser.module 22 Feb 2005 19:19:41 -0000 @@ -3,6 +3,15 @@ /** * @file * Enables users with appropriate permissions to browse a folder of files (FTP-like). + * + * Table structure: + * @code + * create table filebrowser ( + * nid int(10) unsigned NOT NULL default '0', + * filebrowser_root varchar(255) NOT NULL default '', + * PRIMARY KEY (nid) + * ) + * @endcode */ /** @@ -17,6 +26,8 @@ switch ($section) { case 'admin/modules#description': return t('Provides FTP-like browsing capabilities.'); + case 'node/add#filebrowser': + return t('Shared directory for browsing files.'); case $_GET['q']: if ($pagehelp) { return $pagehelp; @@ -26,19 +37,46 @@ } /** - * Implementation of hook_settings(). + * Implementation of hook_node_name(). */ -function filebrowser_settings() { - $output = form_textfield(t('Root directory'), 'filebrowser_root', variable_get('filebrowser_root', ''), 70, 100, t('Root directory used to present the filebrowser interface. Users will not be able to go up from this folder. Only a directory name under the Drupal root is accepted. Example: "public/files".')); - $output .= form_textfield(t('Icon directory'), 'filebrowser_icons', variable_get('filebrowser_icons', ''), 70, 100, t('Name of directory, where file type icons are stored. Files should be named "file-txt.png", "file-gif.png", etc. The default icon is "file-default.png".')); - return $output; +function filebrowser_node_name($node) { + return t('filebrowser directory'); +} + +/** + * Implementation of hook_access(). + */ +function filebrowser_access($op, $node) { + global $user; + + if ($op == 'create') { + // Only users with permission to do so may create this node type. + return user_access('create filebrowser node'); + } + + // Users who create a node may edit or delete it later, assuming they have the + // necessary permissions. + if ($op == 'update' || $op == 'delete') { + if (user_access('edit own filebrowser nodes') && ($user->uid == $node->uid)) { + return TRUE; + } + } } /** * Implementation of hook_perm(). */ function filebrowser_perm() { - return array('access filebrowser'); + return array('create filebrowser node', 'edit own filebrowser nodes', 'access filebrowser'); +} + + +/** + * Implementation of hook_settings(). + */ +function filebrowser_settings() { + $output .= form_textfield(t('Icon directory'), 'filebrowser_icons', variable_get('filebrowser_icons', ''), 70, 100, t('Name of directory, where file type icons are stored. Files should be named "file-txt.png", "file-gif.png", etc. The default icon is "file-default.png".')); + return $output; } /** @@ -51,31 +89,140 @@ 'access' => user_access('access filebrowser'), 'callback' => 'filebrowser_page', 'type' => MENU_CALLBACK); } + else { + $items[] = array('path' => 'node/add/filebrowser', 'title' => t('filebrowser'), + 'access' => user_access('create filebrowser node'), 'callback' => 'node_page', + 'type' => MENU_CALLBACK); + } + return $items; } /** + * Implementation of hook_form(). + */ +function filebrowser_form(&$node, &$error) { + $output = ''; + + // In order to be able to attach taxonomy terms to this node, we need + // to display the appropriate form elements. + if (function_exists('taxonomy_node_form')) { + $output .= implode('', taxonomy_node_form('filebrowser', $node)); + } + + $output .= form_textfield(t('Root Directory'), 'filebrowser_root', $node->filebrowser_root, 60, 128, t('Root directory used to present the filebrowser interface. Users will not be able to go up from this folder. Only a directory name under the Drupal root is accepted. Example: "public/files".')); + + return $output; +} + +/** + * Implementation of hook_validate(). + */ +function filebrowser_validate(&$node) { + if ($node->filebrowser_root) { + if (!(is_dir($node->filebrowser_root) && is_readable($node->filebrowser_root))) { + form_set_error('filebrowser_root', t('Filebrowser Root Directory must exist and be readable by the web server.')); + } + } + elseif ($_POST['edit']) { + form_set_error('filebrowser_root', t('Filebrowser Root Directory must be specified.')); + } +} + +/** + * Implementation of hook_insert(). + */ +function filebrowser_insert($node) { + db_query("INSERT INTO {filebrowser} (nid, filebrowser_root) VALUES (%d, '%s')", $node->nid, $node->filebrowser_root); +} + +/** + * Implementation of hook_update(). + */ +function filebrowser_update($node) { + db_query("UPDATE {filebrowser} SET filebrowser_root = '%s' WHERE nid = %d", $node->filebrowser_root, $node->nid); +} + +/** + * Implementation of hook_delete(). + */ +function filebrowser_delete($node) { + db_query('DELETE FROM {filebrowser} WHERE nid = %d', $node->nid); +} + +/** + * Implementation of hook_load(). + */ +function filebrowser_load($node) { + $additions = db_fetch_object(db_query('SELECT filebrowser_root FROM {filebrowser} WHERE nid = %d', $node->nid)); + return $additions; +} + +/** + * Implementation of hook_view(). + * + * This is a typical implementation that simply runs the node text through + * the output filters. + */ +function filebrowser_view(&$node, $teaser = FALSE, $page = FALSE) { + if(!$teaser) { + $node->body = filebrowser_page($node); + } + //$node->teaser .= $node->filebrowser_root; // security risk? +} + +/** * Prints a folder layout */ -function filebrowser_page() { +function filebrowser_page($node=NULL) { + // load node from arg list + if(!is_object($node) && is_numeric($node)) { + $node = node_load(array('nid'=>$node)); + } + elseif(!is_object($node) && is_numeric(arg(1))) { + $node = node_load(array('nid'=>arg(1))); + } + else { + $do_return = true; + } + + if(!node_access('view', $node)) { + if($do_return) { + return message_access(); + } + else { + print(theme('page', message_access())); + return; + } + } + if(!$node->filebrowser_root) { + print theme("page", '
' . t('Root Directory Not Set') . '
', t('Root Directory Not Set')); + return; + } + // Build breadcrumb list for uplevel folders - $subfolder = preg_replace("!^filebrowser/*!", "", $_GET['q']); + if (arg(0) != 'filebrowser') { + $subfolder = ''; + } + else { + $subfolder = preg_replace("!^filebrowser/[0-9]+/*!", "", $_GET['q']); + } $parts = explode("/", $subfolder); $breadcrumb = array(); - $dirname = t('root'); + $dirname = $node->title; if ($subfolder) { $dirname = array_pop($parts); while (count($parts)) { - $breadcrumb[] = l($parts[count($parts) -1], filebrowser_proper_path(join("/", $parts))); + $breadcrumb[] = l($parts[count($parts) -1], filebrowser_proper_path(join("/", $parts), $node)); array_pop($parts); } - $breadcrumb[] = l(t('Filebrowser root'), 'filebrowser'); + $breadcrumb[] = l($node->title, 'filebrowser/'.$node->nid); } $breadcrumb[] = l(t('Home'), NULL); // Get file list and generate output for this folder $output = ''; - if (!($files = filebrowser_get_list($subfolder))) { + if (!($files = filebrowser_get_list($subfolder, $node))) { drupal_set_message(t('Unable to get files for this directory')); } else { @@ -114,8 +261,18 @@ $output .= theme("table", $headers, $files); } + drupal_set_breadcrumb(array_reverse($breadcrumb)); + drupal_set_title(t('%dirname directory', array("%dirname" => $dirname))); + // Note: CSS can hook on this ID to style table elements differently - print theme("page", '
' . $output . '
', t('%dirname directory', array("%dirname" => $dirname)), array_reverse($breadcrumb)); + $output = '
' . $output . '
'; + + if($do_return) { + return $output; + } + else { + print(theme('page', $output)); + } } /** @@ -124,9 +281,9 @@ * modification) is added, plus a metafile is parsed to gather * more information, if available. */ -function filebrowser_get_list($subfolder = '') { - $folder = filebrowser_safe_folder($subfolder); - $inroot = ($folder == variable_get('filebrowser_root', '')); +function filebrowser_get_list($subfolder = '', $node) { + $folder = filebrowser_safe_folder($subfolder, $node); + $inroot = ($folder == $node->filebrowser_root); // Signal error in case of bogus directory name if (!(file_exists($folder) && is_dir($folder) && ($dir = opendir($folder)))) { @@ -174,7 +331,7 @@ if ($stat = stat($completepath)) { $icon = filebrowser_get_icon($completepath); if (is_dir($completepath)) { - $link = l("$icon $file", filebrowser_proper_path("$subfolder/$file")); + $link = l("$icon $file", filebrowser_proper_path("$subfolder/$file", $node)); $size = ''; } else { @@ -196,7 +353,7 @@ $parts = explode("/", $subfolder); array_pop($parts); $up = t('up'); - $link = l("$icon $file <$up>", filebrowser_proper_path(join("/", $parts))); + $link = l("$icon $file <$up>", filebrowser_proper_path(join("/", $parts), $node)); $details[] = array_merge(array( array('data' => $link, 'class' => 'filename', 'sv' => $file), array('data' => '', 'sv' => 0), @@ -285,8 +442,8 @@ * repeatedly, and try to catch and eliminate path walkback attemepts. * Also prevent from accessing version control system folders. */ -function filebrowser_safe_folder($subfolder) { - $folder = variable_get('filebrowser_root', '') . "/$subfolder"; +function filebrowser_safe_folder($subfolder, $node) { + $folder = $node->filebrowser_root . "/$subfolder"; while (TRUE) { $safer = str_replace(array("\\", "../", "/.svn", "/CVS"), array("/", "", "", ""), $folder); if ($safer !== $folder) { @@ -303,8 +460,8 @@ /** * Allows easy path generation even if $path has a leading slash. */ -function filebrowser_proper_path($path) { - return str_replace("//", "/", "filebrowser/$path"); +function filebrowser_proper_path($path, $node) { + return str_replace("//", "/", "filebrowser/$node->nid/$path"); } function filebrowser_sort_table($a, $b = NULL) {