'admin/settings/private_upload', 'title' => t('Private Uploads'), 'description' => t('Configure settings for private file upload.'), 'access' => user_access('administer site configuration'), 'callback' => 'drupal_get_form', 'callback arguments' => array('private_upload_admin'), ); $items[] = array( 'path' => 'admin/private_upload/add_htaccess', 'access' => user_access('administer site configuration'), 'callback' => '_private_upload_add_htacess', 'type' => MENU_CALLBACK, ); $items[] = array( 'path' => 'admin/private_upload/migrate_old', 'access' => user_access('administer site configuration'), 'callback' => '_private_upload_migrate_old', 'type' => MENU_CALLBACK, ); $items[] = array( 'path' => 'admin/private_upload/migrate_private', 'access' => user_access('administer site configuration'), 'callback' => '_private_upload_migrate_private', 'type' => MENU_CALLBACK, ); } return $items; } /** * hook_requrements(). * * * @param $phase: 'runtime' or 'install' * @param &$status: Not part of the hook. Used to collect messages for alternatvie display. * @return array of requirements; */ function private_upload_requirements($phase) { $status = array(); return _private_upload_requirements($phase, $status); } /** * Does the real work of hook_requirements, but with an extra param to collect * status info. * * @param $phase: 'runtime' or 'install' * @param &$status: Not part of the hook. Used to collect messages for alternatvie display. * @return array of requirements */ function _private_upload_requirements($phase, &$status) { $t = get_t(); // Ensure translations don't break at install time. $requirements = array(); if(module_exists('uploadpath')) { $requirements['private_upload_conflict'] = array( 'title' => t('Private Upload'), 'severity' => REQUIREMENT_ERROR, 'value' => $t('Conflict with Upload Path'), 'description' => $t('Private Upload will not work if Upload Path is installed'), ); } $public = file_directory_path(); $private_path = _private_upload_path(); if( !file_check_directory( $private_path ) ) { $requirements['private_upload_writable'] = array( 'title' => t('Private Upload'), 'severity' => REQUIREMENT_WARNING, 'value' => $t('Private Downloads directory is not writable'), 'description' => $t('Please make sure directory !dir exists and is writable.', array('!dir'=>$private_path)), ); $status[] = '
'. $requirements['private_upload_writable']['description'] .'
'; } else { $status[] = "
$private_path exists and is writable. Great.
"; } // Write out a .htaccess file if one doesn't already exist in the private folder. if (!file_exists($private_path.'/.htaccess')) { _private_upload_add_htacess(); } else { $status[] = '
'. $t("You have an .htaccess file in private folder. Great.") ."
"; } // Write a test file to the private folder to test public access. $test_file = $private_path.'/privacy_test.txt'; if (!file_exists($test_file)) { $test_path = file_create_path($test_file); file_save_data( "This is just a test.", $test_path, FILE_EXISTS_REPLACE ); drupal_set_message("Added test file: $test_path."); } if (file_exists($test_file)) { $url = $GLOBALS['base_url'] .'/'. $test_file; if ( !_private_upload_is_url_private( $url )) { $requirements['private_upload_readable'] = array( 'title' => t('Private Upload'), 'severity' => REQUIREMENT_WARNING, 'value' => $t('Private directory is publically accessable!'), 'description' => $t('Very bad! Your private files are not private!'), ); $status[] = '
'. $requirements['private_upload_readable']['description']. '
'; } else { $secure = true; // good can't read files in private folder $status[] = '
'. $t("Your private folder is not accessable. Great!"). "
"; } } else { // unable to write the test file $requirements['private_upload_testfile'] = array( 'title' => t('Private Upload'), 'severity' => REQUIREMENT_WARNING, 'value' => $t('Unable to write test file.'), 'description' => $t( "Unable to add test file to your private folder. Unable to test security of your private folder!"), ); $status[] = '
'. $requirements['private_upload_htaccess']['description'] .'
'; } if (variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC) == FILE_DOWNLOADS_PRIVATE) { $requirements['private_upload_method'] = array( 'title' => t('Private Upload'), 'severity' => REQUIREMENT_WARNING, 'value' => $t('Private Downloads'), 'description' => $t('Private Upload will not work with file upload method set to private. Please enable Public File Transfer.', array('!url' => url('admin/settings/file-system'))), ); $status[] = '
'. $requirements['private_upload_method']['description'] .'
'; } else { $status[] = '
'. $t("File download method is set to public. Great."). '
'; } $old_file_count = db_result( db_query("SELECT COUNT(fid) FROM {files} WHERE filepath REGEXP '^private_upload'") ); if( $old_file_count ) { $requirements['private_upload_old'] = array( 'title' => t('Private Upload'), 'severity' => REQUIREMENT_WARNING, 'value' => $t('Private Downloads'), 'description' => $t('You have !count old style file(s) listed in the database. ', array('!count'=>$old_file_count) ). l( 'Click here to migrate', 'admin/private_upload/migrate_old'), ); $status[] = '
'. $requirements['private_upload_old']['description'] .'
'; } else { $status[] = '
'. $t("There are no old-style private files hanging around. Great.") . '
'; } if( count($requirements) ) { // failed if ($phase == 'runtime') { foreach( $requirements as $key => $req ) { if ($requirements[$key]['severity'] == REQUIREMENT_WARNING) { $requirements[$key]['severity'] = REQUIREMENT_ERROR; // bump up to error if after install } } } } else { // success $requirements['private_upload'] = array( 'title' => t('Private Upload'), 'severity' => REQUIREMENT_OK, 'value' => $t('Private Upload is correctly configured and secure.'), ); } return $requirements; } /** * Implementation of hook_nodeapi(). */ function private_upload_nodeapi(&$node, $op, $teaser) { switch ($op) { case 'insert': // Modification for upload roles if ($node->upload_role) { if ($node->upload_role > 0) { $sql = "INSERT INTO {private_upload_roles} (nid,rid) VALUES (%d, %d)"; db_query($sql, $node->nid, $node->upload_role); } } break; case 'delete': // Modification for upload roles // Delete existing role for this node $sql = "DELETE FROM {private_upload_roles} WHERE nid = %d"; db_query($sql, $node->nid); break; case 'update': // ****************************************************** // *** INSERT/UPDATE // *** Move a file from public to private, or vise-verse // ****************************************************** // Modification for upload roles if ($node->upload_role) { // Delete existing role for this node $sql = "DELETE FROM {private_upload_roles} WHERE nid = %d"; db_query($sql, $node->nid); if ($node->upload_role > 0) { $sql = "INSERT INTO {private_upload_roles} (nid,rid) VALUES (%d, %d)"; db_query($sql, $node->nid, $node->upload_role); } } if (user_access('upload files')) { if( is_array($node->files) ) { foreach ($node->files as $fid => $file) { $file = (object)$file; // Convert file to object for compatibility $fid = $file->fid; // for the cases where we have temp fid for uploaded files $success = false; $filepath = $file->filepath; // need copy if file_move fails. $public = file_directory_path(); $private_path = _private_upload_path(); // actual path of private files $file_is_private = _private_upload_is_file_private($filepath); if( $file->private && !$file_is_private ) { // private flag is set, but file NOT yet listed as being in private repo, // so try and move it from public area to private repo if( file_move($filepath, $private_path, FILE_EXISTS_REPLACE) ) { $success = true; } else { drupal_set_message( "Could not move the file ($file->filepath) to the private directory ($private_path).", 'error' ); } } else if (!$file->private && $file_is_private) { // private flag is false, but file IS g in private repo // so try and move it from private repo to public area if (file_move($filepath, $public, FILE_EXISTS_REPLACE)) { $success = true; } else { drupal_set_message( "Could not move the file ($file->filepath) to the public directory ($public).", 'error' ); } } if( $success ) { // we were able to move the file, so update filepath in db. db_query("UPDATE {files} SET filepath = '%s' WHERE fid=%d AND nid=%d", $filepath, $fid, $node->nid); $row_count = db_affected_rows(); if( $row_count != 1 ) { drupal_set_message( "Error: Unable to make uploaded file private! (". $row_count .")", 'error' ); } } } // Done with all the files. } } break; case 'view' : // ****************************************************** // *** VIEW // Re-theme the file attachments table. // ****************************************************** // special case for organic groups. User can see the group, but should not have // access to the files unless they are a member of the group. // Warning: this just hides the link, it does not protect the file. if(module_exists('og') && og_is_group_type($node->type)) { global $user; if( !array_key_exists($node->nid, $user->og_groups) ) { foreach ($node->files as $fid => $file) { if( _private_upload_is_file_private($file->filepath) ) { $file->list = false; } } } } // Always rebuild the files table and overwrite default. $node->content['files']['#value'] = theme('private_upload_attachments', private_upload_table_rewrite($node->files)); break; } } /** * hook_form_alter(). * * Inject the 'private' checkboxes into the upload form. * Also change the #theme to something that will show the checkboxes * and overwrite the href in the description. * Two paths - one for normal submit, one for javascript. */ function private_upload_form_alter($form_id, &$form) { if (isset($form['type'])) { $node = $form['#node']; if ($form['type']['#value'] .'_node_form' == $form_id && variable_get("upload_$node->type", TRUE)) { if (is_array($node->files) && count($node->files)) { // hijack theme function // // Modification: Create pulldown menu to select role for private files (upload roles) // $roles = private_upload_get_roles(); $form['attachments']['upload_role'] = array( '#type' => 'select', '#title' => t('Role for viewing private files'), '#options' => $roles, '#default_value' => private_upload_get_role($node->nid), '#description' => t('Select the role (other than anonymous and/or authenticated) to which you wish to restrict viewing/downloading of files marked private. No Additional Restriction means that any role which could normally see the private files(s) will continue to be able to do so. Selecting a role here means only users with this role will be able to view/download files marked as private'), ); $form['attachments']['wrapper']['files']['#theme'] = 'private_upload_form'; $form['#validate']['private_upload_form_validate'] = array(); //$form['#validate'][] = 'private_upload_form_validate'; foreach ($node->files as $fid => $file) { // Add private checkbox. $form['attachments']['wrapper']['files'][$fid]['private'] = array( '#type' => 'checkbox', '#default_value' => _private_upload_is_file_private($file->filepath) ); if( !realpath($file->filepath) ) { $form['attachments']['wrapper']['files'][$fid]['msg'] = array( '#value' => ' *Missing*', ); drupal_set_message("File is not where it should be: $file->filepath", 'warning'); } // Overwrite URL in description with special URL if file is private. $href = _private_upload_create_url($file); $description = "". check_plain($href) .""; $form['attachments']['wrapper']['files'][$fid]['description'] = array( '#type' => 'textfield', '#default_value' => (strlen($file->description)) ? $file->description : $file->filename, '#maxlength' => 256, '#description' => $description, ); } } } } elseif( $form_id == 'upload_js' ) { // // Modification: Create pulldown menu to select role for private files (upload roles) // $roles = private_upload_get_roles(); $form['upload_role'] = array( '#type' => 'select', '#title' => t('Role for viewing private files'), '#options' => $roles, '#default_value' => private_upload_get_role($node->nid), '#description' => t('Select the role (other than anonymous and/or authenticated) to which you wish to restrict viewing/downloading of files marked private. No Additional Restriction means that any role which could normally see the private files(s) will continue to be able to do so. Selecting a role here means only users with this role will be able to view/download files marked as private'), ); $form['files']['#theme'] = 'private_upload_form'; foreach ($form['files'] as $fid => $file) { if( !_private_upload_starts_with( $fid, '#' ) ) { // Ignore the properties. if( $_POST['files'][$fid] ) { $private = $_POST['files'][$fid]['private']; // While I am here lets fix the problem with delete and list as well. $form['files'][$fid]['list']['#default_value'] = $_POST['files'][$fid]['list']; $form['files'][$fid]['remove']['#default_value'] = $_POST['files'][$fid]['remove']; } else { // File is a newly uploaded so set private to default. $private = ( variable_get( 'private_upload_default', 'private' ) == 'private' ); } $form['files'][$fid]['private'] = array( '#type' => 'checkbox', '#default_value' => $private, ); } } } } /** * Called to validate the upload form. */ function private_upload_form_validate($form_id, $form_values) { if (is_array($form_values['files']) && count($form_values['files'])) { $file = array_shift($form_values['files']); if (!isset($file['private'])) { drupal_set_message( t("Private Upload cannot find privacy settings."), 'error' ); // Be sure we are going after core upload.module. $upload_weight = (int)db_result(db_query("SELECT weight FROM {system} WHERE name = 'upload'")); $private_weight = (int)db_result(db_query("SELECT weight FROM {system} WHERE name = 'private_upload'")); if ($private_weight <= $upload_weight) { $new_weight = $upload_weight+1; drupal_set_message( t("Adjusting private_upload's weight to "). $new_weight, 'warning'); db_query("UPDATE {system} SET weight = '%d' WHERE name = 'private_upload'", $new_weight); } else { drupal_set_message(t("Please check for modules that conflicts with Private Upload."), error); } } } } // ***************************************************************************** // Settings Functions ********************************************************** // ***************************************************************************** /** * Setting page * Also shows status and launching point for migration. */ function private_upload_admin() { drupal_set_title('Private Upload Settings'); $form['settings'] = array( '#type' => 'fieldset', '#title' => t('Private Upload Settings'), '#collapsible' => TRUE, ); $public = file_directory_path(); $form['settings']['private_upload_path'] = array( '#type' => 'textfield', '#title' => t('Private Upload Path'), '#default_value' => variable_get('private_upload_path', 'private'), '#description' => t('This folder will be inside of "!public".', array( '!public' => $public)), ); $form['settings']['private_upload_default'] = array( '#type' => 'select', '#title' => t('Default Upload Privacy Setting'), '#default_value' => variable_get('private_upload_default', 'private' ), '#options' => array ( 'private' => 'private', 'public' => 'public' ), '#description' => t('Are uploads public or private by default?'), ); // STATUS REPORT *************************************************************** $form['status'] = array( '#type' => 'fieldset', '#title' => t('Private Upload Status'), '#collapsible' => TRUE, ); $public = file_directory_path(); $status[] = "Public File Folder: '$public'"; $private_path = _private_upload_path(); $output = "Private File Folder: '$private_path'"; $status[] = $output; // get status messages from the requirements hook. _private_upload_requirements('runtime', $status); // loop through all the file in private folder & collect stats. $private_file_count = 0; $d = opendir( $private_path ); if( $d ) { while( $f = readdir($d) ) { if( $f != '.' && $f != '..' && $f != '.htaccess' && $f != 'privacy_test.txt') { $private_file_count++; } } closedir( $d ); $db_private_file_count = db_result( db_query("SELECT COUNT(fid) FROM {files} WHERE filepath REGEXP '^%s'", $private_path) ); $output = t( "There are '!fs_count' files in the private folder, ". " and the DB thinks there are '!db_count' private files.", array( '!fs_count'=>$private_file_count, '!db_count'=>$db_private_file_count) ); if( $db_private_file_count != $private_file_count ) { $status[] = '
'. $output .'
'; } else { $status[] = '
'. $output . t(" Great.") . '
'; } } else { // unable to open folder! $status[] = '
'. t("'!private_path' is not a valid directory (!is).", array('!private_path'=>$private_path, '!is'=>is_dir($private_path))) . '
'; } // check for public files attached to private nodes. $count = db_result( db_query('SELECT COUNT(DISTINCT(f.fid)) FROM {files} f, {node_access} na '. ' WHERE f.nid = na.nid AND na.gid != 0 AND f.filepath NOT REGEXP "^%s"', $private_path)); if( $count ) { $status[] = t("There are !count public files attached to private nodes. ", array('!count'=>$count)). l( 'Click here to make them all private.', 'admin/private_upload/migrate_private'); } else { $status[] = t("There are no public files attached to private nodes. Great."); } $result = db_fetch_array( db_query('SELECT COUNT(f.fid) as fids, COUNT(DISTINCT(f.nid)) as nids '. 'FROM {files} f, {file_revisions} fv WHERE f.fid = fv.fid AND f.nid = fv.vid') ); $status[] = t("Uploaded files in db: '!files' files attached to '!nodes' nodes.", array( '!files'=>$result['fids'], '!nodes'=>$result['nids'])); $form['status']['info'] = array ( '#value' => '', ); return system_settings_form($form); } /** * Make sure the new private_upload_path can be created and writen to. */ function private_upload_admin_validate($form_id, $form_values) { variable_set('private_upload_path', $form_values['private_upload_path'] ); $private_upload_path = file_create_path($form_values['private_upload_path']); // FILE_CREATE_DIRECTORY and FILE_MODIFY_PERMISSIONS if (!file_check_directory($private_upload_path, TRUE, 'private_upload_path')) { return false; } } // ***************************************************************************** // Callback Functions ********************************************************** // ***************************************************************************** /** * Callback to inject an .htaccess file into the private_upload_path folder */ function _private_upload_add_htacess() { $path = file_create_path( _private_upload_path() .'/.htaccess' ); file_save_data( "SetHandler This_is_a_Drupal_security_line_do_not_remove Deny from all", $path, FILE_EXISTS_REPLACE ); drupal_set_message("Added .htaccess file at $path"); } /** * Callback to clean up private files from the dev version * TODO - put this into a private_upload.install update? * * @return: html info string */ function _private_upload_migrate_old() { $private_path = _private_upload_path(); $result = db_query("SELECT fid, nid, filepath FROM {files} WHERE filepath REGEXP '^private_upload'"); while( $file = db_fetch_object($result) ) { $realpath = _private_upload_replace_start_with( $file->filepath, 'private_upload', $private_path ); drupal_set_message("Updating $file->filepath to $realpath"); db_query("UPDATE {files} SET filepath='%s' WHERE fid=%d AND nid=%d", $realpath, $file->fid, $file->nid); } drupal_goto('admin/logs/status'); } /** * Callback to make public file attached to private nodes also be private. * * @return: html info string */ function _private_upload_migrate_private() { $private_path = _private_upload_path(); $result = db_query('SELECT f.* FROM {files} f, {node_access} na '. ' WHERE f.nid = na.nid AND na.gid != 0 AND f.filepath NOT REGEXP "^%s" '. ' GROUP BY f.fid', $private_path ); while( $file = db_fetch_object($result) ) { // file is attached to a private node, but is a public file, so move it. $filepath = $file->filepath; if( file_move($filepath, $private_path, FILE_EXISTS_REPLACE) ) { $output .= t("Making !filename private", array('!filename'=>$file->filename)). "
"; db_query("UPDATE {files} SET filepath = '%s' WHERE fid=%d AND nid=%d", $filepath, $file->fid, $file->nid); } else { $output .= t("Could not move %filepath to private directory (fid: %fid attached to node: nid).", array('%filepath'=>$file->filepath, '%fid'=>$file->fid, 'nid'=>$file->nid)). "
"; } } return $output; } // ***************************************************************************** // Theme functions *********************************************************** // ***************************************************************************** /** * Based on theme_upload_form_current. * Adding the Private checkbox. */ function theme_private_upload_form(&$form) { $header = array(t('Delete'), t('List'), t('Private'), t('Description'), t('Size'), ''); foreach (element_children($form) as $key) { $row = array(); $row[] = drupal_render($form[$key]['remove']); $row[] = drupal_render($form[$key]['list']); $row[] = drupal_render($form[$key]['private']); $row[] = drupal_render($form[$key]['description']); $row[] = drupal_render($form[$key]['size']); $row[] = drupal_render($form[$key]['msg']); $rows[] = $row; } $output .= theme('table', $header, $rows); $output .= drupal_render($form); return $output; } /** * Displays file attachments in table. * Taken from theme_upload_attachments. */ function theme_private_upload_attachments($files) { $header = array(t('Attachment'), t('Size')); $rows = array(); if(is_array($files)) { foreach ($files as $file) { $file = (object)$file; if ($file->list && !$file->remove) { $href = _private_upload_create_url($file); // this is the changed line $text = $file->description ? $file->description : $file->filename; $rows[] = array(l($text, $href), format_size($file->filesize)); } } if (count($rows)) { return theme('table', $header, $rows, array('id' => 'attachments')); } } } // ***************************************************************************** // Utility functions *********************************************************** // ***************************************************************************** function _private_upload_path() { return file_create_path( variable_get('private_upload_path', 'private') ); } /** * Utility: does str1 start with str2 */ function _private_upload_starts_with( $str, $start ) { if( count($str) == 0 ) return false; // avoid false positive. return strstr($str, $start) == $str; } /** * Utility: replace start with new in str1. * Returns the modified string. */ function _private_upload_replace_start_with( $str, $start, $new ) { return substr_replace( $str, $new, 0, strlen($start) ); } /** * @param $filepath * @return boolean - if the $filepath refers to a private file */ function _private_upload_is_file_private( $filepath ) { // $private_prefix = 'private_upload'; // fake path of private file (for public consumption and menu) $private_path = _private_upload_path(); $is_in = _private_upload_starts_with($filepath, $private_path ); return $is_in; } /** * Create a URL for the file that changes if the file is public or private. * * @param file object $file * @return str: the correct URL */ function _private_upload_create_url($file) { if (_private_upload_is_file_private($file->filepath)) { $download_method = variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC); // this should be PUBLIC, but don't break misconfigured systems variable_set('file_downloads', FILE_DOWNLOADS_PRIVATE); } // Generate valid URL for both existing attachments and preview of new attachments (these have 'upload' in fid) $href = file_create_url((strpos($file->fid, 'upload') === FALSE ? $file->filepath : file_create_filename($file->filename, file_create_path()))); if (_private_upload_is_file_private($file->filepath)) { variable_set('file_downloads', $download_method); } return $href; } /** * _private_upload_is_url_private() * * Based on work by schultkl: http://drupal.org/node/201547 * fsockopen used b/c get_headers() fails when allow_url_fopen disabled. * * Status codes checked: * * 200 OK: The request has succeeded. * 302 Found: The requested resource resides temporarily under a different URI * See: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html * * @param $url: url to check if publicly accessible * @return boolean true if proven to be non-publically accessible, else false (public, or unknown) */ function _private_upload_is_url_private($url) { $return_val = FALSE; $socket_open_timeout = 30; $read_data_timeout = 10; $max_chunk = 1024; $status_codes = array("200","302"); // see function header for code details // parse and open a socket to the requested resource $url_info=parse_url($url); $port=isset($url_info['port']) ? $url_info['port'] : 80; $fp=fsockopen($url_info['host'], $port, $errno, $errstr, $socket_open_timeout); if(!$fp) { drupal_set_message( t("Unable to test file access: "). $errstr, 'error' ); return FALSE; // Failure - file status is unknown. } stream_set_timeout($fp, $read_data_timeout); // Request resource headers $head = "HEAD ".@$url_info['path']."?".@$url_info['query']; $head .= " HTTP/1.0\r\nHost: ".@$url_info['host']."\r\n\r\n"; fputs($fp, $head); // Read resource headers if($header=trim(fgets($fp, $max_chunk))) { $header_array = explode(': ',$header); $header_type = $header_array[0]; foreach ($status_codes as $status_code) { if( strstr($header_type, $status_code)) { fclose($fp); return FALSE; // Falure - file is publically accessable. } } } fclose($fp); return TRUE; // good } // ***************************************************************************** // Views **************************************************************** // ***************************************************************************** function private_upload_views_tables_alter(&$table_data) { // $table_data['files']['fields']['private_filepath'] = array( // 'name'] = t('File: Path (Private)'); // $table_data['files']['fields']['filepath']['handler'] = 'private_upload_views_handler_filepath'; // $table_data['files']['fields']['filepath']['name'] = t('File: Path (Private)'); $table_data['files']['fields']['filepath']['handler'] = 'private_upload_views_handler_filepath'; $table_data['files']['fields']['filepath']['option'] = array( '#type' => 'select', '#options' => array( 'raw' => t('Show the true pathname'), 'usable' => t('Show the usable pathname'), ), ); // $table_data['files']['fields']['all_files']['name'] = t('File: All files (Private)'); $table_data['files']['fields']['all_files']['handler'] = array( 'private_upload_views_handler_all_files' => t('All files'), 'private_upload_views_handler_listed_files' => t('Listed files') ); } function private_upload_views_handler_filepath($fieldinfo, $fielddata, $value, $data) { if ($fielddata['options'] == 'usable') { if(_private_upload_is_file_private($value)) { $value = _private_upload_replace_start_with($value, _private_upload_path(), 'system/files' ); } } return $value; } /** * Display all files attached to a given node. */ function private_upload_views_handler_all_files($fieldinfo, $fielddata, $value, $data, $listed = false) { if ($listed) { $and = " AND list = 1"; } $links = array(); $result = db_query("SELECT f.*, fr.* FROM {file_revisions} fr INNER JOIN {files} f ON f.fid = fr.fid ". "WHERE fr.vid = %d $and", $data->vid); while ($file = db_fetch_object($result)) { // link/nolink use file filename; linkdesc/nolinkdesc use file description if ($fielddata['options'] == 'link' || $fielddata['options'] == 'nolink') { $display_string = $file->filename; } else { $display_string = $file->description; } if ($fielddata['options'] == 'nolink' || $fielddata['options'] == 'nolinkdesc') { $links[] = check_plain($display_string); } else { // $links[] = l($display_string, check_url(file_create_url($file->filepath))); // original $links[] = l($display_string, _private_upload_create_url($file)); // the change } } return implode(' | ', $links); } function private_upload_views_handler_listed_files($fieldinfo, $fielddata, $value, $data) { return private_upload_views_handler_all_files($fieldinfo, $fielddata, $value, $data, TRUE); } // ***************************************************************************** // Customizations ************************************************************* // ***************************************************************************** function private_upload_table_rewrite($files) { global $user; $copyfiles = array(); $copy = 'no'; foreach ($files as $fid => $file) { if ( !_private_upload_is_file_private($file->filepath)) { $copy = 'yes'; } if (in_array(private_upload_get_role($file->nid), array_keys($user->roles))) { $copy = 'yes'; } if ( _private_upload_is_file_private($file->filepath) && !user_access('view uploaded files')) { $copy = 'no'; } if ( _private_upload_is_file_private($file->filepath) && user_access('view uploaded files') && private_upload_get_role($file->nid) == 0) { $copy = 'yes'; } if ($copy == 'yes') { $copyfiles[$fid] = $file; } } return $copyfiles; } /** * Get all roles. */ function private_upload_get_roles() { $roles = array(); $all_roles = user_roles(); $roles[0] = 'No Additional Restriction'; foreach ($all_roles as $rid => $role) { if ($rid > 2) { $roles[$rid] = $role; } } return $roles; } /** * Get all role selected for this nodeID. */ function private_upload_get_role($nid) { $role = 0; $sql = "SELECT rid FROM {private_upload_roles} WHERE nid = %d"; $results = db_query($sql, $nid); while ( $data = db_fetch_object($results) ) { $role = $data->rid; } return $role; }