diff --git a/modules/file/file.module b/modules/file/file.module index 9e091af..bf7b07d 100644 --- a/modules/file/file.module +++ b/modules/file/file.module @@ -457,6 +457,17 @@ function file_managed_file_process($element, &$form_state, $form) { '#markup' => theme('file_link', array('file' => $element['#file'])) . ' ', '#weight' => -10, ); + // Anonymous users who have uploaded a temporary file need a + // non-session-based token added so file_managed_file_value() can check + // that they have permission to use this file on subsequent submissions of + // the same form (for example, after an Ajax upload or form validation + // error). + if (!$GLOBALS['user']->uid && $element['#file']->status != FILE_STATUS_PERMANENT) { + $element['fid_token'] = array( + '#type' => 'hidden', + '#value' => drupal_hmac_base64('file-' . $fid, drupal_get_private_key() . drupal_get_hash_salt()), + ); + } } // Add the extension list to the page as JavaScript settings. @@ -533,13 +544,24 @@ function file_managed_file_value(&$element, $input = FALSE, $form_state = NULL) $force_default = TRUE; } // Temporary files that belong to other users should never be allowed. - // Since file ownership can't be determined for anonymous users, they - // are not allowed to reuse temporary files at all. - elseif ($file->status != FILE_STATUS_PERMANENT && (!$GLOBALS['user']->uid || $file->uid != $GLOBALS['user']->uid)) { - $force_default = TRUE; + elseif ($file->status != FILE_STATUS_PERMANENT) { + if ($GLOBALS['user']->uid && $file->uid != $GLOBALS['user']->uid) { + $force_default = TRUE; + } + // Since file ownership can't be determined for anonymous users, they + // are not allowed to reuse temporary files at all. But they do need + // to be able to reuse their own files from earlier submissions of + // the same form, so to allow that, check for the token added by + // file_managed_file_process(). + elseif (!$GLOBALS['user']->uid) { + $token = drupal_array_get_nested_value($form_state['input'], array_merge($element['#parents'], array('fid_token'))); + if ($token !== drupal_hmac_base64('file-' . $file->fid, drupal_get_private_key() . drupal_get_hash_salt())) { + $force_default = TRUE; + } + } } // If all checks pass, allow the file to be changed. - else { + if (!$force_default) { $fid = $file->fid; } } diff --git a/modules/node/node.test b/modules/node/node.test index e4e1d3d..51fa3bd 100644 --- a/modules/node/node.test +++ b/modules/node/node.test @@ -2995,7 +2995,7 @@ class NodeFormAnonSubmission extends NodeWebTestCase { public static function getInfo() { return array( 'name' => 'Node form anonymous submission', - 'description' => 'Test anon form submission.', + 'description' => 'Test anonymous form submission.', 'group' => 'Node', ); } @@ -3004,18 +3004,18 @@ class NodeFormAnonSubmission extends NodeWebTestCase { parent::setUp(); // Allow node submissions by anonymous users. - user_role_grant_permissions(1, array( + user_role_grant_permissions(DRUPAL_ANONYMOUS_RID, array( 'create article content', 'access content', )); } /** - * Test the basic node submission for an anonymous visitor. + * Tests the basic node submission for an anonymous visitor. */ - function testAnonNode() { - $bundle_label = t('Article'); - $node_title = t('Test page'); + function testAnonymousNode() { + $bundle_label = 'Article'; + $node_title = 'Test page'; // Load the node form. $this->drupalGet('node/add/article'); @@ -3024,7 +3024,7 @@ class NodeFormAnonSubmission extends NodeWebTestCase { $edit = array( 'title' => $node_title, - 'body[und][0][value]' => t('Test article'), + 'body[und][0][value]' => 'Test article', 'body[und][0][format]' => 'filtered_html', ); $this->drupalPost(NULL, $edit, t('Save')); @@ -3041,11 +3041,11 @@ class NodeFormAnonSubmission extends NodeWebTestCase { } /** - * Test the file submission. + * Tests file submission for an anonymous visitor. */ - function testAnonNodeWithFile() { - $bundle_label = t('Article'); - $node_title = t('Test page'); + function testAnonymousNodeWithFile() { + $bundle_label = 'Article'; + $node_title = 'Test page'; // Load the node form. $this->drupalGet('node/add/article'); @@ -3058,7 +3058,7 @@ class NodeFormAnonSubmission extends NodeWebTestCase { // Submit the form. $edit = array( 'title' => $node_title, - 'body[und][0][value]' => t('Test article'), + 'body[und][0][value]' => 'Test article', 'body[und][0][format]' => 'filtered_html', 'files[field_image_und_0]' => drupal_realpath($image->uri), ); @@ -3077,11 +3077,32 @@ class NodeFormAnonSubmission extends NodeWebTestCase { } /** - * Test the file submission with an excluded required field. + * Tests file submission for an anonymous visitor with a missing node title. */ - function testAnonNodeWithFileWithoutTitle() { - $bundle_label = t('Article'); - $node_title = t('Test page'); + function testAnonymousNodeWithFileWithoutTitle() { + $this->drupalLogout(); + $this->_testNodeWithFileWithoutTitle(); + } + + /** + * Tests file submission for an authenticated user with a missing node title. + */ + function testAuthenticatedNodeWithFileWithoutTitle() { + $admin_user = $this->drupalCreateUser(array( + 'bypass node access', + 'access content overview', + 'administer nodes', + )); + $this->drupalLogin($admin_user); + $this->_testNodeWithFileWithoutTitle(); + } + + /** + * Helper method to test file submissions with missing node titles. + */ + protected function _testNodeWithFileWithoutTitle() { + $bundle_label = 'Article'; + $node_title = 'Test page'; // Load the node form. $this->drupalGet('node/add/article'); @@ -3093,7 +3114,7 @@ class NodeFormAnonSubmission extends NodeWebTestCase { // Submit the form but exclude the title field. $edit = array( - 'body[und][0][value]' => t('Test article'), + 'body[und][0][value]' => 'Test article', 'body[und][0][format]' => 'filtered_html', 'files[field_image_und_0]' => drupal_realpath($image->uri), ); @@ -3108,7 +3129,7 @@ class NodeFormAnonSubmission extends NodeWebTestCase { $edit = array( 'title' => $node_title, ); - $this->drupalPost(NULL, $edit, 'Save'); + $this->drupalPost(NULL, $edit, t('Save')); // Confirm the final submission actually worked. $t_args = array('@type' => $bundle_label, '%title' => $node_title); @@ -3124,25 +3145,9 @@ class NodeFormAnonSubmission extends NodeWebTestCase { } /** - * Run the same test as testAnonNodeWithFileWithoutTitle() after logging in. - */ - function testAuthNodeWithFileWithoutTitle() { - // Login as an admin-level user. - $admin_user = $this->drupalCreateUser(array( - 'bypass node access', - 'access content overview', - 'administer nodes', - )); - $this->drupalLogin($admin_user); - - // Run the tests. - $this->testAnonNodeWithFileWithoutTitle(); - } - - /** - * Generate a test image. + * Generates a test image. * - * @return object + * @return stdClass * A file object. */ function getTestImage() {