1)
IMCE has a fantastic permission system for uploading and managing files, but
how is file protection handled? Are the file directories protected against
viewing and leeching from people who are not logged into Drupal?

If not, how would this best be implemented? For instance, having an
unprotected directory tree for graphics/images, but protecting a 'download'
directory from indexing/leeching?

2)
Does version IMCE 6.x 'dovetail' with the Drupal 6.x 'private file system' at all?

Thanks.

CommentFileSizeAuthor
#12 module-imce-file_download-6.x-1.4.patch2.6 KBfajo
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

ufku’s picture

1) IMCE does not implement file/directory protection. I don't know if there is any module for this purpose.
2) IMCE is compatible with private file system. It implements file_download hook but not any restrictions on it.

-Anti-’s picture

Thanks for your reply

> 2) IMCE is compatible with private file system.
> It implements file_download hook but not any restrictions on it.

Does that mean that the 'private' attachments folder still functions
when it is enabled in Administer > Site configuration > File System,
but the directory-tree used for IMCE has no protection?

Cheers.

ufku’s picture

yes, that's right.

MiMe’s picture

Suggestion to make files protected:

function imce_file_download($file) {
	global $user;
	require_once 'inc/page.inc';
	
	// Check user access first
	$imce = imce_initiate_profile($user);
	$myFile =  file_directory_path().'/'.$file;
	
	if(is_file($myFile)) {
		$perms = imce_directory_info(dirname($file), $imce);
		
		if($perms['browse'] == 1) {		
			if ($path = file_create_path($file)) {
				if ($info = @getimagesize($path)) {
					$type = $info['mime'];
				}
				else if (function_exists('finfo_file') && $finfo = @finfo_open(FILEINFO_MIME)) {
					$type = finfo_file($finfo, $path);
					finfo_close($finfo);
				}
				else if ($result = db_result(db_query("SELECT filemime FROM {files} WHERE filepath = '%s'", $path))) {
					$type = $result;
				}
				else if (function_exists('mime_content_type')) {
					$type = mime_content_type($path);
				}
				else {
					$type = 'application/x-download';
				}
				return array('Content-type: '. $type, 'Content-Length: '. filesize($path));
			}
		}		
	}
	
	return -1;
}

This makes file access denied if the IMCE profile doesn't have browse access.
I have only made som very limited tesing.

Sorry, I don't have the ability to create a patch...

ggamba’s picture

Hi Anti,

Private upload (http://drupal.org/project/private_upload ) works well for me: it creates a "private" directory under \files that works exactly as if you were in "private" mode, while the other stuff in \files works in "public" mode.

It would be great, by the way, if IMCE could interact with Private upload in some way (to upload a file in the "private" directory you have to use File attachments while editing the node, you can't use IMCE).

Bye
Gabriele

Vacilando’s picture

Version: 6.x-1.0 » 6.x-1.1
Category: support » feature
Status: Active » Reviewed & tested by the community

MiMe's patch works precisely as expected -- I very much recommend IMCE to implement it to allow private files for directories that do not have IMCE browse access.

Skirr’s picture

It would be great to have this feature. Will it be implemented?

ufku’s picture

Status: Reviewed & tested by the community » Needs work

This patch allows IMCE to control the whole file system as if the only file uploader is IMCE in the system. This should cause inconsistency with other uploader modules. There must a yes/no setting to make administrators decide to give the whole control to IMCE.

kassissieh’s picture

Is #8 true? Module_invoke_all causes all site modules to run hook_file_download on the requested file path. If a module returns -1, then the download is denied, no matter what other modules return. For example, if a user uploads a file to the file system using CCK and a node access module, then CCK's prohibition of download would take precedence over IMCE allowing the download. It's only in the case that other upload modules return no result that IMCE would allow access to such a file. However, this leads to a different kind of problem when IMCE is uninstalled. I'll file a separate feature request about that.

The patch in #4 sounds like a good improvement.

izmeez’s picture

subscribing

vitis’s picture

sub

fajo’s picture

The changes suggested in #4 will cause IMCE to take responsibility over ALL files and not only files in directories configured in the IMCE profiles. That is, if a directrory is not configured in IMCE the hook will deny access to that file. Attached a patch against 6.x-1.4 that will fix this. It is a slightly modified verion of #4's changes that will ignore files in directories not configured in the users IMCE profile. Below is the code:

function imce_file_download($file) {
    global $user;
    require_once 'inc/page.inc';
   
    // Check user access first
    $imce = imce_initiate_profile($user);
    $myFile =  file_directory_path().'/'.$file;
   
    if(is_file($myFile)) {
        $perms = imce_directory_info(dirname($file), $imce);
        
        if ($perms) {
            if($perms['browse'] == 1) {       
                if ($path = file_create_path($file)) {
                    if ($info = @getimagesize($path)) {
                        $type = $info['mime'];
                    }
                    else if (function_exists('finfo_file') && $finfo = @finfo_open(FILEINFO_MIME)) {
                        $type = finfo_file($finfo, $path);
                        finfo_close($finfo);
                    }
                    else if ($result = db_result(db_query("SELECT filemime FROM {files} WHERE filepath = '%s'", $path))) {
                        $type = $result;
                    }
                    else if (function_exists('mime_content_type')) {
                        $type = mime_content_type($path);
                    }
                    else {
                        $type = 'application/x-download';
                    }
                    return array('Content-type: '. $type, 'Content-Length: '. filesize($path));
                }
            }
            else {
                return -1; // access denied
            }
        }
    }
   
    return; // file not handled by IMCE, leave it to other modules to decide
}
MiMe’s picture

The line:
require_once 'inc/page.inc';

Should be replace by this:
module_load_include('inc', 'imce', 'inc/page.inc');

Otherwise filefield_sources will generate an error when you have applied the upload patch #877452: Enable uploading and deletion through IMCE

MiMe’s picture

Sorry, my bad...
the module_load_include should look like this:

module_load_include('inc', 'imce', 'inc/imce.page');
Anonymous’s picture

I hacked the code with

function imce_file_download($file) {
    global $user;

module_load_include('inc', 'imce', 'inc/imce.page');  

    // Check user access first
    $imce = imce_initiate_profile($user);
    $myFile =  file_directory_path().'/'.$file;
  
    if(is_file($myFile)) {
        $perms = imce_directory_info(dirname($file), $imce);
       
        if ($perms) {
            if($perms['browse'] == 1) {      
                if ($path = file_create_path($file)) {
                    if ($info = @getimagesize($path)) {
                        $type = $info['mime'];
                    }
                    else if (function_exists('finfo_file') && $finfo = @finfo_open(FILEINFO_MIME)) {
                        $type = finfo_file($finfo, $path);
                        finfo_close($finfo);
                    }
                    else if ($result = db_result(db_query("SELECT filemime FROM {files} WHERE filepath = '%s'", $path))) {
                        $type = $result;
                    }
                    else if (function_exists('mime_content_type')) {
                        $type = mime_content_type($path);
                    }
                    else {
                        $type = 'application/x-download';
                    }
                    return array('Content-type: '. $type, 'Content-Length: '. filesize($path));
                }
            }
            else {
                return -1; // access denied
            }
        }
    }
  
    return; // file not handled by IMCE, leave it to other modules to decide
}

but when I login I got following errors:
* You do not have access to any configuration profile to use the file browser!
* warning: Invalid argument supplied for foreach() in /var/www/vhosts/snowpedia.it/httpdocs/sites/all/modules/imce/inc/imce.page.inc on line 907.

MiMe’s picture

What version of IMCE are you using?

Anonymous’s picture

IMCE 6.x-2.x-dev (2010-ott-06)

MiMe’s picture

I've updated the code to include the $serve variable from the current IMCE and also to check if the $imce['directories'] is empty.
giorez: Try this code.

function imce_file_download($file) {
  $serve = variable_get('file_downloads', '') == FILE_DOWNLOADS_PRIVATE && !variable_get('imce_settings_disable_private', 0) && ($path = file_create_path($file)) && file_exists($path) && strpos(basename($path), '.');

  if ($serve) {
    global $user;
    module_load_include('inc', 'imce', 'inc/imce.page');

    // Check user access first
    $imce = imce_initiate_profile($user);
    $myFile = file_directory_path() . '/' . $file;

    if (is_file($myFile)) {
      $perms = NULL;
      if(!empty($imce['directories'])) {
        $perms = imce_directory_info(dirname($file), $imce);
      }

      if ($perms) {
        if ($perms['browse'] == 1) {
          if ($path = file_create_path($file)) {
            if ($info = @getimagesize($path)) {
              $type = $info['mime'];
            }
            else if (function_exists('finfo_file') && $finfo = @finfo_open(FILEINFO_MIME)) {
              $type = finfo_file($finfo, $path);
              finfo_close($finfo);
            }
            else if ($result = db_result(db_query("SELECT filemime FROM {files} WHERE filepath = '%s'", $path))) {
              $type = $result;
            }
            else if (function_exists('mime_content_type')) {
              $type = mime_content_type($path);
            }
            else {
              $type = 'application/x-download';
            }
            return array('Content-type: ' . $type, 'Content-Length: ' . filesize($path));
          }
        }
        else {
          return -1; // access denied
        }
      }
    }
  }

  return;
}
ufku’s picture

Status: Needs work » Closed (won't fix)

Closing 6.x-1.x issues as this branch is no more supported.