diff --git a/file_entity.admin.inc b/file_entity.admin.inc
index 7173472..bb1b2ed 100644
--- a/file_entity.admin.inc
+++ b/file_entity.admin.inc
@@ -112,18 +112,20 @@ function file_entity_admin_files($form, &$form_state) {
         '#attributes' => array('class' => array('links', 'inline')),
       ),
     );
-
-    $options[$file->fid]['operations']['data']['#links']['edit'] = array(
-      'title' => t('Edit'),
-      'href' => 'file/' . $file->fid . '/edit',
-      'query' => $destination,
-    );
-
-    $options[$file->fid]['operations']['data']['#links']['delete'] = array(
-      'title' => t('Delete'),
-      'href' => 'file/' . $file->fid . '/delete',
-      'query' => $destination,
-    );
+    if (file_entity_access('edit', $file)) {
+      $options[$file->fid]['operations']['data']['#links']['edit'] = array(
+        'title' => t('Edit'),
+        'href' => 'file/' . $file->fid . '/edit',
+        'query' => $destination,
+      );
+    }
+    if (file_entity_access('delete', $file)) {
+      $options[$file->fid]['operations']['data']['#links']['delete'] = array(
+        'title' => t('Delete'),
+        'href' => 'file/' . $file->fid . '/delete',
+        'query' => $destination,
+      );
+    }
   }
 
   $form['files'] = array(
diff --git a/file_entity.api.php b/file_entity.api.php
index a881ece..ca6d0db 100644
--- a/file_entity.api.php
+++ b/file_entity.api.php
@@ -123,48 +123,66 @@ function hook_file_view_alter($build, $type) {
 }
 
 /**
- * Defines bulk file operations.
- *
- * This hook enables modules to inject custom operations into the mass
- * operations dropdown found at admin/content/file, by associating a callback
- * function with the operation, which is called when the form is submitted.
- * The callback function receives one initial argument, which is an array of
- * the checked files.
+ * Control access to a file.
+ *
+ * Modules may implement this hook if they want to have a say in whether or not
+ * a given user has access to perform a given operation on a file.
+ *
+ * The administrative account (user ID #1) always passes any access check,
+ * so this hook is not called in that case. Users with the "bypass file access"
+ * permission may always view and edit files through the administrative
+ * interface.
+ *
+ * Note that not all modules will want to influence access on all
+ * file types. If your module does not want to actively grant or
+ * block access, return FILE_ENTITY_ACCESS_IGNORE or simply return nothing.
+ * Blindly returning FALSE will break other file access modules.
+ *
+ * @param $op
+ *   The operation to be performed. Possible values:
+ *   - "create"
+ *   - "delete"
+ *   - "update"
+ *   - "view"
+ * @param $file
+ *   The file on which the operation is to be performed, or, if it does
+ *   not yet exist, the type of file to be created.
+ * @param $account
+ *   A user object representing the user for whom the operation is to be
+ *   performed.
  *
  * @return
- *  An associave array of operations keyed by machine name.
- *    - label: A string to show in the operations dropdown.
- *    - callback (string): A callback function to call for the operation. This
- *        function will be passed an array of file_ids which were selected.
- *    - confirm (boolean): Whether or not this operation requires a confirm form
- *        In the case where confirm is set to true, callback should be a function
- *        which can return a confirm form.
- *
- * @see hook_file_operation_info_alter()
- * @see file_entity_get_file_operation_info()
+ *   FILE_ENTITY_ACCESS_ALLOW if the operation is to be allowed;
+ *   FILE_ENTITY_ACCESS_DENY if the operation is to be denied;
+ *   FILE_ENTITY_ACCESS_IGNORE to not affect this operation at all.
+ *
+ * @ingroup file_entity_access
  */
-function hook_file_operation_info() {
-  $info['fluff'] = array(
-    'label' => t('Fluff selected files'),
-    'callback' => 'file_fluff_files',
-  );
+function hook_file_entity_access($op, $file, $account) {
+  $type = is_string($file) ? $file : $file->type;
 
-  return $info;
+  if ($op !== 'create' && (REQUEST_TIME - $file->timestamp) < 3600) {
+    // If the file was uploaded in the last hour, deny access to it.
+    return FILE_ENTITY_ACCESS_DENY;
+  }
+
+  // Returning nothing from this function would have the same effect.
+  return FILE_ENTITY_ACCESS_IGNORE;
 }
 
 /**
- * Perform alterations on bulk file operations.
+ * Control access to listings of files.
  *
- * @param $info
- *   Array of information on bulk file operations exposed by
- *   hook_file_operation_info() implementations.
+ * @param $query
+ *   A query object describing the composite parts of a SQL query related to
+ *   listing files.
  *
- * @see hook_file_operation_info()
- * @see file_entity_get_file_operation_info()
+ * @see hook_query_TAG_alter()
+ * @ingroup file_entity_access
  */
-function hook_file_operation_info_alter(&$info) {
-  // Remove the 'Fluff selected files' operation.
-  unset($info['fluff']);
+function hook_query_file_entity_access_alter(QueryAlterableInterface $query) {
+  // Only show files that have been uploaded more than an hour ago.
+  $query->condition('timestamp', REQUEST_TIME - 3600, '<=');
 }
 
 /**
diff --git a/file_entity.file_api.inc b/file_entity.file_api.inc
index dfd9a3a..0094b98 100644
--- a/file_entity.file_api.inc
+++ b/file_entity.file_api.inc
@@ -124,7 +124,7 @@ function file_view($file, $view_mode = 'full', $langcode = NULL) {
   // displayed on its own page. Modules may alter this behavior (for example,
   // to restrict contextual links to certain view modes) by implementing
   // hook_file_view_alter().
-  if (!empty($file->fid) && !($view_mode == 'full' && file_is_page($file))) {
+  if (!empty($file->fid) && !($view_mode == 'full' && file_entity_is_page($file))) {
     $build['#contextual_links']['file'] = array('file', array($file->fid));
   }
 
diff --git a/file_entity.install b/file_entity.install
index d4114f8..83415eb 100644
--- a/file_entity.install
+++ b/file_entity.install
@@ -238,7 +238,7 @@ function file_entity_install() {
   // Set permissions.
   $roles = user_roles();
   foreach ($roles as $rid => $role) {
-    user_role_grant_permissions($rid, array('view file'));
+    user_role_grant_permissions($rid, array('view files'));
   }
 }
 
@@ -373,6 +373,22 @@ function file_entity_update_7104() {
 }
 
 /**
+ * Update permission names.
+ */
+function file_entity_update_7105() {
+  $permissions = array(
+    'view file' => 'view files',
+    'edit file' => 'edit any files',
+  );
+  foreach ($permissions as $old => $new) {
+    db_update('role_permission')
+      ->fields(array('permission' => $new))
+      ->condition('permission', $old)
+      ->execute();
+  }
+}
+
+/**
  * Create the {image_dimensions} database table.
  */
 function file_entity_update_7200() {
diff --git a/file_entity.module b/file_entity.module
index 6acea45..a577408 100644
--- a/file_entity.module
+++ b/file_entity.module
@@ -10,7 +10,25 @@
  *
  * Adds support for docx, xlsx, pptx and ppsx.
  */
-define('FILE_DEFAULT_ALLOWED_EXTENSIONS', 'jpg jpeg gif png txt doc docx xls xlsx pdf ppt pptx pps ppsx odt ods odp');
+define('FILE_ENTITY_DEFAULT_ALLOWED_EXTENSIONS', 'jpg jpeg gif png txt doc docx xls xlsx pdf ppt pptx pps ppsx odt ods odp');
+
+/**
+ * Modules should return this value from hook_file_entity_access() to allow
+ * access to a file.
+ */
+define('FILE_ENTITY_ACCESS_ALLOW', 'allow');
+
+/**
+ * Modules should return this value from hook_file_entity_access() to deny
+ * access to a file.
+ */
+define('FILE_ENTITY_ACCESS_DENY', 'deny');
+
+/**
+ * Modules should return this value from hook_file_entity_access() to not affect
+ * file access.
+ */
+define('FILE_ENTITY_ACCESS_IGNORE', NULL);
 
 /**
  * As part of extending Drupal core's file entity API, this module adds some
@@ -87,13 +105,6 @@ function file_entity_help($path, $arg) {
 }
 
 /**
- * Access callback for files.
- */
-function file_entity_access($op) {
-  return (user_access('administer files') || user_access($op . ' file'));
-}
-
-/**
  * Implements hook_menu().
  */
 function file_entity_menu() {
@@ -104,7 +115,7 @@ function file_entity_menu() {
     'title' => 'File types',
     'description' => 'Manage settings for the type of files used on your site.',
     'page callback' => 'file_entity_list_types_page',
-    'access arguments' => array('administer site configuration'),
+    'access arguments' => array('administer file types'),
     'file' => 'file_entity.admin.inc',
   );
   $items['admin/structure/file-types/manage/%file_type'] = array(
@@ -129,7 +140,8 @@ function file_entity_menu() {
     'title' => 'Add file',
     'page callback' => 'drupal_get_form',
     'page arguments' => array('file_entity_add_upload', array()),
-    'access arguments' => array('administer files'),
+    'access callback' => 'file_entity_access',
+    'access arguments' => array('create'),
     'file' => 'file_entity.pages.inc',
   );
   if (module_exists('plupload') && module_exists('multiform')) {
@@ -148,7 +160,7 @@ function file_entity_menu() {
     'page callback' => 'file_entity_view_page',
     'page arguments' => array(1),
     'access callback' => 'file_entity_access',
-    'access arguments' => array('view'),
+    'access arguments' => array('view', 1),
     'file' => 'file_entity.pages.inc',
   );
   $items['file/%file/view'] = array(
@@ -161,7 +173,7 @@ function file_entity_menu() {
     'page callback' => 'drupal_get_form',
     'page arguments' => array('file_entity_edit', 1),
     'access callback' => 'file_entity_access',
-    'access arguments' => array('edit'),
+    'access arguments' => array('update', 1),
     'weight' => 0,
     'type' => MENU_LOCAL_TASK,
     'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE,
@@ -172,7 +184,7 @@ function file_entity_menu() {
     'page callback' => 'drupal_get_form',
     'page arguments'  => array('file_delete_form', 1),
     'access callback' => 'file_entity_access',
-    'access arguments' => array('edit'),
+    'access arguments' => array('delete', 1),
     'weight' => 1,
     'type' => MENU_LOCAL_TASK,
     'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE,
@@ -191,7 +203,7 @@ function file_entity_menu() {
       $access = array_intersect_key($bundle_info['admin'], drupal_map_assoc(array('access callback', 'access arguments')));
       $access += array(
         'access callback' => 'user_access',
-        'access arguments' => array('administer site configuration'),
+        'access arguments' => array('administer file types'),
       );
 
       // The file type must be passed to the page callbacks. It might be
@@ -201,7 +213,7 @@ function file_entity_menu() {
 
       $items[$path] = array(
         'title' => 'Edit file type',
-        'title callback' => 'file_type_get_name',
+        'title callback' => 'file_entity_type_get_name',
         'title arguments' => array(4),
         'page callback' => 'drupal_get_form',
         'page arguments' => array('file_entity_file_type_form', $file_type_argument),
@@ -308,21 +320,65 @@ function file_entity_menu_local_tasks_alter(&$data, $router_item, $root_path) {
  * Implement hook_permission().
  */
 function file_entity_permission() {
-  return array(
+  $permissions = array(
+    'bypass file access' => array(
+      'title' => t('Bypass file access control'),
+      'description' => t('View, edit and delete all files regardless of permission restrictions.'),
+      'restrict access' => TRUE,
+    ),
     'administer files' => array(
       'title' => t('Administer files'),
       'description' => t('Add, edit or delete files and administer settings.'),
+      'restrict access' => TRUE,
+    ),
+    'administer file types' => array(
+      'title' => t('Administer file types'),
+      'restrict access' => TRUE,
+    ),
+    'view files' => array(
+      'title' => t('View file details'),
+      'description' => t('For viewing file details, not for downloading files.'),
+    ),
+    'delete own files' => array(
+      'title' => t('Delete own files'),
+    ),
+    'view own private files' => array(
+      'title' => t('View own private file details'),
+      'description' => t('For viewing file details, not for downloading files.'),
     ),
-    'view file' => array(
-      'title' => t('View file'),
-      'description' => t('View all files.'),
+    'create files' => array(
+      'title' => t('Add and upload files'),
     ),
-    'edit file' => array(
-      'title' => t('Edit file'),
-      'description' => t('Edit all files.'),
+    'edit own files' => array(
+      'title' => t('Edit own files'),
+    ),
+    'edit any files' => array(
+      'title' => t('Edit any files'),
+    ),
+    'delete any files' => array(
+      'title' => t('Delete any files'),
     ),
   );
+
+  // Add description for the 'View file details' and 'View own private file
+  // details' permissions to show which stream wrappers they apply to.
+  $wrappers = array();
+  foreach (file_get_stream_wrappers(STREAM_WRAPPERS_VISIBLE) as $key => $wrapper) {
+    if (empty($wrapper['private'])) {
+      $wrappers['public'][$key] = $wrapper['name'];
+    }
+    else {
+      $wrappers['private'][$key] = $wrapper['name'];
+    }
+  }
+  $wrappers = array('public' => array(t('None')), 'private' => array(t('None')));
+
+  $permissions['view files']['description'] .= ' ' . t('Includes the following types of files: %wrappers.', array('%wrappers' => implode(', ', $wrappers['public'])));
+  $permissions['view own private files']['description'] .= ' ' . t('Includes the following types of files: %wrappers.', array('%wrappers' => implode(', ', $wrappers['private'])));
+
+  return $permissions;
 }
+
 /**
  * Implements hook_admin_paths().
  */
@@ -417,7 +473,7 @@ function file_entity_entity_property_info() {
     'description' => t('The type of the file.'),
     'setter callback' => 'entity_property_verbatim_set',
     'setter permission' => 'administer files',
-    'options list' => 'file_type_get_names',
+    'options list' => 'file_entity_type_get_names',
     'required' => TRUE,
     'schema field' => 'type',
   );
@@ -452,7 +508,7 @@ function file_entity_metadata_form_file($file) {
 function file_entity_field_extra_fields() {
   $info = array();
 
-  if ($file_type_names = file_type_get_names()) {
+  if ($file_type_names = file_entity_type_get_names()) {
     foreach ($file_type_names as $type => $name) {
       $info['file'][$type]['form']['filename'] = array(
         'label' => t('File name'),
@@ -699,7 +755,7 @@ function file_entity_views_api() {
  * @param $file
  *   A file object.
  */
-function file_is_page($file) {
+function file_entity_is_page($file) {
   $page_file = menu_get_object('file', 1);
   return (!empty($page_file) ? $page_file->fid == $file->fid : FALSE);
 }
@@ -728,7 +784,7 @@ function template_preprocess_file_entity(&$variables) {
   $variables['file_url'] = file_create_url($file->uri);
   $label = entity_label('file', $file);
   $variables['label']     = check_plain($label);
-  $variables['page']      = $view_mode == 'full' && file_is_page($file);
+  $variables['page']      = $view_mode == 'full' && file_entity_is_page($file);
 
   // Hide the file name from being displayed until we can figure out a better
   // way to control this. We cannot simply not output the title since
@@ -792,7 +848,7 @@ function template_preprocess_file_entity(&$variables) {
  * @return
  *   The file type name or FALSE if the file type is not found.
  */
-function file_type_get_name($file) {
+function file_entity_type_get_name($file) {
   $type = is_object($file) ? $file->type : $file;
   $info = entity_get_info('file');
   return isset($info['bundles'][$type]['label']) ? $info['bundles'][$type]['label'] : FALSE;
@@ -804,7 +860,7 @@ function file_type_get_name($file) {
  * @return
  *   An array of file type names, keyed by the type.
  */
-function file_type_get_names() {
+function file_entity_type_get_names() {
   $names = &drupal_static(__FUNCTION__);
 
   if (!isset($names)) {
@@ -897,6 +953,31 @@ function file_entity_get_hidden_stream_wrappers() {
 }
 
 /**
+ * Return a specific stream wrapper's registry information.
+ *
+ * @param $scheme
+ *   A URI scheme, a stream is referenced as "scheme://target".
+ *
+ * @see file_get_stream_wrappers()
+ */
+function file_entity_get_stream_wrapper($scheme) {
+  $wrappers = file_get_stream_wrappers();
+  return isset($wrappers[$scheme]) ? $wrappers[$scheme] : FALSE;
+}
+
+/**
+ * Implements hook_stream_wrappers_alter().
+ */
+function file_entity_stream_wrappers_alter(&$wrappers) {
+  if (isset($wrappers['private'])) {
+    $wrappers['private']['private'] = TRUE;
+  }
+  if (isset($wrappers['temporary'])) {
+    $wrappers['temporary']['private'] = TRUE;
+  }
+}
+
+/**
  * Implements hook_ctools_plugin_api().
  */
 function file_entity_ctools_plugin_api($owner, $api) {
@@ -906,6 +987,187 @@ function file_entity_ctools_plugin_api($owner, $api) {
 }
 
 /**
+ * @defgroup file_entity_access File access rights
+ * @{
+ * The file access system determines who can do what to which files.
+ *
+ * In determining access rights for a file, file_entity_access() first checks
+ * whether the user has the "bypass file access" permission. Such users have
+ * unrestricted access to all files. user 1 will always pass this check.
+ *
+ * Next, all implementations of hook_file_entity_access() will be called. Each
+ * implementation may explicitly allow, explicitly deny, or ignore the access
+ * request. If at least one module says to deny the request, it will be rejected.
+ * If no modules deny the request and at least one says to allow it, the request
+ * will be permitted.
+ *
+ * There is no access grant system for files.
+ *
+ * In file listings, the process above is followed except that
+ * hook_file_entity_access() is not called on each file for performance reasons
+ * and for proper functioning of the pager system. When adding a filelisting to
+ * your module, be sure to use a dynamic query created by db_select()
+ * and add a tag of "file_entity_access". This will allow modules dealing
+ * with file access to ensure only files to which the user has access
+ * are retrieved, through the use of hook_query_TAG_alter().
+ *
+ * Note: Even a single module returning FILE_ENTITY_ACCESS_DENY from
+ * hook_file_entity_access() will block access to the file. Therefore,
+ * implementers should take care to not deny access unless they really intend to.
+ * Unless a module wishes to actively deny access it should return
+ * FILE_ENTITY_ACCESS_IGNORE (or simply return nothing)
+ * to allow other modules to control access.
+ *
+ * Stream wrappers that are considered private should implement a 'private'
+ * flag equal to TRUE in hook_stream_wrappers().
+ *
+ * @todo Unify core's hook_file_download() as a 'download' op of file_entity_access().
+ */
+
+/**
+ * Determine if a user may perform the given operation on the specified file.
+ *
+ * @param $op
+ *   The operation to be performed on the file. Possible values are:
+ *   - "view"
+ *   - "update"
+ *   - "delete"
+ *   - "create"
+ * @param $file
+ *   The file object on which the operation is to be performed, or file type
+ *   (e.g. 'image') for "create" operation.
+ * @param $account
+ *   Optional, a user object representing the user for whom the operation is to
+ *   be performed. Determines access for a user other than the current user.
+ *
+ * @return
+ *   TRUE if the operation may be performed, FALSE otherwise.
+ */
+function file_entity_access($op, $file = NULL, $account = NULL) {
+  $rights = &drupal_static(__FUNCTION__, array());
+
+  if (!$file && !in_array($op, array('view', 'update', 'delete', 'create'), TRUE)) {
+    // If there was no file to check against, or the $op was not one of the
+    // supported ones, we return access denied.
+    return FALSE;
+  }
+
+  // If no user object is supplied, the access check is for the current user.
+  if (empty($account)) {
+    $account = $GLOBALS['user'];
+  }
+
+  if (!$file && $op == 'create') {
+    return user_access('create files', $account);
+  }
+
+  // $file may be either an object or a file type. Since file types cannot be
+  // an integer, use either fid or type as the static cache id.
+  $cid = is_object($file) ? $file->fid : $file;
+
+  // If we've already checked access for this file, user and op, return from
+  // cache.
+  if (isset($rights[$account->uid][$cid][$op])) {
+    return $rights[$account->uid][$cid][$op];
+  }
+
+  if (user_access('bypass file access', $account)) {
+    return $rights[$account->uid][$cid][$op] = TRUE;
+  }
+
+  // We grant access to the file if both of the following conditions are met:
+  // - No modules say to deny access.
+  // - At least one module says to grant access.
+  $access = module_invoke_all('file_entity_access', $op, $file, $account);
+  if (in_array(FILE_ENTITY_ACCESS_DENY, $access, TRUE)) {
+    return $rights[$account->uid][$cid][$op] = FALSE;
+  }
+  elseif (in_array(FILE_ENTITY_ACCESS_ALLOW, $access, TRUE)) {
+    return $rights[$account->uid][$cid][$op] = TRUE;
+  }
+
+
+  // Fall back to default behaviors on view.
+  if ($op == 'view' && is_object($file)) {
+    $scheme = file_uri_scheme($file->uri);
+    $wrapper = file_entity_get_stream_wrapper($scheme);
+
+    if (!empty($wrapper['private'])) {
+      // For private files, users can view their own private files if the
+      // user is not anonymous, and has the 'view own private files' permission.
+      if (!empty($account->uid) && $file->uid == $account->uid && user_access('view own private files', $account)) {
+        return $rights[$account->uid][$cid][$op] = TRUE;
+      }
+    }
+    elseif ($file->status == FILE_STATUS_PERMANENT && user_access('view files')) {
+      // For non-private files, users can view if they have the 'view files'
+      // permission.
+      return $rights[$account->uid][$cid][$op] = TRUE;
+    }
+  }
+
+  return FALSE;
+}
+
+/**
+ * Implements hook_file_entity_access().
+ */
+function file_entity_file_entity_access($op, $file, $account) {
+  $type = is_string($file) ? $file : $file->type;
+
+  // If the file URI is invalid, deny access.
+  if (is_object($file) && !file_valid_uri($file->uri)) {
+    return FILE_ENTITY_ACCESS_DENY;
+  }
+
+  if ($op == 'create') {
+    if (user_access('create files')) {
+      return FILE_ENTITY_ACCESS_ALLOW;
+    }
+  }
+
+  if ($op == 'update') {
+    if (user_access('edit any files', $account) || (user_access('edit own files', $account) && ($account->uid == $file->uid))) {
+      return FILE_ENTITY_ACCESS_ALLOW;
+    }
+  }
+
+  if ($op == 'delete') {
+    if (user_access('delete any files', $account) || (user_access('delete own files', $account) && ($account->uid == $file->uid))) {
+      return FILE_ENTITY_ACCESS_ALLOW;
+    }
+  }
+
+  return FILE_ENTITY_ACCESS_IGNORE;
+}
+
+/**
+ * Implements hook_file_entity_access() on behalf of system.module and private files.
+ */
+function system_file_entity_access($op, $file, $account) {
+  $grants = array();
+  if ($op == 'view' && file_uri_scheme($file->uri) == 'private') {
+    // When viewing private files, we can only invoke hook_file_download()
+    // if the $account user objet matches the current user.
+    if ($GLOBALS['user']->uid == $account->uid) {
+      foreach (module_implements('file_download') as $module) {
+        $access = module_invoke($module, 'file_download', $file->uri);
+        if ($access === -1) {
+          return FILE_ENTITY_ACCESS_DENY;
+        }
+        elseif (!empty($access)) {
+          $grants[] = $access;
+        }
+      }
+    }
+  }
+
+  return !empty($grants) ? FILE_ENTITY_ACCESS_ALLOW : FILE_ENTITY_ACCESS_IGNORE;
+}
+
+/**
+ * @} End of "defgroup file_entity_access".
+ *
  * Implements hook_file_default_types().
  */
 function file_entity_file_default_types() {
diff --git a/file_entity.pages.inc b/file_entity.pages.inc
index 1c6df02..31ba464 100644
--- a/file_entity.pages.inc
+++ b/file_entity.pages.inc
@@ -79,17 +79,24 @@ function file_entity_add_upload_submit($form, &$form_state) {
     return;
   }
 
-  // Redirect to the file edit page after submission.
-  if (file_entity_access('edit')) {
+  // Figure out destination.
+  if (isset($_GET['destination'])) {
+    $destination = drupal_get_destination();
+    unset($_GET['destination']);
+  }
+  elseif (user_access('administer files')) {
     $destination = array('destination' => 'admin/content/file');
-    if (isset($_GET['destination'])) {
-      $destination = drupal_get_destination();
-      unset($_GET['destination']);
-    }
+  }
+  else {
+    $destination = array('destination' => 'file/' . $file->fid);
+  }
+
+  // Redirect to the file edit page after submission.
+  if (file_entity_access('update', $file)) {
     $form_state['redirect'] = array('file/' . $file->fid . '/edit', array('query' => $destination));
   }
   else {
-    $form_state['redirect'] = 'admin/content/file';
+    $form_state['redirect'] = $destination['destination'];
   }
 }
 
@@ -163,7 +170,7 @@ function file_entity_add_upload_multiple_submit($form, &$form_state) {
   }
 
   // Redirect to the file edit page.
-  if (file_entity_access('edit') && module_exists('multiform')) {
+  if (file_entity_access('update', $file) && module_exists('multiform')) {
     $destination = array('destination' => 'admin/content/file');
     if (isset($_GET['destination'])) {
       $destination = drupal_get_destination();
@@ -301,7 +308,7 @@ function file_entity_edit_submit($form, &$form_state) {
   file_save($file);
 
   $args = array(
-    '@type' => file_type_get_name($file),
+    '@type' => file_entity_type_get_name($file),
     '%title' => entity_label('file', $file),
   );
   watchdog('file', '@type: updated %title.', $args);
@@ -366,7 +373,7 @@ function file_delete_form_submit($form, &$form_state) {
     file_delete_multiple(array($file->fid));
 
     $args = array(
-      '@type' => file_type_get_name($file),
+      '@type' => file_entity_type_get_name($file),
       '%title' => entity_label('file', $file),
     );
     watchdog('file', '@type: deleted %title.', $args);
@@ -483,7 +490,7 @@ function file_entity_get_upload_validators(array $options = array()) {
     $validators['file_validate_extensions'] = array($options['file_extensions']);
   }
   else {
-    $validators['file_validate_extensions'] = array(FILE_DEFAULT_ALLOWED_EXTENSIONS);
+    $validators['file_validate_extensions'] = array(FILE_ENTITY_DEFAULT_ALLOWED_EXTENSIONS);
   }
 
   // Validate file size but do not allow anything higher than file_upload_max_size().
diff --git a/tests/file_entity.test b/tests/file_entity.test
index 2799ef4..9822d41 100644
--- a/tests/file_entity.test
+++ b/tests/file_entity.test
@@ -143,7 +143,7 @@ class FileEntityReplaceTestCase extends FileEntityTestHelper {
     $file = reset($this->files['text']);
 
     // Create a user with file edit permissions.
-    $user = $this->drupalCreateUser(array('edit file'));
+    $user = $this->drupalCreateUser(array('edit any files'));
     $this->drupalLogin($user);
 
     // Test that the Upload widget appears for a local file.
