Index: includes/file.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/file.inc,v retrieving revision 1.183 diff -u -9 -p -r1.183 file.inc --- includes/file.inc 19 Aug 2009 08:38:09 -0000 1.183 +++ includes/file.inc 20 Aug 2009 16:16:40 -0000 @@ -669,19 +669,19 @@ function file_unmanaged_copy($source, $d drupal_chmod($destination); return $destination; } /** * Given a relative path, construct a URI into Drupal's default files location. */ function file_build_uri($path) { - $uri = variable_get('file_scheme_default', 'public') . '://' . $path; + $uri = variable_get('file_default_scheme', 'public') . '://' . $path; return file_stream_wrapper_uri_normalize($uri); } /** * Determines the destination path for a file depending on how replacement of * existing files should be handled. * * @param $destination * A string specifying the desired final URI or filepath. Index: modules/simpletest/tests/file.test =================================================================== RCS file: /cvs/drupal/drupal/modules/simpletest/tests/file.test,v retrieving revision 1.40 diff -u -9 -p -r1.40 file.test --- modules/simpletest/tests/file.test 19 Aug 2009 08:38:09 -0000 1.40 +++ modules/simpletest/tests/file.test 20 Aug 2009 16:16:40 -0000 @@ -2101,24 +2101,24 @@ class StreamWrapperRegistryTest extends * Test the URI and target functions. */ function testGetInstanceByUri() { $instance = file_stream_wrapper_get_instance_by_uri($this->scheme . '://foo'); $this->assertEqual($this->classname, get_class($instance), t('Got correct class type for dummy URI.')); $instance = file_stream_wrapper_get_instance_by_uri('public://foo'); $this->assertEqual('DrupalPublicStreamWrapper', get_class($instance), t('Got correct class type for public URI.')); - // Test file_stream_wrapper_uri_normalize. + // Test file_stream_wrapper_uri_normalize(). $uri = 'public:///' . file_directory_path() . '/foo/bar/'; $uri = file_stream_wrapper_uri_normalize($uri); $this->assertEqual('public://foo/bar', $uri, t('Got a properly normalized URI @uri', array('@uri' => $uri))); - // Test file_uri_taget(). + // Test file_uri_target(). $this->assertEqual('foo/bar.txt', file_uri_target('public://foo/bar.txt'), t('Got a valid stream target from public://foo/bar.txt')); $this->assertFalse(file_uri_target('foo/bar.txt'), t('foo/bar.txt is not a valid stream.')); } /** * Test the scheme functions. */ function testGetValidStreamScheme() { $this->assertEqual('foo', file_uri_scheme('foo://pork//chops'), t('Got the correct scheme from foo://asdf')); Index: modules/upload/upload.module =================================================================== RCS file: /cvs/drupal/drupal/modules/upload/upload.module,v retrieving revision 1.248 diff -u -9 -p -r1.248 upload.module --- modules/upload/upload.module 20 Aug 2009 10:48:03 -0000 1.248 +++ modules/upload/upload.module 20 Aug 2009 16:16:40 -0000 @@ -143,29 +143,31 @@ function _upload_file_limits($user) { 'file_size' => $file_limit, 'user_size' => $user_limit, 'resolution' => variable_get('upload_max_resolution', 0), ); } /** * Implement hook_file_download(). */ -function upload_file_download($filepath) { - $file = db_query("SELECT f.*, u.nid FROM {file} f INNER JOIN {upload} u ON f.fid = u.fid WHERE uri = :path", array(':path' => $filepath))->fetchObject(); +function upload_file_download($uri) { + $file = db_query("SELECT f.filemime, f.filesize, u.nid FROM {file} f INNER JOIN {upload} u ON f.fid = u.fid WHERE uri = :uri", array(':uri' => $uri))->fetchObject(); - if ($file && user_access('view uploaded files') && ($node = node_load($file->nid)) && node_access('view', $node)) { - return array( - 'Content-Type' => $file->filemime, - 'Content-Length' => $file->filesize, - ); - } - else { - return -1; + if ($file) { + if (user_access('view uploaded files') && ($node = node_load($file->nid)) && node_access('view', $node)) { + return array( + 'Content-Type' => $file->filemime, + 'Content-Length' => $file->filesize, + ); + } + else { + return -1; + } } } /** * Save new uploads and store them in the session to be associated to the node * on upload_save. * * @param $node * A node object to associate with uploaded files. @@ -175,19 +177,19 @@ function upload_node_form_submit(&$form, $limits = _upload_file_limits($user); $validators = array( 'file_validate_extensions' => array($limits['extensions']), 'file_validate_image_resolution' => array($limits['resolution']), 'file_validate_size' => array($limits['file_size'], $limits['user_size']), ); // Save new file uploads. - if (user_access('upload files') && ($file = file_save_upload('upload', $validators, 'public://'))) { + if (user_access('upload files') && ($file = file_save_upload('upload', $validators, file_build_uri('/')))) { $file->list = variable_get('upload_list_default', 1); $file->description = $file->filename; $file->weight = 0; $file->new = TRUE; $form['#node']->files[$file->fid] = $file; $form_state['values']['files'][$file->fid] = (array)$file; } if (isset($form_state['values']['files'])) { Index: modules/upload/upload.test =================================================================== RCS file: /cvs/drupal/drupal/modules/upload/upload.test,v retrieving revision 1.23 diff -u -9 -p -r1.23 upload.test --- modules/upload/upload.test 17 Aug 2009 19:14:41 -0000 1.23 +++ modules/upload/upload.test 20 Aug 2009 16:16:41 -0000 @@ -167,18 +167,74 @@ class UploadTestCase extends DrupalWebTe $filename = basename($file); $filesize = format_size($info['size']); $maxsize = format_size(parse_size(($settings['upload_uploadsize'] * 1024) . 'KB')); // Won't parse decimals. // Test the error message in two steps in case there are additional errors // that change the error message's format. $this->assertRaw(t('The specified file %name could not be uploaded.', array('%name' => $filename)), t('File upload was blocked')); $this->assertRaw(t('The file is %filesize exceeding the maximum file size of %maxsize.', array('%filesize' => $filesize, '%maxsize' => $maxsize)), t('File size cited as problem with upload')); } + /** + * Check file access when using private downloads. + */ + function testDownloadAccess() { + $admin_user = $this->drupalCreateUser(array('administer site configuration', 'administer users', 'edit any page content', 'upload files')); + $access_user = $this->drupalCreateUser(array('access content', 'access user profiles', 'view uploaded files')); + $no_access_user = $this->drupalCreateUser(array('access content')); + + $files = $this->drupalGetTestFiles('text', 1024); // 1 Kb. + $file = current($files); + + $files = $this->drupalGetTestFiles('image'); + $user_picture = current($files); + + $this->drupalLogin($admin_user); + + // Set default download method. + variable_set('file_default_scheme', 'private'); + + // Create a node and upload a file to it. + $node = $this->drupalCreateNode(); + $this->uploadFile($node, $file->uri, FALSE); + $uploaded_uri = 'private://' . basename($file->uri); + $this->assertTrue(file_exists($uploaded_uri), t('File was uploaded to expected location.')); + + // Upload a user picture for the admin. We use user pictures to check + // that upload.module does not block access to other managed files. + $edit = array('files[picture_upload]' => $user_picture->uri); + $this->drupalPost('user/' . $admin_user->uid . '/edit', $edit, t('Save')); + + // Add an unmanaged file. + $unmanaged_uri = file_unmanaged_copy($file->uri); + + // Login as a user that can view the file. + $this->drupalLogin($access_user); + + // Check that this user can see the uploaded node file. + $this->drupalGet(file_create_url($uploaded_uri)); + $this->assertResponse(200, t('User with permission can view file with private downloads.')); + + // Check that this user cannot an view an unmanaged file. + $this->drupalGet(file_create_url($unmanaged_uri)); + $this->assertResponse(404, t('User cannot view an unmanaged file with private downloads.')); + + // Check that this user can view a managed file not owned by upload. + $this->drupalGet(file_create_url('private://pictures/picture-' . $admin_user->uid . '.' . pathinfo($user_picture->uri, PATHINFO_EXTENSION))); + $this->assertResponse(200, t('User can view files not uploaded through upload module with private downloads.')); + + // Login as a user that cannot view the upload file. + $this->drupalLogin($no_access_user); + $this->drupalGet(file_create_url($uploaded_uri)); + $this->assertResponse(403, t('User without permission cannot view uploaded files with private downloads.')); + + variable_set('file_default_scheme', 'public'); + } + function setUploadSettings($settings, $rid = NULL) { $edit = array(); foreach ($settings as $key => $value) { $edit[$key . '_default'] = $value; if ($rid !== NULL && $key != 'upload_list' && $key != 'upload_max_resolution') { $edit[$key . '_' . $rid] = $value; } } $this->drupalPost('admin/settings/uploads', $edit, 'Save configuration');