'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' => '- ' . implode( '
- ', $status ) . '
',
);
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;
}