diff --git a/file_entity.admin.inc b/file_entity.admin.inc
index 0e24997..b9428db 100644
--- a/file_entity.admin.inc
+++ b/file_entity.admin.inc
@@ -169,7 +169,7 @@ function file_entity_admin_files_submit($form, &$form_state) {
  * Displays the file type admin overview page.
  */
 function file_entity_list_types_page() {
-  $types = file_info_file_types();
+  $types = file_type_get_types();
   $entity_info = entity_get_info('file');
   $field_ui = module_exists('field_ui');
   $header = array(
@@ -182,6 +182,7 @@ function file_entity_list_types_page() {
     $row = array(array('data' => theme('file_entity_file_type_overview', $info)));
     $path = isset($entity_info['bundles'][$type]['admin']['real path']) ? $entity_info['bundles'][$type]['admin']['real path'] : NULL;
     if ($field_ui) {
+      $row[] = array('data' => isset($path) ? l(t('edit file type'), $path . '/edit') : '');
       $row[] = array('data' => isset($path) ? l(t('manage fields'), $path . '/fields') : '');
       $row[] = array('data' => isset($path) ? l(t('manage display'), $path . '/display') : '');
     }
@@ -316,7 +317,7 @@ function file_entity_file_display_form_submit($form, &$form_state) {
  * Returns HTML for a file type label and description for the file type admin overview page.
  */
 function theme_file_entity_file_type_overview($variables) {
-  return check_plain($variables['label']) . '<div class="description">' . $variables['description'] . '</div>';
+  return check_plain($variables['name']) . '<div class="description">' . $variables['description'] . '</div>';
 }
 
 /**
@@ -342,3 +343,86 @@ function theme_file_entity_file_display_order($variables) {
 
   return $output;
 }
+
+/**
+ * Admin screen for file type settings.
+ */
+function file_entity_file_type_form($form, &$form_state, $type) {
+  $type = file_type_get_type($type);
+
+  $form['#file_type'] = $type;
+
+  $form['name'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Name'),
+    '#description' => t('This is the human readable name of the file type.'),
+    '#required' => TRUE,
+    '#default_value' => $type['name'],
+  );
+  $form['description'] = array(
+    '#type' => 'textarea',
+    '#title' => t('Description'),
+    '#description' => t('This is the description of the file type.'),
+    '#default_value' => $type['description'],
+  );
+  $form['help'] = array(
+    '#type' => 'textarea',
+    '#title' => t('Help text'),
+    '#description' => t('This is the help text that will be displayed when creating files of this type.'),
+    '#default_value' => $type['help'],
+  );
+
+  $form['mimetypes'] = array(
+    '#type' => 'textarea',
+    '#title' => t('Mimetypes'),
+    '#description' => t('Enter one mimetype per line.'),
+    '#default_value' => implode("\n", $type['mimetypes']),
+  );
+
+  $form['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Save'),
+  );
+
+  return $form;
+}
+
+/**
+ * Validation handler for file type settings form.
+ */
+function file_entity_file_type_form_validate($form, &$form_state) {
+  $type = $form['#file_type'];
+
+  $type['mimetypes'] = explode("\n", $form_state['values']['mimetypes']);
+
+  include_once DRUPAL_ROOT . '/includes/file.mimetypes.inc';
+  $mimetypes = file_mimetype_mapping();
+
+  foreach ($type['mimetypes'] as $mimetype) {
+    $mimetype = trim($mimetype);
+    if ($mimetype && !in_array($mimetype, $mimetypes['mimetypes'])) {
+      form_set_error('mimetypes', t('The mimetype %mimetype is not a valid mimetype.', array('%mimetype' => $mimetype)));
+    }
+  }
+}
+
+/**
+ * Submit handler for file type settings form.
+ */
+function file_entity_file_type_form_submit($form, &$form_state) {
+  $type = $form['#file_type'];
+
+  $type['name'] = $form_state['values']['name'];
+  $type['description'] = $form_state['values']['description'];
+  $type['help'] = $form_state['values']['help'];
+
+  $type['mimetypes'] = explode("\n", $form_state['values']['mimetypes']);
+  foreach ($type['mimetypes'] as $key => $mimetype) {
+    $type['mimetypes'][$key] = trim($mimetype);
+    if (!$type['mimetypes'][$key]) {
+      unset($type['mimetypes'][$key]);
+    }
+  }
+
+  file_type_save($type);
+}
diff --git a/file_entity.api.php b/file_entity.api.php
index a7d9e8a..e1548d0 100644
--- a/file_entity.api.php
+++ b/file_entity.api.php
@@ -11,18 +11,19 @@
  * @return
  *   An array whose keys are file type names and whose values are arrays
  *   describing the file type, with the following key/value pairs:
- *   - label: The human-readable name of the file type.
- *   - default view callback: (optional) The name of the function that returns a
- *     drupal_render() array for displaying the file. Used when there are no
- *     administrator configured file formatters, or none of the configured ones
- *     return a display. See hook_file_type_TYPE_default_view() for details.
+ *    *    $info is an object with the following fields:
+ *      ->type => The machine name of the file type, such as 'video';
+ *      ->name => The human readable name;
+ *      ->description => A brief description of the file type;
+ *      ->help ;
+ *      ->custom ;
+ *      ->modified ;
+ *      ->locked ;
+ *      ->disabled ;
+ *      ->mimetypes => An array of mimetypes supported by this file type.
+ *   - type: The machine name of the file type, such as 'video'.
+ *   - name: The human-readable name of the file type.
  *   - description: (optional) A short description of the file type.
- *   - weight: (optional) A number defining the order in which the 'claim
- *     callback' function for this type is called relative to the claim
- *     callbacks of other defined types, when the type of a file needs to be
- *     determined. The type with the lowest weighted claim callback to return
- *     TRUE is assigned to the file. Also, on administrative pages listing file
- *     types, the types are ordered by weight.
  *   - admin: (optional) An array of information, to be added to the
  *     ['bundles'][TYPE]['admin'] entry for the 'file' entity type, thereby
  *     controlling the path at which Field UI pages are attached for this file
diff --git a/file_entity.file_api.inc b/file_entity.file_api.inc
index 79284d1..ef7f3d8 100644
--- a/file_entity.file_api.inc
+++ b/file_entity.file_api.inc
@@ -6,61 +6,6 @@
  */
 
 /**
- * Returns information about file types from hook_file_type_info().
- *
- * @param $file_type
- *   (optional) A file type name. If ommitted, all file types will be returned.
- *
- * @return
- *   Either a file type description, as provided by hook_file_type_info(), or an
- *   array of all existing file types, keyed by file type name.
- */
-function file_info_file_types($file_type = NULL) {
-  $info = &drupal_static(__FUNCTION__);
-  if (!isset($info)) {
-    $info = module_invoke_all('file_type_info');
-
-    // Add support for the standard file types until this can be fully
-    // abstracted out of Media module.
-    $info += array(
-      'application' => array('label' => t('Application (multipurpose)')),
-      'audio' => array('label' => t('Audio')),
-      'image' => array('label' => t('Image')),
-      'text' => array('label' => t('Text')),
-      'video' => array('label' => t('Video')),
-    );
-
-    drupal_alter('file_type_info', $info);
-    uasort($info, '_file_entity_sort_weight_label');
-  }
-  if ($file_type) {
-    if (isset($info[$file_type])) {
-      return $info[$file_type];
-    }
-  }
-  else {
-    return $info;
-  }
-}
-
-/**
- * Determines the file type of a passed in file object.
- *
- * The file type is determined by extracting the 'first' part of the file's
- * MIME type. For example, a PNG image with a MIME type of 'image/png' will
- * have a file type of 'image'.
- *
- * @link http://www.iana.org/assignments/media-types/index.html IANA list of official MIME media types @endlink
- */
-function file_get_type($file) {
-  // Ensure that a MIME type has been determined first.
-  if (empty($file->filemime)) {
-    $file->filemime = file_get_mimetype($file->uri);
-  }
-  return substr($file->filemime, 0, strpos($file->filemime, '/'));
-}
-
-/**
  * Returns information about file formatters from hook_file_formatter_info().
  *
  * @param $formatter_type
@@ -90,14 +35,6 @@ function file_info_formatter_types($formatter_type = NULL) {
 }
 
 /**
- * Clears the file info cache.
- */
-function file_info_cache_clear() {
-  drupal_static_reset('file_info_file_types');
-  drupal_static_reset('file_info_formatter_types');
-}
-
-/**
  * Construct a drupal_render() style array from an array of loaded files.
  *
  * @param $files
@@ -289,17 +226,8 @@ function file_view_file($file, $displays = 'default', $langcode = NULL) {
     }
   }
 
-  // If none of the configured formatters were able to display the file, attempt
-  // to display the file using the file type's default view callback.
-  if (!isset($element)) {
-    $file_type_info = file_info_file_types($file->type);
-    if (isset($file_type_info['default view callback']) && ($function = $file_type_info['default view callback']) && function_exists($function)) {
-      $element = $function($file, $view_mode, $langcode);
-    }
-  }
-
-  // If a render element was returned by a formatter or the file type's default
-  // view callback, add some defaults to it and return it.
+  // If a render element was returned by a formatter, add some defaults to it
+  // and return it.
   if (isset($element)) {
     $element += array(
       '#file' => $file,
@@ -452,7 +380,7 @@ function _file_entity_sort_weight_label($a, $b) {
  *
  * @param $uri
  *   A string containing the URI, path, or filename.
- * @param $use_existing
+ * @param $create_if_not_exists
  *   (Optional) If TRUE and there's an existing file in the {file_managed}
  *   table with the passed in URI, then that file object is returned.
  *   Otherwise, a new file object is returned. Default is TRUE.
@@ -461,9 +389,9 @@ function _file_entity_sort_weight_label($a, $b) {
  *   A file object, or FALSE on error.
  *
  * @todo This should probably be named file_load_by_uri($uri, $create_if_not_exists).
- * @todo Remove this function when http://drupal.org/node/685818 is fixed.
+ * @todo Remove this function when http://drupal.org/file/685818 is fixed.
  */
-function file_uri_to_object($uri, $use_existing = TRUE) {
+function file_uri_to_object($uri, $create_if_not_exists = TRUE) {
   $file = FALSE;
   $uri = file_stream_wrapper_uri_normalize($uri);
 
@@ -509,4 +437,172 @@ function hook_file_operations_info() {
     ),
   );
   return $operations;
-}
\ No newline at end of file
+}
+
+/*
+ * Updates the database cache of file types.
+ *
+ * All new module-defined file types are saved to the database via a call to
+ * file_type_save(), and obsolete ones are deleted via a call to
+ * file_type_delete(). See _file_types_build() for an explanation of the new
+ * and obsolete types.
+ */
+function file_types_rebuild() {
+  _file_types_build(TRUE);
+}
+
+/**
+ * Builds and returns the list of available file types.
+ *
+ * The list of types is built by invoking hook_file_type_info() on all modules and
+ * comparing this information with the file types in the {file_type} table.
+ * These two information sources are not synchronized during module installation
+ * until file_types_rebuild() is called.
+ *
+ * @param $rebuild
+ *  TRUE to rebuild file types. Equivalent to calling file_types_rebuild().
+ * @return
+ *   Associative array with two components:
+ *   - names: Associative array of the names of file types, keyed by the type.
+ *   - types: Associative array of file type objects, keyed by the type.
+ *   Both of these arrays will include new types that have been defined by
+ *   hook_file_info() implementations but not yet saved in the {file_type}
+ *   table. These are indicated in the type object by $type->is_new being set
+ *   to the value 1. These arrays will also include obsolete types: types that
+ *   were previously defined by modules that have now been disabled, or for
+ *   whatever reason are no longer being defined in hook_file_type_info()
+ *   implementations, but are still in the database. These are indicated in the
+ *   type object by $type->disabled being set to TRUE.
+ */
+function _file_types_build($rebuild = FALSE) {
+  $rebuild = TRUE;
+  ctools_include('export');
+  $cid = 'file_types';
+
+  if (!$rebuild) {
+    $_file_types = &drupal_static(__FUNCTION__);
+    if (isset($_file_types)) {
+      return $_file_types;
+    }
+    if ($cache = cache_get($cid)) {
+      $_file_types = $cache->data;
+      return $_file_types;
+    }
+  }
+
+  $_file_types = (object) array('types' => array());
+  $types = ctools_export_crud_load_all('file_type');
+
+  foreach ($types as $type_name => $type) {
+    $_file_types->types[$type_name] = (array) $type;
+  }
+
+  drupal_alter('file_type_info', $_file_types);
+  cache_set($cid, $_file_types);
+  return $_file_types;
+}
+
+/**
+ * Clears the file type cache.
+ */
+function file_type_cache_reset() {
+  cache_clear_all('file_types:', 'cache', TRUE);
+  drupal_static_reset('_file_types_build');
+  drupal_static_reset('file_info_formatter_types');
+}
+
+function file_type_merge_defaults(&$type) {
+  $type += array(
+    'name' => strtoupper($type['type']),
+    'description' => '',
+    'help' => '',
+    'mimetypes' => array(),
+  );
+}
+
+/**
+ *  Update an existing file type or create a new one.
+ *
+ *  @param $type
+ *  The file type to save, as an array or object.
+ */
+function file_type_save(&$type) {
+  ctools_include('export');
+  file_type_merge_defaults($type);
+  $type = (object)$type;
+
+  ctools_export_crud_save('file_type', $type);
+  $type = (array)$type;
+  //  field_attach_create_bundle('file', $type->type);
+
+  // Clear the file type cache.
+//  file_type_cache_reset();
+}
+
+/**
+ * Delete a file type from the database.
+ *
+ * @param $type
+ * The machine-readable name of the file type to be deleted.
+ */
+function file_type_delete($type) {
+  $info = file_type_get_type($type);
+  db_delete('file_type')
+    ->condition('type', $type)
+    ->execute();
+  db_delete('file_type_mimetypes')
+    ->condition('type', $type)
+    ->execute();
+  field_attach_delete_bundle('file', $type);
+  module_invoke_all('file_type_delete', $info);
+
+  // Clear the file type cache.
+  file_type_cache_reset();
+}
+
+/**
+ * Extract the type name.
+ *
+ * @param $file
+ *   Either a string or object, containing the file type information.
+ *
+ * @return
+ *   file type of the passed-in data.
+ */
+function _file_extract_type($file) {
+  return is_object($file) ? $file->type : $file;
+}
+
+/**
+ * Returns a list of all the available file types.
+ *
+ * This list can include types that are queued for addition or deletion.
+ * See _file_types_build() for details.
+ *
+ * @return
+ *   An array of file types, as objects, keyed by the type.
+ *
+ * @see file_type_get_type()
+ */
+function file_type_get_types() {
+  return _file_types_build()->types;
+}
+
+/**
+ * Returns the file type of the passed file or file type string.
+ *
+ * @param $file
+ *   An object or string that indicates the file type to return.
+ *
+ * @return
+ *   A single file type, as an object, or FALSE if the file type is not found.
+ *   The file type is an object containing fields from hook_file_info() return
+ *   values, as well as the field 'type' (the machine-readable type) and other
+ *   fields used internally and defined in _file_types_build(),
+ *   hook_file_info(), and file_type_set_defaults().
+ */
+function file_type_get_type($file) {
+  $type = _file_extract_type($file);
+  $types = _file_types_build()->types;
+  return isset($types[$type]) ? $types[$type] : FALSE;
+}
diff --git a/file_entity.install b/file_entity.install
index 3fe21a2..808187b 100644
--- a/file_entity.install
+++ b/file_entity.install
@@ -23,6 +23,11 @@ function file_entity_schema_alter(&$schema) {
  * Implements hook_schema().
  */
 function file_entity_schema() {
+   // Using this strange looking function name because of http://drupal.org/node/150220.
+  // Any changes to this table should happen after this line.
+  $schema['file_type'] = _file_entity_update_7105_schema_file_type();
+  $schema['file_type_mimetypes'] = _file_entity_update_7105_schema_file_type_mimetypes();
+
   $schema['file_display'] = array(
     'description' => 'Stores configuration options for file displays.',
     'fields' => array(
@@ -126,6 +131,9 @@ function file_entity_install() {
  * Implement hook_uninstall().
  */
 function file_entity_uninstall() {
+  foreach (_file_types_build()->names as $type) {
+    file_type_delete($type);
+  }
   db_drop_field('file_managed', 'type');
 }
 
@@ -246,3 +254,98 @@ function file_entity_update_7104() {
     }
   }
 }
+
+// Using this strange looking function name because of http://drupal.org/node/150220.
+// This function should never be modified.
+function _file_entity_update_7105_schema_file_type() {
+  return array(
+    'description' => 'Stores the settings for file types.',
+    'fields' => array(
+      'type' => array(
+        'description' => 'The machine name of the file type.',
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'name' => array(
+        'description' => 'The human readable name of the file type.',
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '',
+        'translatable' => TRUE,
+      ),
+      'description' => array(
+        'description' => 'A brief description of this file type.',
+        'type' => 'text',
+        'not null' => TRUE,
+        'size' => 'medium',
+        'default' => '',
+        'translatable' => TRUE,
+      ),
+      'help' => array(
+        'description' => 'Help information shown to the user when creating a file of this type.',
+        'type' => 'text',
+        'not null' => TRUE,
+        'size' => 'medium',
+        'default' => '',
+        'translatable' => TRUE,
+      ),
+    ),
+    'primary key' => array('type'),
+    'export' => array(
+      'key' => 'type',
+      'key name' => 'Type',
+      'primary key' => 'type',
+      'default hook' => 'file_type_info',
+      'identifier' => 'file_type',
+      'export type string' => 'ctools_type',
+      'subrecords callback' => 'file_entity_file_type_ctools_subrecords',
+      'save callback' => 'file_entity_file_type_ctools_save',
+//      'delete callback' => 'file_entity_file_type_ctools_delete',
+      'api' => array(
+        'owner' => 'file_entity',
+        'api' => 'file_type',
+        'minimum_version' => 1,
+        'current_version' => 1,
+      ),
+    ),
+  );
+}
+
+// Using this strange looking function name because of http://drupal.org/node/150220.
+// This function should never be modified.
+function _file_entity_update_7105_schema_file_type_mimetypes() {
+  return array(
+    'description' => 'Maps mimetypes to file types.',
+    'fields' => array(
+      'type' => array(
+        'description' => 'The machine name of the file type.',
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'mimetype' => array(
+        'description' => 'Mimetypes mapped to this file type.',
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+    ),
+    'indexes' => array(
+      array('file_type' => 'type'),
+      array('file_type_mimetype' => 'mimetype'),
+    ),
+  );
+}
+
+/**
+ * Add the file_type and file_type_mimetypes tables.
+ */
+function file_entity_update_7105() {
+  db_create_table('file_type', _file_entity_update_7105_schema_file_type());
+  db_create_table('file_type_mimetypes',  _file_entity_update_7105_schema_file_type_mimetypes());
+}
diff --git a/file_entity.module b/file_entity.module
index 5b719ed..da42e9a 100644
--- a/file_entity.module
+++ b/file_entity.module
@@ -118,6 +118,15 @@ function file_entity_menu() {
       // router path).
       $file_type_argument = isset($bundle_info['admin']['bundle argument']) ? $bundle_info['admin']['bundle argument'] : $file_type;
 
+      // Add the 'File type settings' tab.
+      $items["$path/edit"] = array(
+        'title' => 'Edit file type',
+        'page callback' => 'drupal_get_form',
+        'page arguments' => array('file_entity_file_type_form', $file_type_argument),
+        'type' => MENU_LOCAL_TASK,
+        'file' => 'file_entity.admin.inc',
+      ) + $access;
+
       // Add the 'Manage file display' tab.
       $items["$path/file-display"] = array(
         'title' => 'Manage file display',
@@ -189,8 +198,12 @@ function file_entity_theme() {
       'render element' => 'elements',
       'template' => 'file_entity',
     ),
+    'file_entity_file_type_settings' => array(
+      'variables' => array('type' => NULL),
+      'file' => 'file_entity.admin.inc',
+    ),
     'file_entity_file_type_overview' => array(
-      'variables' => array('label' => NULL, 'description' => NULL),
+      'variables' => array('name' => NULL, 'description' => NULL),
       'file' => 'file_entity.admin.inc',
     ),
     'file_entity_file_display_order' => array(
@@ -214,17 +227,14 @@ function file_entity_entity_info_alter(&$entity_info) {
   $entity_info['file']['fieldable'] = TRUE;
   $entity_info['file']['entity keys']['bundle'] = 'type';
   $entity_info['file']['bundles'] = array();
-  foreach (file_info_file_types() as $type => $info) {
-    $info += array(
-      // Provide a default administration path for Field UI, but not if 'admin'
-      // has been explicitly set to NULL.
-      'admin' => array(
-        'path' => 'admin/config/media/file-types/manage/%',
-        'real path' => 'admin/config/media/file-types/manage/' . $type,
-        'bundle argument' => 5,
-      ),
+  foreach (file_type_get_types() as $type => $info) {
+    $info['admin'] = array(
+      'path' => 'admin/config/media/file-types/manage/%',
+      'real path' => 'admin/config/media/file-types/manage/' . $type,
+      'bundle argument' => 5,
     );
-    $entity_info['file']['bundles'][$type] = array_intersect_key($info, drupal_map_assoc(array('label', 'admin')));
+    $entity_info['file']['bundles'][$type]['name'] = $info['name'];
+    $entity_info['file']['bundles'][$type]['admin'] = $info['admin'];
     $entity_info['file']['view callback'] = 'file_view_multiple';
   }
 }
@@ -269,9 +279,6 @@ function file_entity_file_presave($file) {
     $file->filemime = file_get_mimetype($file->uri);
   }
 
-  // Always update file type based on filemime.
-  $file->type = file_get_type($file);
-
   field_attach_presave('file', $file);
 }
 
@@ -484,14 +491,14 @@ function _file_entity_view_mode_menu_access($file_type, $view_mode, $access_call
  * Implements hook_modules_enabled().
  */
 function file_entity_modules_enabled($modules) {
-  file_info_cache_clear();
+  file_type_cache_reset();
 }
 
 /**
  * Implements hook_modules_disabled().
  */
 function file_entity_modules_disabled($modules) {
-  file_info_cache_clear();
+  file_type_cache_reset();
 }
 
 /**
@@ -704,6 +711,148 @@ function file_entity_get_hidden_stream_wrappers() {
 }
 
 /**
+ * Implements hook_file_type_info().
+ */
+function file_entity_file_type_info() {
+  // Insert default pre-defined file types into the database. For a complete
+  // list of available file type attributes, refer to the file type API
+  // documentation.
+  $types = array();
+  $types['image'] = (object)array(
+    'api_version' => 1,
+    'type' => 'image',
+    'name' => t('Image'),
+    'description' => t("An <em>Image</em> is a two-dimensional picture that has a similar appearance to some subject, usually a physical object or a person."),
+    'mimetypes' => array(
+      'image/jpeg',
+      'image/gif',
+      'image/png',
+    ),
+  );
+
+  $types['video'] = (object)array(
+    'api_version' => 1,
+    'type' => 'video',
+    'name' => t('Video'),
+    'description' => t('<em>Videos</em> are a sequence of still images representing scenes in motion.'),
+    'mimetypes' => array(
+      'video/quicktime',
+      'video/mp4',
+      'video/x-msvideo',
+      'video/ogg',
+    ),
+  );
+
+  $types['audio'] = (object)array(
+    'api_version' => 1,
+    'type' => 'audio',
+    'name' => t('Audio'),
+    'description' => t('<em>Audio</em> files are an electrical representation of sound.'),
+    'mimetypes' => array(
+      'audio/mpeg',
+      'audio/x-ms-wma',
+      'audio/x-wav',
+      'audio/ogg',
+    ),
+  );
+
+  $types['document'] = (object)array(
+    'api_version' => 1,
+    'type' => 'document',
+    'name' => t('Document'),
+    'description' => t('A <em>Document</em> is a work of writing intended to store and communicate information.'),
+    'mimetypes' => array(
+      'text/plain',
+      'application/msword',
+      'application/vnd.ms-excel',
+      'application/pdf',
+      'application/vnd.ms-powerpoint',
+      'application/vnd.oasis.opendocument.text',
+      'application/vnd.oasis.opendocument.spreadsheet',
+      'application/vnd.oasis.opendocument.presentation',
+    ),
+  );
+
+  return $types;
+}
+
+function file_entity_file_type_ctools_subrecords($objects) {
+  foreach ($objects as $name => $type) {
+    // Then load the mimetypes.
+    $objects[$name]->mimetypes = array();
+    $results = db_select('file_type_mimetypes', 'ftm')
+      ->fields('ftm', array('mimetype'))
+      ->condition('ftm.type', $objects[$name]->type)
+      ->execute();
+    foreach ($results as $mimetype) {
+      $objects[$name]->mimetypes[] = $mimetype->mimetype;
+    }
+  }
+}
+
+/**
+ * Load callback called when ctools exportables saves a file type.
+ */
+function file_entity_file_type_ctools_save($object) {
+  $table = 'file_type';
+  $schema = ctools_export_get_schema($table);
+  $export = $schema['export'];
+
+    // Objects should have a serial primary key. If not, simply fail to write.
+    if (empty($export['primary key'])) {
+      return FALSE;
+    }
+
+    $key = $export['primary key'];
+    if ($object->export_type & EXPORT_IN_DATABASE) {
+      // Existing record.
+      $update = array($key);
+    }
+    else {
+      // New record.
+      $update = array();
+      $object->export_type = EXPORT_IN_DATABASE;
+    }
+    drupal_write_record($table, $object, $update);
+
+  // Then save the mimetypes.
+  db_delete('file_type_mimetypes')
+    ->condition('type', $object->type)
+    ->execute();
+
+  foreach ($object->mimetypes as $mimetype) {
+    db_insert('file_type_mimetypes')
+      ->fields(array('type' => $object->type, 'mimetype' => $mimetype))
+      ->execute();
+  }
+}
+
+/**
+ * Load callback called when ctools exportables deletes a file type.
+ */
+function file_entity_file_type_ctools_delete($name) {
+  $file_type = ctools_export_load_object('file_type', 'names', array($name));
+  // Then delete the mimetypes.
+  db_delete('file_type_mimetypes')
+    ->condition('type', $type->type)
+    ->execute();
+}
+
+/**
+ * Implements hook_ctools_plugin_api().
+ */
+function file_entity_ctools_plugin_api($owner, $api) {
+  static $api_versions = array(
+    'file_entity' => array(
+      'file_type' => 1,
+    ),
+  );
+  if (isset($api_versions[$owner][$api])) {
+    return array('version' => $api_versions[$owner][$api]);
+  }
+}
+
+/**
  * @see theme_file_file_link.
  * This is a copy of it, except we make the url file/$fid.
  *
diff --git a/file_entity.tokens.inc b/file_entity.tokens.inc
index 4ace9c5..f3453b6 100644
--- a/file_entity.tokens.inc
+++ b/file_entity.tokens.inc
@@ -66,15 +66,15 @@ function file_entity_tokens($type, $tokens, array $data = array(), array $option
     foreach ($tokens as $name => $original) {
       switch ($name) {
         case 'type':
-          if ($file_type = file_info_file_types($file->type)) {
-            $replacements[$original] = $sanitize ? check_plain($file_type['label']) : $file_type['label'];
+          if ($file_type = file_type_get_types($file->type)) {
+            $replacements[$original] = $sanitize ? check_plain($file_type['name']) : $file_type['name'];
           }
           break;
       }
     }
 
     // Chained token relationships.
-    if (($file_type_tokens = token_find_with_prefix($tokens, 'type')) && $file_type = file_info_file_types($file->type)) {
+    if (($file_type_tokens = token_find_with_prefix($tokens, 'type')) && $file_type = file_type_get_types($file->type)) {
       $file_type['type'] = $file->type;
       $replacements += token_generate('file-type', $file_type_tokens, array('file_type' => $file_type), $options);
     }
