commit ca0757b91c38c78a1434a92ac17297b4d6db712f
Author: Assos Assos <assos+forge@centrale-marseille.fr>
Date:   Wed Oct 8 22:51:03 2014 +0200

    Weekly update of contrib modules

diff --git a/drupal7/sites/all/modules/date_ical/date_ical.api.php b/drupal7/sites/all/modules/date_ical/date_ical.api.php
index 24abdb1d..22a710c9 100644
--- a/drupal7/sites/all/modules/date_ical/date_ical.api.php
+++ b/drupal7/sites/all/modules/date_ical/date_ical.api.php
@@ -221,3 +221,32 @@ function hook_date_ical_import_timezone_alter(&$tzid, $context) {
     $tzid = 'America/New_York';
   }
 }
+
+/**
+ * Add an additional custom source to be mapped by a feed.
+ *
+ * This is useful when you need to map fields from an iCal feed which
+ * the Date iCal module does not currently support.
+ *
+ * @param array $sources
+ *   An associative array containing the source's properties, as follows:
+ *     name: The name that will appear in the feed importer Mapping page.
+ *     description: The description of this field shown in the Mapping page.
+ *     date_ical_parse_handler: The function in the ParserVcalendar class
+ *       which should be used to parse this iCal property into a Drupal field.
+ */
+function hook_date_ical_mapping_sources_alter(&$sources) {
+  // Example of what might be done with this alter hook:
+  // Add the "ATTENDEE" iCal property to the mapping sources.
+  $sources['ATTENDEE'] = array(
+    'name' => t('Attendee'),
+    'description' => t('The ATTENDEE property.'),
+    'date_ical_parse_handler' => 'parseTextProperty',
+  );
+  // Add "ATTENDEE:CN" parameter to the mapping sources.
+  $sources['ATTENDEE:CN'] = array(
+    'name' => t('Attendee: CN'),
+    'description' => t("The CN parameter of the ATTENDEE property: the attendee's Common Name."),
+    'date_ical_parse_handler' => 'parsePropertyParameter',
+  );
+}
diff --git a/drupal7/sites/all/modules/date_ical/date_ical.info b/drupal7/sites/all/modules/date_ical/date_ical.info
index d0943167..52c4f0db 100644
--- a/drupal7/sites/all/modules/date_ical/date_ical.info
+++ b/drupal7/sites/all/modules/date_ical/date_ical.info
@@ -21,9 +21,9 @@ files[] = includes/date_ical_plugin_style_ical_feed.inc
 ; Includes for iCal feed import using Feeds
 files[] = includes/DateiCalFeedsParser.inc
 
-; Information added by Drupal.org packaging script on 2014-05-30
-version = "7.x-3.2"
+; Information added by Drupal.org packaging script on 2014-10-08
+version = "7.x-3.3"
 core = "7.x"
 project = "date_ical"
-datestamp = "1401492228"
+datestamp = "1412727230"
 
diff --git a/drupal7/sites/all/modules/date_ical/date_ical.module b/drupal7/sites/all/modules/date_ical/date_ical.module
index aa716c4c..f9c314ff 100644
--- a/drupal7/sites/all/modules/date_ical/date_ical.module
+++ b/drupal7/sites/all/modules/date_ical/date_ical.module
@@ -10,7 +10,7 @@
  * value of the iCal feeds created by Date iCal. It's primarily used for
  * debugging.
  */
-define('DATE_ICAL_VERSION', '3.2');
+define('DATE_ICAL_VERSION', '3.3');
 
 /**
  * Exception class for generic exceptions thrown by this module.
@@ -222,29 +222,28 @@ function date_ical_feeds_processor_targets_alter(&$targets, $entity_type, $bundl
 /**
  * Reformats the provided text to be compliant with the iCal spec.
  *
- * If the text contains HTML tags, those tags will be stripped (with <p> tags
- * converted to "\n\n" and link tags converted to footnotes), and uneeded
- * whitespace will be cleaned up.
+ * If the text contains HTML tags, those tags will be stripped. Paragraph,
+ * heading, and div tags will be replaced with newlines.
  *
  * @param string $text
  *   The text to be sanitized.
  */
 function date_ical_sanitize_text($text = '') {
-  // Use Drupal's built-in HTML to Text converter, which does a mostly
-  // adequate job of making the text iCal-compliant.
-  $text = trim(drupal_html_to_text($text));
-  // Replace instances of more than one space with exactly one space. This
-  // cleans up the whitespace mess that drupal_html_to_text() leaves behind.
-  $text = preg_replace("/  +/", " ", $text);
-  // The call to drupal_html_to_text() above converted <p> to \n\n, and also
-  // shoved a \n into the string every 80 characters. We don't want those
-  // single \n's lying around, because iCalcreator will properly "fold" long
-  // text fields for us. So, we need to remove all instances of \n which
-  // are neither immediately preceeded, nor followed, by another \n.
-  // However, \n's which are followed immediately by a > character should
-  // remain, because of how drupal_html_to_text() converts <blockquote>.
-  $text = preg_replace("/(?<!\n)\n(?![\n\>])/", " ", $text);
-  return $text;
+  // HTML tags may get converted to &lt; and such by the View code, so we need
+  // to convert them back to HTML so we can remove them with strip_tags().
+  $text = decode_entities($text);
+  
+  // Convert <p> tags to double newlines.
+  $text = trim(preg_replace("/<p.*?>/i", "\n\n", $text));
+  // Separate heading tags from the text around them in both directions.
+  $text = trim(preg_replace("/<\\?h\d.*?>/i", "\n\n", $text));
+  // Add a newline for each <div>.
+  $text = trim(preg_replace("/<div.*?>/i", "\n", $text));
+  
+  // Strip the remaining HTML.
+  $text = strip_tags($text);
+  // Remove newlines added at the beginning.
+  return trim($text);
 }
 
 /**
diff --git a/drupal7/sites/all/modules/date_ical/includes/DateiCalFeedsParser.inc b/drupal7/sites/all/modules/date_ical/includes/DateiCalFeedsParser.inc
index 83270737..c1863f5b 100644
--- a/drupal7/sites/all/modules/date_ical/includes/DateiCalFeedsParser.inc
+++ b/drupal7/sites/all/modules/date_ical/includes/DateiCalFeedsParser.inc
@@ -85,6 +85,7 @@ class DateiCalFeedsParser extends FeedsParser {
   public function configDefaults() {
     return array(
       'indefinite_count' => '52',
+      'indefinite_message_display' => TRUE,
       'until_not_utc' => FALSE,
       'skip_days' => NULL,
     );
@@ -107,6 +108,12 @@ class DateiCalFeedsParser extends FeedsParser {
       '#description' => t('Indefinitely repeating events are not supported. The repeat count will instead be set to this number.'),
       '#default_value' => $this->config['indefinite_count'],
     );
+    $form['indefinite_message_display'] = array(
+      '#title' => t('Display message when RRULE is missing COUNT'),
+      '#type' => 'checkbox',
+      '#default_value' => $this->config['indefinite_message_display'],
+      '#description' => t('Display a message when an indefinitely repeating rule is adjusted by the "Indefinite COUNT" setting above.'),
+    );
     $form['until_not_utc'] = array(
       '#title' => t('RRULE UNTILs are not in UTC'),
       '#type' => 'checkbox',
@@ -196,6 +203,10 @@ class DateiCalFeedsParser extends FeedsParser {
       'description' => t('The CATEGORIES property. Catagories that describe the event, which can be imported into taxonomy terms.'),
       'date_ical_parse_handler' => 'parseMultivalueProperty',
     );
+    
+    // Allow other modules to add custom source fields.
+    drupal_alter('date_ical_mapping_sources', $sources);
+    
     return $sources;
   }
 }
diff --git a/drupal7/sites/all/modules/date_ical/includes/date_ical_plugin_row_ical_entity.inc b/drupal7/sites/all/modules/date_ical/includes/date_ical_plugin_row_ical_entity.inc
index 723ee5f7..0c664da6 100644
--- a/drupal7/sites/all/modules/date_ical/includes/date_ical_plugin_row_ical_entity.inc
+++ b/drupal7/sites/all/modules/date_ical/includes/date_ical_plugin_row_ical_entity.inc
@@ -248,7 +248,7 @@ class date_ical_plugin_row_ical_entity extends views_plugin_row {
           // Make sure this Node Reference actually references a node.
           if ($location_field['nid']) {
             $node = node_load($location_field['nid']);
-            $location = check_plain($node->title);
+            $location = $node->title;
           }
         }
         elseif ($location_info['type'] == 'addressfield') {
@@ -276,10 +276,10 @@ class date_ical_plugin_row_ical_entity extends views_plugin_row {
               $location_data[] = $location_field[$included_field];
             }
           }
-          $location = check_plain(implode(', ', $location_data));
+          $location = implode(', ', $location_data);
         }
         else {
-          $location = check_plain($location_field['value']);
+          $location = $location_field['value'];
         }
       }
     }
@@ -345,7 +345,7 @@ class date_ical_plugin_row_ical_entity extends views_plugin_row {
     $event['url'] = url($uri['path'], $uri['options']);
     $event['rrule'] = $is_field && array_key_exists('rrule', $date_field) ? $date_field['rrule'] : '';
     if ($location) {
-      $event['location'] = $location;
+      $event['location'] = date_ical_sanitize_text($location);
     }
     
     // For this event's UID, use either the date_id generated by the Date
diff --git a/drupal7/sites/all/modules/date_ical/includes/date_ical_plugin_row_ical_fields.inc b/drupal7/sites/all/modules/date_ical/includes/date_ical_plugin_row_ical_fields.inc
index c632b1a1..c9540c76 100644
--- a/drupal7/sites/all/modules/date_ical/includes/date_ical_plugin_row_ical_fields.inc
+++ b/drupal7/sites/all/modules/date_ical/includes/date_ical_plugin_row_ical_fields.inc
@@ -226,13 +226,11 @@ class date_ical_plugin_row_ical_fields extends views_plugin_row {
     drupal_alter('date_ical_export_html', $text_fields, $this->view, $context);
     
     // Sanitize the text fields for iCal compliance, and add them to the event.
-    // Also strip all HTML from the summary and location fields, since they
-    // must be plaintext, and may have been set as links by the view.
-    $event['summary'] = date_ical_sanitize_text(strip_tags($text_fields['summary']));
-    $event['location'] = date_ical_sanitize_text(strip_tags($text_fields['location']));
+    $event['summary'] = date_ical_sanitize_text($text_fields['summary']);
+    $event['location'] = date_ical_sanitize_text($text_fields['location']);
     $event['description'] = date_ical_sanitize_text($text_fields['description']);
     
-    // Allow other modules to alter the event object, before it gets passed to
+    // Allow other modules to alter the event object before it gets passed to
     // the style plugin to be converted into an iCal VEVENT.
     drupal_alter('date_ical_export_raw_event', $event, $this->view, $context);
     
diff --git a/drupal7/sites/all/modules/date_ical/libraries/ParserVcalendar.inc b/drupal7/sites/all/modules/date_ical/libraries/ParserVcalendar.inc
index a714a7dd..0b5d8422 100644
--- a/drupal7/sites/all/modules/date_ical/libraries/ParserVcalendar.inc
+++ b/drupal7/sites/all/modules/date_ical/libraries/ParserVcalendar.inc
@@ -33,6 +33,17 @@ class ParserVcalendar {
   protected $totalComponents = 0;
   protected $lastComponentParsed = 0;
   
+  /**
+   * This is the list of iCal properties which are allowed to have more than
+   * one entry in a single VEVENT. If we ever support parsing more than just
+   * the first one, this listing will be useful.
+   */
+  protected $multi_entry_properties = array(
+    'ATTACH', 'ATTENDEE', 'CATEGORIES', 'COMMENT', 'CONTACT', 'DESCRIPTION',
+    'EXDATE', 'EXRULE', 'FREEBUSY', 'RDATE', 'RELATED-TO', 'RESOURCES',
+    'RRULE', 'REQUEST-STATUS', 'TZNAME', 'X-PROP'
+  );
+  
   /**
    * Constructor.
    */
@@ -123,8 +134,9 @@ class ParserVcalendar {
           else {
             // We can safely ignore certain sources.
             $known_unknowns = array(
-              // "Black Source 1" is from Feeds Tamper.
-              'Blank source 1',
+              'Blank source 1', // "Black Source 1" is from Feeds Tamper.
+              'parent:nid', // Defined in FeedsParser
+              'parent:uid', // Defined in FeedsParser
             );
             if (!in_array($property_key, $known_unknowns)) {
               // Only warn the user if this mapping source is in use.
@@ -180,6 +192,21 @@ class ParserVcalendar {
     return $this->lastComponentParsed;
   }
   
+  /**
+   * Handler that parses GEO fields.
+   *
+   * @return array
+   *   The latitude and longitude values, keyed by 'lat' and 'lon'.
+   */
+  public function parseGeofield($property_key, $vcalendar_component) {
+    $geo = array();
+    if (!empty($vcalendar_component->geo['value'])) {
+      $geo['lat'] = $vcalendar_component->geo['value']['latitude'];
+      $geo['lon'] = $vcalendar_component->geo['value']['longitude'];
+    }
+    return $geo;
+  }
+  
   /**
    * Handler that parses text fields.
    *
@@ -188,6 +215,15 @@ class ParserVcalendar {
    */
   public function parseTextProperty($property_key, $vcalendar_component) {
     $text = $vcalendar_component->getProperty($property_key);
+    // In case someone writes a hook that adds a source for a multi-entry
+    // property and a parameter of that same property, we need to force
+    // iCalcreator to assume it has not accessed that property, yet.
+    // TODO: This is really just a hack. If/when multi-entry properties
+    // become supported, this will need to be redesigned.
+    if (in_array($property_key, $this->multi_entry_properties)) {
+      unset($vcalendar_component->propix[$property_key]);
+    }
+    
     if ($text === FALSE) {
       if ($property_key == 'SUMMARY') {
         $uid = $vcalendar_component->getProperty('UID');
@@ -201,21 +237,6 @@ class ParserVcalendar {
     return $text;
   }
   
-  /**
-   * Handler that parses GEO fields.
-   *
-   * @return array
-   *   The latitude and longitude values, keyed by 'lat' and 'lon'.
-   */
-  public function parseGeofield($property_key, $vcalendar_component) {
-    $geo = array();
-    if (!empty($vcalendar_component->geo['value'])) {
-      $geo['lat'] = $vcalendar_component->geo['value']['latitude'];
-      $geo['lon'] = $vcalendar_component->geo['value']['longitude'];
-    }
-    return $geo;
-  }
-  
   /**
    * Handler that parses field parameters.
    *
@@ -225,6 +246,11 @@ class ParserVcalendar {
   public function parsePropertyParameter($property_key, $vcalendar_component) {
     list($key, $attr) = explode(':', $property_key);
     $property = $vcalendar_component->getProperty($key, FALSE, TRUE);
+    // See parseTextProperty() for why this is here.
+    if (in_array($property_key, $this->multi_entry_properties)) {
+      unset($vcalendar_component->propix[$property_key]);
+    }
+        
     if ($property === FALSE) {
       // If the component doesn't have this property, return NULL.
       return NULL;
@@ -422,17 +448,19 @@ class ParserVcalendar {
         $rrule_data['value']['INTERVAL'] = '1';
       }
       
-      if (!isset($rrule_data['value']['COUNT']) && !isset($rrule_data['value']['UNTIL'])) {
+      if ((!isset($rrule_data['value']['COUNT']) && !isset($rrule_data['value']['UNTIL']))) {
         $msg = "The event with UID %uid has an indefinitely repeating RRULE, which the Date Repeat module doesn't support.
           As a workaround, Date iCal set the repeat count to @count. This value can be customized in the iCal parser settings.";
         watchdog('date_ical', $msg, array('%uid' => $uid, '@count' => $count), WATCHDOG_WARNING);
-        drupal_set_message(
-          t("At least one of the events in this iCal feed has an indefinitely repeating RRULE, which the Date Repeat module doesn't support.<br>
-            As a workaround, Date iCal set the repeat count to @count. This value can be customized in the iCal parser settings.",
-          array('@count' => $count)),
-          'warning',
-          FALSE
-        );
+        if ($this->config['indefinite_message_display']) {
+          drupal_set_message(
+            t("At least one of the events in this iCal feed has an indefinitely repeating RRULE, which the Date Repeat module doesn't support.<br>
+              As a workaround, Date iCal set the repeat count to @count. This value can be customized in the iCal parser settings.",
+            array('@count' => $count)),
+            'warning',
+            FALSE
+          );
+        }
         $rrule_data['value']['COUNT'] = $this->config['indefinite_count'];
       }
     }
diff --git a/drupal7/sites/all/modules/file_entity/admin_views_default/file.admin-content-file.inc b/drupal7/sites/all/modules/file_entity/admin_views_default/file.admin-content-file.inc
index e0c8a747..c108497c 100644
--- a/drupal7/sites/all/modules/file_entity/admin_views_default/file.admin-content-file.inc
+++ b/drupal7/sites/all/modules/file_entity/admin_views_default/file.admin-content-file.inc
@@ -33,71 +33,78 @@ $handler->display->display_options['pager']['options']['id'] = '0';
 $handler->display->display_options['pager']['options']['quantity'] = '9';
 $handler->display->display_options['style_plugin'] = 'table';
 $handler->display->display_options['style_options']['columns'] = array(
-  'views_bulk_operations' => 'views_bulk_operations',
-  'filename' => 'filename',
-  'type' => 'type',
-  'name' => 'name',
-  'filesize' => 'filesize',
-  'timestamp' => 'timestamp',
-  'edit' => 'edit',
-  'delete' => 'delete',
+    'views_bulk_operations' => 'views_bulk_operations',
+    'filename' => 'filename',
+    'type' => 'type',
+    'name' => 'name',
+    'filesize' => 'filesize',
+    'timestamp' => 'timestamp',
+    'edit' => 'edit',
+    'delete' => 'delete',
 );
 $handler->display->display_options['style_options']['default'] = 'timestamp';
 $handler->display->display_options['style_options']['info'] = array(
-  'views_bulk_operations' => array(
-    'align' => '',
-    'separator' => '',
-    'empty_column' => 0,
-  ),
-  'filename' => array(
-    'sortable' => 1,
-    'default_sort_order' => 'asc',
-    'align' => '',
-    'separator' => '',
-    'empty_column' => 0,
-  ),
-  'type' => array(
-    'sortable' => 1,
-    'default_sort_order' => 'asc',
-    'align' => '',
-    'separator' => '',
-    'empty_column' => 0,
-  ),
-  'name' => array(
-    'sortable' => 1,
-    'default_sort_order' => 'asc',
-    'align' => '',
-    'separator' => '',
-    'empty_column' => 0,
-  ),
-  'filesize' => array(
-    'sortable' => 1,
-    'default_sort_order' => 'asc',
-    'align' => '',
-    'separator' => '',
-    'empty_column' => 0,
-  ),
-  'timestamp' => array(
-    'sortable' => 1,
-    'default_sort_order' => 'desc',
-    'align' => '',
-    'separator' => '',
-    'empty_column' => 0,
-  ),
-  'edit' => array(
-    'sortable' => 0,
-    'default_sort_order' => 'asc',
-    'align' => '',
-    'separator' => '',
-    'empty_column' => 0,
-  ),
-  'delete' => array(
-    'sortable' => 0,
-    'default_sort_order' => 'asc',
-    'align' => '',
-    'separator' => '',
-    'empty_column' => 0,
-  ),
+    'views_bulk_operations' => array(
+        'align' => '',
+        'separator' => '',
+        'empty_column' => 0,
+    ),
+    'filename' => array(
+        'sortable' => 1,
+        'default_sort_order' => 'asc',
+        'align' => '',
+        'separator' => '',
+        'empty_column' => 0,
+    ),
+    'type' => array(
+        'sortable' => 1,
+        'default_sort_order' => 'asc',
+        'align' => '',
+        'separator' => '',
+        'empty_column' => 0,
+    ),
+    'name' => array(
+        'sortable' => 1,
+        'default_sort_order' => 'asc',
+        'align' => '',
+        'separator' => '',
+        'empty_column' => 0,
+    ),
+    'filesize' => array(
+        'sortable' => 1,
+        'default_sort_order' => 'asc',
+        'align' => '',
+        'separator' => '',
+        'empty_column' => 0,
+    ),
+    'timestamp' => array(
+        'sortable' => 1,
+        'default_sort_order' => 'desc',
+        'align' => '',
+        'separator' => '',
+        'empty_column' => 0,
+    ),
+    'edit' => array(
+        'sortable' => 0,
+        'default_sort_order' => 'asc',
+        'align' => '',
+        'separator' => '',
+        'empty_column' => 0,
+    ),
+    'usage' => array(
+        'sortable' => 1,
+        'default_sort_order' => 'asc',
+        'align' => '',
+        'separator' => '',
+        'empty_column' => 0,
+    ),
+    'delete' => array(
+        'sortable' => 0,
+        'default_sort_order' => 'asc',
+        'align' => '',
+        'separator' => '',
+        'empty_column' => 0,
+    ),
 );
 $handler->display->display_options['style_options']['sticky'] = TRUE;
 $handler->display->display_options['style_options']['empty_table'] = TRUE;
@@ -123,111 +130,130 @@ $handler->display->display_options['fields']['views_bulk_operations']['vbo_setti
 $handler->display->display_options['fields']['views_bulk_operations']['vbo_settings']['force_single'] = 0;
 $handler->display->display_options['fields']['views_bulk_operations']['vbo_settings']['entity_load_capacity'] = '10';
 $handler->display->display_options['fields']['views_bulk_operations']['vbo_operations'] = array(
-  'action::views_bulk_operations_archive_action' => array(
-    'selected' => 1,
-    'postpone_processing' => 0,
-    'skip_confirmation' => 0,
-    'override_label' => 1,
-    'label' => 'Archive',
-    'settings' => array(
-      'scheme' => 'public',
-      'temporary' => 1,
+    'action::views_bulk_operations_archive_action' => array(
+        'selected' => 1,
+        'postpone_processing' => 0,
+        'skip_confirmation' => 0,
+        'override_label' => 1,
+        'label' => 'Archive',
+        'settings' => array(
+            'scheme' => 'public',
+            'temporary' => 1,
+        ),
+    ),
+    'action::views_bulk_operations_delete_item' => array(
+        'selected' => 1,
+        'postpone_processing' => 0,
+        'skip_confirmation' => 0,
+        'override_label' => 1,
+        'label' => 'Delete',
+    ),
+    'action::views_bulk_operations_script_action' => array(
+        'selected' => 0,
+        'postpone_processing' => 0,
+        'skip_confirmation' => 0,
+        'override_label' => 0,
+        'label' => '',
+    ),
+    'action::views_bulk_operations_modify_action' => array(
+        'selected' => 1,
+        'postpone_processing' => 0,
+        'skip_confirmation' => 1,
+        'override_label' => 1,
+        'label' => 'Change value',
+        'settings' => array(
+            'show_all_tokens' => 1,
+            'display_values' => array(
+                '_all_' => '_all_',
+            ),
+        ),
     ),
-  ),
-  'action::views_bulk_operations_delete_item' => array(
-    'selected' => 1,
-    'postpone_processing' => 0,
-    'skip_confirmation' => 0,
-    'override_label' => 1,
-    'label' => 'Delete',
-  ),
-  'action::views_bulk_operations_script_action' => array(
-    'selected' => 0,
-    'postpone_processing' => 0,
-    'skip_confirmation' => 0,
-    'override_label' => 0,
-    'label' => '',
-  ),
-  'action::views_bulk_operations_modify_action' => array(
-    'selected' => 1,
-    'postpone_processing' => 0,
-    'skip_confirmation' => 1,
-    'override_label' => 1,
-    'label' => 'Change value',
-    'settings' => array(
-      'show_all_tokens' => 1,
-      'display_values' => array(
-        '_all_' => '_all_',
-      ),
+    'action::views_bulk_operations_argument_selector_action' => array(
+        'selected' => 0,
+        'skip_confirmation' => 0,
+        'override_label' => 0,
+        'label' => '',
+        'settings' => array(
+            'url' => '',
+        ),
     ),
-  ),
-  'action::views_bulk_operations_argument_selector_action' => array(
-    'selected' => 0,
-    'skip_confirmation' => 0,
-    'override_label' => 0,
-    'label' => '',
-    'settings' => array(
-      'url' => '',
+    'action::system_send_email_action' => array(
+        'selected' => 0,
+        'postpone_processing' => 0,
+        'skip_confirmation' => 0,
+        'override_label' => 0,
+        'label' => '',
+    ),
+    'action::panelizer_set_status_action' => array(
+        'selected' => 0,
+        'postpone_processing' => 0,
+        'skip_confirmation' => 0,
+        'override_label' => 0,
+        'label' => '',
     ),
-  ),
-  'action::system_send_email_action' => array(
-    'selected' => 0,
-    'postpone_processing' => 0,
-    'skip_confirmation' => 0,
-    'override_label' => 0,
-    'label' => '',
-  ),
-  'action::panelizer_set_status_action' => array(
-    'selected' => 0,
-    'postpone_processing' => 0,
-    'skip_confirmation' => 0,
-    'override_label' => 0,
-    'label' => '',
-  ),
 );
 /* Field: File: Name */
 $handler->display->display_options['fields']['filename']['id'] = 'filename';
 $handler->display->display_options['fields']['filename']['table'] = 'file_managed';
 $handler->display->display_options['fields']['filename']['field'] = 'filename';
+$handler->display->display_options['fields']['filename']['label'] = 'Title';
 /* Field: File: Type */
 $handler->display->display_options['fields']['type']['id'] = 'type';
 $handler->display->display_options['fields']['type']['table'] = 'file_managed';
 $handler->display->display_options['fields']['type']['field'] = 'type';
 $handler->display->display_options['fields']['type']['machine_name'] = 0;
+/* Field: File: Size */
+$handler->display->display_options['fields']['filesize']['id'] = 'filesize';
+$handler->display->display_options['fields']['filesize']['table'] = 'file_managed';
+$handler->display->display_options['fields']['filesize']['field'] = 'filesize';
+$handler->display->display_options['fields']['filesize']['empty'] = '0 bytes';
 /* Field: User: Name */
 $handler->display->display_options['fields']['name']['id'] = 'name';
 $handler->display->display_options['fields']['name']['table'] = 'users';
 $handler->display->display_options['fields']['name']['field'] = 'name';
 $handler->display->display_options['fields']['name']['relationship'] = 'uid';
-$handler->display->display_options['fields']['name']['label'] = 'User';
-/* Field: File: Size */
-$handler->display->display_options['fields']['filesize']['id'] = 'filesize';
-$handler->display->display_options['fields']['filesize']['table'] = 'file_managed';
-$handler->display->display_options['fields']['filesize']['field'] = 'filesize';
+$handler->display->display_options['fields']['name']['label'] = 'Author';
 /* Field: File: Upload date */
 $handler->display->display_options['fields']['timestamp']['id'] = 'timestamp';
 $handler->display->display_options['fields']['timestamp']['table'] = 'file_managed';
 $handler->display->display_options['fields']['timestamp']['field'] = 'timestamp';
-$handler->display->display_options['fields']['timestamp']['label'] = 'Uploaded';
+$handler->display->display_options['fields']['timestamp']['label'] = 'Updated';
 $handler->display->display_options['fields']['timestamp']['date_format'] = 'short';
+$handler->display->display_options['fields']['timestamp']['second_date_format'] = 'long';
+/* Field: File: Usage link */
+$handler->display->display_options['fields']['usage']['id'] = 'usage';
+$handler->display->display_options['fields']['usage']['table'] = 'file_managed';
+$handler->display->display_options['fields']['usage']['field'] = 'usage';
+$handler->display->display_options['fields']['usage']['label'] = 'Used in';
+$handler->display->display_options['fields']['usage']['element_label_colon'] = FALSE;
 /* Field: File: Edit link */
 $handler->display->display_options['fields']['edit']['id'] = 'edit';
 $handler->display->display_options['fields']['edit']['table'] = 'file_managed';
 $handler->display->display_options['fields']['edit']['field'] = 'edit';
 $handler->display->display_options['fields']['edit']['label'] = '';
+$handler->display->display_options['fields']['edit']['exclude'] = TRUE;
 $handler->display->display_options['fields']['edit']['element_label_colon'] = FALSE;
-/* Field: File: Usage link */
-$handler->display->display_options['fields']['usage']['id'] = 'usage';
-$handler->display->display_options['fields']['usage']['table'] = 'file_managed';
-$handler->display->display_options['fields']['usage']['field'] = 'usage';
-$handler->display->display_options['fields']['usage']['label'] = '';
-$handler->display->display_options['fields']['usage']['element_label_colon'] = FALSE;
 /* Field: File: Delete link */
 $handler->display->display_options['fields']['delete']['id'] = 'delete';
 $handler->display->display_options['fields']['delete']['table'] = 'file_managed';
 $handler->display->display_options['fields']['delete']['field'] = 'delete';
 $handler->display->display_options['fields']['delete']['label'] = '';
+$handler->display->display_options['fields']['delete']['exclude'] = TRUE;
+$handler->display->display_options['fields']['delete']['alter']['text'] = '<ul class="links inline">
+<li>[edit]</li>
+<li>[delete]</li>
+</ul>';
 $handler->display->display_options['fields']['delete']['element_label_colon'] = FALSE;
+/* Field: Global: Custom text */
+$handler->display->display_options['fields']['nothing']['id'] = 'nothing';
+$handler->display->display_options['fields']['nothing']['table'] = 'views';
+$handler->display->display_options['fields']['nothing']['field'] = 'nothing';
+$handler->display->display_options['fields']['nothing']['label'] = 'Operations';
+$handler->display->display_options['fields']['nothing']['alter']['text'] = '<ul class="links inline">
+<li>[edit]</li>
+<li>[delete]</li>
+</ul>';
+$handler->display->display_options['fields']['nothing']['element_label_colon'] = FALSE;
 /* Filter criterion: File: Name */
 $handler->display->display_options['filters']['filename']['id'] = 'filename';
 $handler->display->display_options['filters']['filename']['table'] = 'file_managed';
@@ -241,9 +267,9 @@ $handler->display->display_options['filters']['filename']['expose']['operator']
 $handler->display->display_options['filters']['filename']['expose']['identifier'] = 'filename';
 $handler->display->display_options['filters']['filename']['expose']['remember'] = TRUE;
 $handler->display->display_options['filters']['filename']['expose']['remember_roles'] = array(
-  2 => '2',
-  1 => 0,
-  3 => 0,
+    2 => '2',
+    1 => 0,
+    3 => 0,
 );
 /* Filter criterion: File: Type */
 $handler->display->display_options['filters']['type']['id'] = 'type';
@@ -257,9 +283,9 @@ $handler->display->display_options['filters']['type']['expose']['operator'] = 't
 $handler->display->display_options['filters']['type']['expose']['identifier'] = 'type';
 $handler->display->display_options['filters']['type']['expose']['remember'] = TRUE;
 $handler->display->display_options['filters']['type']['expose']['remember_roles'] = array(
-  2 => '2',
-  1 => 0,
-  3 => 0,
+    2 => '2',
+    1 => 0,
+    3 => 0,
 );
 /* Filter criterion: User: Name */
 $handler->display->display_options['filters']['uid']['id'] = 'uid';
@@ -275,9 +301,9 @@ $handler->display->display_options['filters']['uid']['expose']['operator'] = 'ui
 $handler->display->display_options['filters']['uid']['expose']['identifier'] = 'uid';
 $handler->display->display_options['filters']['uid']['expose']['remember'] = TRUE;
 $handler->display->display_options['filters']['uid']['expose']['remember_roles'] = array(
-  2 => '2',
-  1 => 0,
-  3 => 0,
+    2 => '2',
+    1 => 0,
+    3 => 0,
 );
 
 /* Display: System */
diff --git a/drupal7/sites/all/modules/file_entity/file_entity.admin.inc b/drupal7/sites/all/modules/file_entity/file_entity.admin.inc
index 43ef4755..0e09e451 100644
--- a/drupal7/sites/all/modules/file_entity/file_entity.admin.inc
+++ b/drupal7/sites/all/modules/file_entity/file_entity.admin.inc
@@ -1065,6 +1065,7 @@ function file_entity_settings_form($form, &$form_state) {
     '#title' => t('Default allowed file extensions'),
     '#default_value' => variable_get('file_entity_default_allowed_extensions', 'jpg jpeg gif png txt doc docx xls xlsx pdf ppt pptx pps ppsx odt ods odp mp3 mov mp4 m4a m4v mpeg avi ogg oga ogv weba webp webm'),
     '#description' => t('Separate extensions with a space or comma and do not include the leading dot.'),
+    '#maxlength' => NULL,
   );
 
   $form['file_entity_alt'] = array(
diff --git a/drupal7/sites/all/modules/file_entity/file_entity.api.php b/drupal7/sites/all/modules/file_entity/file_entity.api.php
index 9827446a..3a736812 100644
--- a/drupal7/sites/all/modules/file_entity/file_entity.api.php
+++ b/drupal7/sites/all/modules/file_entity/file_entity.api.php
@@ -338,6 +338,17 @@ function hook_file_download_headers_alter(array &$headers, $file) {
   $headers['X-Powered-By'] = 'My Module';
 }
 
+/**
+ * React to a file being downloaded.
+ */
+function hook_file_transfer($uri, array $headers) {
+  // Redirect a download for an S3 file to the actual location.
+  if (file_uri_scheme($uri) == 's3') {
+    $url = file_create_url($uri);
+    drupal_goto($url);
+  }
+}
+
 /**
  * Decides which file type (bundle) should be assigned to a file entity.
  *
diff --git a/drupal7/sites/all/modules/file_entity/file_entity.field.inc b/drupal7/sites/all/modules/file_entity/file_entity.field.inc
index 97f3c280..2a3700c1 100644
--- a/drupal7/sites/all/modules/file_entity/file_entity.field.inc
+++ b/drupal7/sites/all/modules/file_entity/file_entity.field.inc
@@ -160,6 +160,11 @@ function file_entity_field_formatter_settings_form($field, $instance, $view_mode
       '#type' => 'checkbox',
       '#default_value' => $settings['loop'],
     );
+    $element['muted'] = array(
+      '#title' => t('Muted'),
+      '#type' => 'checkbox',
+      '#default_value' => $settings['muted'],
+    );
     $element['width'] = array(
       '#type' => 'textfield',
       '#title' => t('Width'),
@@ -220,10 +225,8 @@ function file_entity_field_formatter_settings_summary($field, $instance, $view_m
     if (isset($settings['multiple_file_behavior'])) {
       $summary[] = t('Multiple files: %multiple', array('%multiple' => $settings['multiple_file_behavior']));
     }
-
   }
   elseif ($display['type'] === 'file_video') {
-    $summary_items = array();
     if (isset($settings['controls'])) {
       $summary[] = t('Controls: %controls', array('%controls' => $settings['controls'] ? 'visible' : 'hidden'));
     }
@@ -286,6 +289,9 @@ function file_entity_field_formatter_view($entity_type, $entity, $field, $instan
     foreach ($items as $delta => $item) {
       if (!isset($recursion_queue[$item['fid']])) {
         $files_display[$item['fid']] = file_load($item['fid']);
+        if (!empty($item['description'])) {
+          $files_display[$item['fid']]->description = $item['description'];
+        }
       }
     }
 
@@ -293,6 +299,7 @@ function file_entity_field_formatter_view($entity_type, $entity, $field, $instan
     if ($files_display) {
       foreach ($files_display as $fid => $file) {
         $files_display[$fid]->referencing_entity = $entity;
+        $files_display[$fid]->referencing_entity_type = $entity_type;
         $files_display[$fid]->referencing_field = $field['field_name'];
       }
       $output = file_view_multiple($files_display, $view_mode);
@@ -330,14 +337,14 @@ function file_entity_field_formatter_view($entity_type, $entity, $field, $instan
     if ($multiple_file_behavior == 'tags') {
       foreach ($items as $delta => $item) {
         if ($item['type'] == 'audio') {
-          $source_lists[] = array($item);
+          $source_lists[$delta] = array($item);
         }
       }
     }
     else {
       foreach ($items as $delta => $item) {
         if ($item['type'] == 'audio') {
-          $source_lists[0][] = $item;
+          $source_lists[0][$delta] = $item;
         }
       }
     }
@@ -364,22 +371,20 @@ function file_entity_field_formatter_view($entity_type, $entity, $field, $instan
     if ($multiple_file_behavior == 'tags') {
       foreach ($items as $delta => $item) {
         if ($item['type'] == 'video') {
-          $source_lists[] = array($item);
+          $source_lists[$delta] = array($item);
         }
       }
     }
     else {
       foreach ($items as $delta => $item) {
         if ($item['type'] == 'video') {
-          $source_lists[0][] = $item;
+          $source_lists[0][$delta] = $item;
         }
       }
     }
 
     // Render each source list as an <video> element.
     foreach ($source_lists as $delta => $sources) {
-      $width = $settings['width'];
-      $height = $settings['height'];
       $element[$delta] = array(
         '#theme' => 'file_entity_file_video',
         '#files' => $sources,
@@ -387,8 +392,8 @@ function file_entity_field_formatter_view($entity_type, $entity, $field, $instan
         '#autoplay' => $settings['autoplay'],
         '#loop' => $settings['loop'],
         '#muted' => $settings['muted'],
-        '#width' => ($width && $height) ? $width : NULL,
-        '#height' => ($width && $height) ? $height : NULL,
+        '#width' => $settings['width'],
+        '#height' => $settings['height'],
       );
     }
   }
diff --git a/drupal7/sites/all/modules/file_entity/file_entity.file.inc b/drupal7/sites/all/modules/file_entity/file_entity.file.inc
index d5cfadc8..74feaa6f 100644
--- a/drupal7/sites/all/modules/file_entity/file_entity.file.inc
+++ b/drupal7/sites/all/modules/file_entity/file_entity.file.inc
@@ -59,17 +59,15 @@ function file_entity_file_insert($file) {
 
   // Save file metadata.
   if (!empty($file->metadata)) {
+    $query = db_insert('file_metadata')->fields(array('fid', 'name', 'value'));
     foreach ($file->metadata as $name => $value) {
-      db_merge('file_metadata')
-        ->fields(array(
-          'value' => serialize($value),
-        ))
-        ->key(array(
-          'fid' => $file->fid,
-          'name' => $name,
-        ))
-        ->execute();
+      $query->values(array(
+        'fid' => $file->fid,
+        'name' => $name,
+        'value' => serialize($value),
+      ));
     }
+    $query->execute();
   }
 
   // Clear any related field caches.
@@ -84,40 +82,26 @@ function file_entity_file_update($file) {
   field_attach_update('file', $file);
 
   // Save file metadata.
+  db_delete('file_metadata')->condition('fid', $file->fid)->execute();
   if (!empty($file->metadata)) {
+    $query = db_insert('file_metadata')->fields(array('fid', 'name', 'value'));
     foreach ($file->metadata as $name => $value) {
-      db_merge('file_metadata')
-        ->fields(array(
-          'value' => serialize($value),
-        ))
-        ->key(array(
-          'fid' => $file->fid,
-          'name' => $name,
-        ))
-        ->execute();
-    }
-  }
-
-  // Save file metadata.
-  db_delete('file_metadata')->condition('fid', $file->fid);
-  if (!empty($file->metadata)) {
-    foreach ($file->metadata as $name => $value) {
-      db_merge('file_metadata')
-        ->fields(array(
-          'value' => serialize($value),
-        ))
-        ->key(array(
-          'fid' => $file->fid,
-          'name' => $name,
-        ))
-        ->execute();
+      $query->values(array(
+        'fid' => $file->fid,
+        'name' => $name,
+        'value' => serialize($value),
+      ));
     }
+    $query->execute();
   }
 
-  if (file_entity_file_get_mimetype_type($file) == 'image' && module_exists('image')) {
-    // If the image dimensions have changed, update any image field references
-    // to this file and flush image style derivatives.
-    if ($file->metadata['width'] != $file->metadata['width'] || $file->metadata['height'] != $file->metadata['height']) {
+  if (module_exists('image') && file_entity_file_get_mimetype_type($file) == 'image' && $file->filesize) {
+    // If the file has changed dimensions or a new file has been uploaded,
+    // update any image field reference to this file and flush image style
+    // derivatives.
+    $file->metadata += array('width' => NULL, 'height' => NULL);
+    $file->original->metadata += array('width' => NULL, 'height' => NULL);
+    if ($file->filesize != $file->original->filesize || $file->metadata['width'] != $file->original->metadata['width'] || $file->metadata['height'] != $file->original->metadata['height']) {
       _file_entity_update_image_field_dimensions($file);
     }
 
@@ -246,6 +230,12 @@ function file_entity_metadata_fetch_image_dimensions($file) {
  * @see http://drupal.org/node/1448124
  */
 function _file_entity_update_image_field_dimensions($file) {
+  // Prevent PHP notices when trying to read empty files.
+  // @see http://drupal.org/node/681042
+  if (!$file->filesize) {
+    return;
+  }
+
   // Do not bother proceeding if this file does not have an image mime type.
   if (file_entity_file_get_mimetype_type($file) != 'image') {
     return;
diff --git a/drupal7/sites/all/modules/file_entity/file_entity.file_api.inc b/drupal7/sites/all/modules/file_entity/file_entity.file_api.inc
index 9baa1a45..cfb75f9b 100644
--- a/drupal7/sites/all/modules/file_entity/file_entity.file_api.inc
+++ b/drupal7/sites/all/modules/file_entity/file_entity.file_api.inc
@@ -484,6 +484,31 @@ function file_type_is_disabled($type) {
   return !empty($type->disabled);
 }
 
+/**
+ * Returns an array of valid file extensions.
+ */
+function file_type_get_valid_extensions($type) {
+  include_once DRUPAL_ROOT . '/includes/file.mimetypes.inc';
+  $mapping = file_mimetype_mapping();
+
+  $type_extensions = array();
+  $type_ext_keys = array();
+  if (!empty($type->mimetypes)) {
+    foreach ($mapping['mimetypes'] as $ext_key => $mimetype) {
+      if (file_entity_match_mimetypes($mimetype, $type->mimetypes)) {
+        $type_ext_keys[] = $ext_key;
+      }
+    }
+
+    if ($type_ext_keys) {
+      $type_extensions = array_intersect($mapping['extensions'], $type_ext_keys);
+      $type_extensions = array_keys($type_extensions);
+    }
+  }
+
+  return $type_extensions;
+}
+
 /**
  * Updates an existing file type or creates a new one.
  *
@@ -596,6 +621,7 @@ function file_type_delete($type) {
  *   Type of the file_type to disable
  */
 function file_type_enable($type) {
+  ctools_include('export');
   ctools_export_crud_enable('file_type', $type);
 }
 
@@ -607,6 +633,7 @@ function file_type_enable($type) {
  *   Type of the file_type to disable
  */
 function file_type_disable($type) {
+  ctools_include('export');
   ctools_export_crud_disable('file_type', $type);
 }
 
@@ -699,7 +726,7 @@ function file_uri_to_object($uri, $use_existing = TRUE) {
   if (empty($file)) {
     $file = new stdClass();
     $file->uid = $GLOBALS['user']->uid;
-    $file->filename = basename($uri);
+    $file->filename = drupal_basename($uri);
     $file->uri = $uri;
     $file->filemime = file_get_mimetype($uri);
     // This is gagged because some uris will not support it.
diff --git a/drupal7/sites/all/modules/file_entity/file_entity.file_default_displays.inc b/drupal7/sites/all/modules/file_entity/file_entity.file_default_displays.inc
index c96f6a1a..74ca6609 100644
--- a/drupal7/sites/all/modules/file_entity/file_entity.file_default_displays.inc
+++ b/drupal7/sites/all/modules/file_entity/file_entity.file_default_displays.inc
@@ -93,6 +93,45 @@ function file_entity_file_default_displays() {
   $file_display->settings = '';
   $file_displays['image__teaser__file_field_file_default'] = $file_display;
 
+  // Enhance the default image displays if the Image module is enabled.
+  if (module_exists('image')) {
+    // Images should be displayed as unstyled images by default.
+    $file_display = new stdClass();
+    $file_display->api_version = 1;
+    $file_display->name = 'image__default__file_field_image';
+    $file_display->weight = 49;
+    $file_display->status = TRUE;
+    $file_display->settings = array(
+      'image_style' => '',
+      'image_link' => '',
+    );
+    $file_displays['image__default__file_field_image'] = $file_display;
+
+    // Image previews should be displayed as image thumbnails by default.
+    $file_display = new stdClass();
+    $file_display->api_version = 1;
+    $file_display->name = 'image__preview__file_field_image';
+    $file_display->weight = 49;
+    $file_display->status = TRUE;
+    $file_display->settings = array(
+      'image_style' => 'thumbnail',
+      'image_link' => '',
+    );
+    $file_displays['image__preview__file_field_image'] = $file_display;
+
+    // Image teasers should be displayed as medium images by default.
+    $file_display = new stdClass();
+    $file_display->api_version = 1;
+    $file_display->name = 'image__teaser__file_field_image';
+    $file_display->weight = 49;
+    $file_display->status = TRUE;
+    $file_display->settings = array(
+      'image_style' => 'medium',
+      'image_link' => 'content',
+    );
+    $file_displays['image__teaser__file_field_image'] = $file_display;
+  }
+
   $file_display = new stdClass();
   $file_display->api_version = 1;
   $file_display->name = 'video__default__file_field_file_video';
diff --git a/drupal7/sites/all/modules/file_entity/file_entity.info b/drupal7/sites/all/modules/file_entity/file_entity.info
index 623ae375..a34997e6 100644
--- a/drupal7/sites/all/modules/file_entity/file_entity.info
+++ b/drupal7/sites/all/modules/file_entity/file_entity.info
@@ -10,6 +10,7 @@ files[] = views/views_handler_argument_file_type.inc
 files[] = views/views_handler_field_file_rendered.inc
 files[] = views/views_handler_field_file_type.inc
 files[] = views/views_handler_filter_file_type.inc
+files[] = views/views_handler_filter_schema_type.inc
 files[] = views/views_handler_field_file_filename.inc
 files[] = views/views_handler_field_file_link.inc
 files[] = views/views_handler_field_file_link_edit.inc
@@ -24,9 +25,9 @@ configure = admin/config/media/file-settings
 ; We have to add a fake version so Git checkouts do not fail Media dependencies
 version = 7.x-2.x-dev
 
-; Information added by drupal.org packaging script on 2013-10-25
-version = "7.x-2.0-alpha3"
+; Information added by Drupal.org packaging script on 2014-10-04
+version = "7.x-2.0-beta1"
 core = "7.x"
 project = "file_entity"
-datestamp = "1382744726"
+datestamp = "1412420930"
 
diff --git a/drupal7/sites/all/modules/file_entity/file_entity.install b/drupal7/sites/all/modules/file_entity/file_entity.install
index ca4ab066..bbf4b246 100644
--- a/drupal7/sites/all/modules/file_entity/file_entity.install
+++ b/drupal7/sites/all/modules/file_entity/file_entity.install
@@ -375,6 +375,8 @@ function file_entity_update_7104() {
             'permission' => 'view file',
             'module' => 'file_entity',
           ))
+          ->condition('rid', $rid)
+          ->condition('permission', 'view file')
           ->execute();
       }
     }
@@ -900,16 +902,13 @@ function file_entity_update_7210() {
 
   // Migrate any existing MIME type information into {file_type}.
   if (db_table_exists('file_type_mimetypes')) {
-    foreach (file_type_load_all(TRUE) as $type) {
-      $mimetypes = array();
-      $result = db_select('file_type_mimetypes', 'ftm')
+    module_load_include('inc', 'file_entity', 'file_entity.file_api');
+    $types = file_type_load_all(TRUE);
+    foreach ($types as $type) {
+      $mimetypes = db_select('file_type_mimetypes', 'ftm')
         ->fields('ftm', array('mimetype'))
-        ->condition('type', $type->type, '=')
-        ->execute();
-
-      foreach ($result as $record) {
-        $mimetypes[] = $record->mimetype;
-      }
+        ->condition('type', $type->type)
+        ->execute()->fetchCol();
 
       if (!empty($mimetypes)) {
         $type->mimetypes = $mimetypes;
diff --git a/drupal7/sites/all/modules/file_entity/file_entity.module b/drupal7/sites/all/modules/file_entity/file_entity.module
index 3ca0bb7d..5d058e4c 100644
--- a/drupal7/sites/all/modules/file_entity/file_entity.module
+++ b/drupal7/sites/all/modules/file_entity/file_entity.module
@@ -38,8 +38,7 @@ require_once dirname(__FILE__) . '/file_entity.field.inc';
  */
 function file_entity_hook_info() {
   $hooks = array(
-    'file_operation_info',
-    'file_operation_info_alter',
+    'file_operations',
     'file_type_info',
     'file_type_info_alter',
     'file_formatter_info',
@@ -84,6 +83,17 @@ function file_entity_hook_info_alter(&$info) {
   $info += array_fill_keys($hooks, array('group' => 'file'));
 }
 
+/**
+ * Implements hook_module_implements_alter().
+ */
+function file_entity_module_implements_alter(&$implementations, $hook) {
+  // nginx_accel_redirect_file_transfer() is an accidental hook implementation.
+  // @see https://www.drupal.org/node/2278625
+  if ($hook == 'file_transfer') {
+    unset($implementations['nginx_accel_redirect']);
+  }
+}
+
 /**
  * Implements hook_help().
  */
@@ -189,6 +199,20 @@ function file_entity_menu() {
     'type' => MENU_DEFAULT_LOCAL_TASK,
     'weight' => -10,
   );
+  $items['file/add/upload/file'] = array(
+    'title' => 'File',
+    'type' => MENU_DEFAULT_LOCAL_TASK,
+    'weight' => -10,
+  );
+  $items['file/add/upload/archive'] = array(
+    'title' => 'Archive',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('file_entity_upload_archive_form'),
+    'access arguments' => array('administer files'),
+    'file' => 'file_entity.pages.inc',
+    'type' => MENU_LOCAL_TASK,
+    'weight' => -5,
+  );
   $items['file/%file'] = array(
     'title callback' => 'entity_label',
     'title arguments' => array('file', 1),
@@ -1113,9 +1137,16 @@ function file_entity_file_formatter_file_field_view($file, $display, $langcode)
       // Set $display['type'] to what hook_field_formatter_*() expects.
       $display['type'] = $field_formatter_type;
 
+      // Allow any attribute overrides (e.g. from the Media module) to be
+      // respected.
+      $item = (array) $file;
+      if (!empty($file->override['attributes'])) {
+        $item = array_merge($item, $file->override['attributes']);
+      }
+
       // Set $items to what file field formatters expect. See file_field_load(),
       // and note that, here, $file is already a fully loaded entity.
-      $items = array((array) $file);
+      $items = array($item);
 
       // Invoke hook_field_formatter_prepare_view() and
       // hook_field_formatter_view(). Note that we are reusing field formatter
@@ -1878,6 +1909,13 @@ function _file_entity_query_file_entity_access_alter($query, $type) {
           $file_conditions->exists($subquery);
         }
         // Otherwise attach it to the node query itself.
+        elseif ($table == 'file_managed') {
+          // Fix for https://drupal.org/node/2073085
+          $db_or = db_or();
+          $db_or->exists($subquery);
+          $db_or->isNull($falias . '.' . $field);
+          $query->condition($db_or);
+        }
         else {
           $query->exists($subquery);
         }
@@ -1917,7 +1955,7 @@ function file_entity_file_download($uri) {
     return file_get_content_headers($file);
   }
 
-  return NULL;
+  return -1;
 }
 
 /**
@@ -2151,59 +2189,6 @@ function file_entity_upload_validators_pre_render($element) {
   return $element;
 }
 
-/**
- * Implements hook_file_default_displays_alter() on behalf of image.module.
- */
-function image_file_default_displays_alter(&$file_displays) {
-  // Images should be displayed as unstyled images by default.
-  if (isset($file_displays['image__default__file_field_file_default'])) {
-    $file_displays['image__default__file_field_file_default']->status = FALSE;
-  }
-
-  $file_display = new stdClass();
-  $file_display->api_version = 1;
-  $file_display->name = 'image__default__file_field_image';
-  $file_display->weight = 50;
-  $file_display->status = TRUE;
-  $file_display->settings = array(
-    'image_style' => '',
-    'image_link' => '',
-  );
-  $file_displays['image__default__file_field_image'] = $file_display;
-
-  // Image previews should be displayed as image thumbnails by default.
-  if (isset($file_displays['image__preview__file_field_file_default'])) {
-    $file_displays['image__preview__file_field_file_default']->status = FALSE;
-  }
-
-  $file_display = new stdClass();
-  $file_display->api_version = 1;
-  $file_display->name = 'image__preview__file_field_image';
-  $file_display->weight = 50;
-  $file_display->status = TRUE;
-  $file_display->settings = array(
-    'image_style' => 'thumbnail',
-    'image_link' => '',
-  );
-  $file_displays['image__preview__file_field_image'] = $file_display;
-
-  // Image teasers should be displayed as medium images by default.
-  if (isset($file_displays['image__teaser__file_field_file_default'])) {
-    $file_displays['image__teaser__file_field_file_default']->status = FALSE;
-  }
-
-  $file_display = new stdClass();
-  $file_display->api_version = 1;
-  $file_display->name = 'image__teaser__file_field_image';
-  $file_display->weight = 50;
-  $file_display->status = TRUE;
-  $file_display->settings = array(
-    'image_style' => 'medium',
-    'image_link' => 'content',
-  );
-  $file_displays['image__teaser__file_field_image'] = $file_display;
-}
-
 /**
  * @name pathauto_file Pathauto integration for the core file module.
  * @{
@@ -2265,7 +2250,7 @@ function pathauto_file_operations() {
  */
 function pathauto_file_update_alias(stdClass $file, $op, array $options = array()) {
   // Skip processing if the user has disabled pathauto for the file.
-  if (isset($file->path['pathauto']) && empty($file->path['pathauto'])) {
+  if (isset($file->path['pathauto']) && empty($file->path['pathauto']) && empty($options['force'])) {
     return;
   }
 
@@ -2482,21 +2467,25 @@ function file_entity_admin_menu_map() {
 }
 
 /*
- * Generate a file download CSRF token.
+ * Generates a token to protect a file download URL.
+ *
+ * This prevents unauthorized crawling of all file download URLs since the
+ * {file_managed}.fid column is an auto-incrementing serial field and is easy
+ * to guess or attempt many at once. This can be costly both in CPU time
+ * and bandwidth.
  *
- * This is essentially a duplicate of drupal_get_token, that attempts to still
- * work if the user is anonymous, by using ip_address() as the identifier
- * rather than session_id().
+ * @see image_style_path_token()
  *
  * @param object $file
  *   A file entity object.
  *
  * @return string
- *   A CSRF token string.
+ *   An eight-character token which can be used to protect file downloads
+ *   against denial-of-service attacks.
  */
 function file_entity_get_download_token($file) {
-  $identifier = !empty($GLOBALS['user']->uid) ? session_id() : ip_address();
-  return drupal_hmac_base64("file/$file->fid/download", $identifier . drupal_get_private_key() . drupal_get_hash_salt());
+  // Return the first eight characters.
+  return substr(drupal_hmac_base64("file/$file->fid/download:" . $file->uri, drupal_get_private_key() . drupal_get_hash_salt()), 0, 8);
 }
 
 /**
@@ -2542,7 +2531,7 @@ function file_entity_field_attach_load($entity_type, $entities, $age, $options)
           foreach ($items as $delta => $item) {
             // If alt and title text is not specified, fall back to alt and
             // title text on the file.
-            if (empty($item['alt']) || empty($item['title'])) {
+            if (!empty($item['fid']) && (empty($item['alt']) || empty($item['title']))) {
               $file = file_load($item['fid']);
               foreach (array('alt', 'title') as $key) {
                 if (empty($item[$key]) && !empty($file->{$key})) {
diff --git a/drupal7/sites/all/modules/file_entity/file_entity.pages.inc b/drupal7/sites/all/modules/file_entity/file_entity.pages.inc
index 31d0d763..a00245a9 100644
--- a/drupal7/sites/all/modules/file_entity/file_entity.pages.inc
+++ b/drupal7/sites/all/modules/file_entity/file_entity.pages.inc
@@ -37,20 +37,34 @@ function file_entity_download_page($file) {
   }
 
   $headers = array(
-    'Content-Type' => 'force-download',
-    'Content-Disposition' => 'attachment; filename="' . $file->filename . '"',
+    'Content-Type' => mime_header_encode($file->filemime),
+    'Content-Disposition' => 'attachment; filename="' . mime_header_encode(drupal_basename($file->uri)) . '"',
     'Content-Length' => $file->filesize,
     'Content-Transfer-Encoding' => 'binary',
     'Pragma' => 'no-cache',
     'Cache-Control' => 'must-revalidate, post-check=0, pre-check=0',
     'Expires' => '0',
-    'Accept-Ranges' => 'bytes',
   );
 
   // Let other modules alter the download headers.
   drupal_alter('file_download_headers', $headers, $file);
 
-  file_transfer($file->uri, $headers);
+  // Let other modules know the file is being downloaded.
+  module_invoke_all('file_transfer', $file->uri, $headers);
+
+  if (file_entity_file_is_local($file)) {
+    // For local files, transfer the file and do not reveal the actual URL.
+    file_transfer($file->uri, $headers);
+  }
+  else {
+    // For remote files, just redirect the user to that file's actual URL.
+    $headers['Location'] = file_create_url($file->uri);
+    foreach ($headers as $name => $value) {
+      drupal_add_http_header($name, $value);
+    }
+    drupal_send_headers();
+    drupal_exit();
+  }
 }
 
 /**
@@ -66,6 +80,7 @@ function file_entity_download_page($file) {
 function file_entity_add_upload($form, &$form_state, array $options = array()) {
   $step = (isset($form_state['step']) && in_array($form_state['step'], array(1, 2, 3, 4))) ? $form_state['step'] : 1;
   $form['#step'] = $step;
+  $form['#options'] = $options;
   switch ($step) {
     case 1:
       return file_entity_add_upload_step_upload($form, $form_state, $options);
@@ -143,16 +158,32 @@ function file_entity_add_upload_step_filetype($form, &$form_state, array $option
 function file_entity_add_upload_step_scheme($form, &$form_state, array $options = array()) {
   $file = file_load($form_state['storage']['upload']);
 
-  $options = array();
+  $schemes = array();
   foreach (file_get_stream_wrappers(STREAM_WRAPPERS_WRITE_VISIBLE) as $scheme => $info) {
-    $options[$scheme] = check_plain($info['description']);
+    $schemes[$scheme] = check_plain($info['description']);
+  }
+
+  // Remove any schemes not found in the instance settings.
+  if (!empty($options['schemes'])) {
+    $schemes = array_intersect_key($schemes, $options['schemes']);
+  }
+
+  // Determine which scheme to use as the default value.
+  if (isset($form_state['storage']['scheme'])) {
+    $fallback_scheme = $form_state['storage']['scheme'];
+  }
+  elseif (!empty($options['uri_scheme'])) {
+    $fallback_scheme = $options['uri_scheme'];
+  }
+  else {
+    $fallback_scheme = file_default_scheme();
   }
 
   $form['scheme'] = array(
     '#type' => 'radios',
     '#title' => t('Destination'),
-    '#options' => $options,
-    '#default_value' => isset($form_state['storage']['scheme']) ? $form_state['storage']['scheme'] : file_default_scheme(),
+    '#options' => $schemes,
+    '#default_value' => $fallback_scheme,
     '#required' => TRUE,
   );
 
@@ -179,6 +210,16 @@ function file_entity_add_upload_step_fields($form, &$form_state, array $options
   $file = file_load($form_state['storage']['upload']);
   $file->type = $form_state['storage']['type'];
 
+  // Let users modify the filename here.
+  $form['filename'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Name'),
+    '#default_value' => $file->filename,
+    '#required' => TRUE,
+    '#maxlength' => 255,
+    '#weight' => -10,
+  );
+
   // Add fields.
   field_attach_form('file', $file, $form, $form_state);
 
@@ -207,7 +248,7 @@ function file_entity_usage_page($file) {
   foreach (file_usage_list($file) as $module => $usage) {
     $info = system_get_info('module', $module);
 
-    // There are cases, where actual entitiy doesen't exist.
+    // There are cases where the actual entity doesn't exist.
     // We have to handle this.
     foreach ($usage as $entity_type => $entity_ids) {
       $entity_info = entity_get_info($entity_type);
@@ -315,7 +356,7 @@ function file_entity_add_upload_submit($form, &$form_state) {
           $form['#step'] += ($trigger == 'edit-previous') ? -1 : 1;
           $form_state['storage']['type'] = reset($candidates_keys);
         }
-        elseif (variable_get('file_entity_file_upload_wizard_skip_file_type', FALSE)) {
+        elseif (!$candidates || variable_get('file_entity_file_upload_wizard_skip_file_type', FALSE)) {
           // Do not assign the file a file type.
           $form['#step'] += ($trigger == 'edit-previous') ? -1 : 1;
           $form_state['storage']['type'] = FILE_TYPE_NONE;
@@ -323,17 +364,36 @@ function file_entity_add_upload_submit($form, &$form_state) {
       }
       else {
         // Check if we can skip step 3.
+        $options = $form['#options'];
         $schemes = file_get_stream_wrappers(STREAM_WRAPPERS_WRITE_VISIBLE);
-        if (count($schemes) == 1) {
+
+        // Remove any schemes not found in the instance settings.
+        if (!empty($options['schemes'])) {
+          $schemes = array_intersect_key($schemes, $options['schemes']);
+        }
+
+        if (!file_entity_file_is_writeable($file)) {
+          // The file is read-only (remote) and must use its provided scheme.
+          $form['#step'] += ($trigger == 'edit-previous') ? -1 : 1;
+          $form_state['storage']['scheme'] = file_uri_scheme($file->uri);
+        }
+        elseif (count($schemes) == 1) {
           // There is only one possible stream wrapper for this file.
           // Skip the third page.
           $form['#step'] += ($trigger == 'edit-previous') ? -1 : 1;
           $form_state['storage']['scheme'] = key($schemes);
         }
         elseif (variable_get('file_entity_file_upload_wizard_skip_scheme', FALSE)) {
-          // Assign the file the default scheme.
           $form['#step'] += ($trigger == 'edit-previous') ? -1 : 1;
-          $form_state['storage']['scheme'] = file_default_scheme();
+
+          // Fallback to the URI scheme specified in the field settings
+          // otherwise use the default file scheme.
+          if (!empty($options['uri_scheme'])) {
+            $form_state['storage']['scheme'] = $options['uri_scheme'];
+          }
+          else {
+            $form_state['storage']['scheme'] = file_default_scheme();
+          }
         }
       }
     }
@@ -480,6 +540,9 @@ function file_entity_add_upload_multiple_submit($form, &$form_state) {
     $form['upload']['#upload_location'] . '/' :
     variable_get('file_default_scheme', 'public') . '://';
 
+  // Ensure writable destination directory for the files.
+  file_prepare_directory($upload_location, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
+
   // We can't use file_save_upload() because of
   // http://www.jacobsingh.name/content/tight-coupling-no-not.
   foreach ($form_state['values']['upload'] as $uploaded_file) {
@@ -568,8 +631,23 @@ function file_entity_edit($form, &$form_state, $file) {
   if (file_entity_file_is_writeable($file)) {
     // Set up replacement file validation.
     $replacement_options = array();
-    // The replacement file must have the same extension as the original file.
-    $replacement_options['file_extensions'] = pathinfo($file->uri, PATHINFO_EXTENSION);
+
+    // The replacement file must have an extension valid for the original type.
+    $file_extensions = array();
+    $file_type_name = isset($file->type) ? $file->type : file_get_type($file);
+    if ($file_type_name && ($file_type = file_type_load($file_type_name))) {
+      $file_extensions = file_type_get_valid_extensions($file_type);
+    }
+
+    // Set allowed file extensions.
+    if (!empty($file_extensions)) {
+      // Set to type based file extensions.
+      $replacement_options['file_extensions'] = implode(' ', $file_extensions);
+    }
+    else {
+      // Fallback to the extension of the current file.
+      $replacement_options['file_extensions'] = pathinfo($file->uri, PATHINFO_EXTENSION);
+    }
 
     $form['replace_upload'] = array(
       '#type' => 'file',
@@ -656,6 +734,7 @@ function file_entity_edit($form, &$form_state, $file) {
     '#value' => t('Save'),
     '#weight' => 5,
     '#submit' => array('file_entity_edit_submit'),
+    '#validate' => array('file_entity_edit_validate'),
   );
   $form['actions']['delete'] = array(
     '#type' => 'submit',
@@ -722,12 +801,29 @@ function file_entity_edit_validate($form, &$form_state) {
  */
 function file_entity_edit_submit($form, &$form_state) {
   $file = $form_state['file'];
+  $orphaned_uri = '';
 
   // Check if a replacement file has been uploaded.
   if (!empty($form_state['values']['replace_upload'])) {
     $replacement = $form_state['values']['replace_upload'];
     // Move file from temp to permanent home.
-    file_unmanaged_copy($replacement->uri, $file->uri, FILE_EXISTS_REPLACE);
+    $destination_uri = file_uri_scheme($file->uri) . '://' . file_uri_target($replacement->uri);
+    $replace_mode = $destination_uri == $file->uri ? FILE_EXISTS_REPLACE : FILE_EXISTS_RENAME;
+    if ($new_file_uri = file_unmanaged_copy($replacement->uri, $destination_uri, $replace_mode)) {
+      // @todo Add watchdog() about replaced file here?
+
+      // Remove temporary file.
+      file_delete($replacement);
+
+      // Update if the uri target has changed.
+      if ($new_file_uri != $file->uri) {
+       // Store the original file uri to delete if save is sucessful.
+       $orphaned_uri = $file->uri;
+
+        // Update file entity uri.
+        $file->uri = $new_file_uri;
+      }
+    }
   }
 
   // Run entity form submit handling and save the file.
@@ -767,6 +863,15 @@ function file_entity_edit_submit($form, &$form_state) {
   watchdog('file', '@type: updated %title.', $args);
   drupal_set_message(t('@type %title has been updated.', $args));
 
+  // Clean up orphaned file.
+  if (!empty($orphaned_uri)) {
+    file_unmanaged_delete($orphaned_uri);
+
+    $args['@orphaned'] = file_uri_target($orphaned_uri);
+    watchdog('file', '@type: deleted orphaned file @orphaned for %title.', $args);
+    drupal_set_message(t('The replaced @type @orphaned has been deleted.', $args));
+  }
+
   $form_state['redirect'] = 'file/' . $file->fid;
 
   // Clear the page and block caches.
@@ -984,3 +1089,84 @@ function file_entity_get_upload_validators(array $options = array()) {
 
   return $validators;
 }
+
+function file_entity_upload_archive_form($form, &$form_state) {
+  $options = array(
+    'file_extensions' => archiver_get_extensions(),
+  );
+
+  $form['upload'] = array(
+    '#type' => 'managed_file',
+    '#title' => t('Upload an archive file'),
+    '#upload_location' => NULL, // Upload to the temporary directory.
+    '#upload_validators' => file_entity_get_upload_validators($options),
+    '#progress_indicator' => 'bar',
+    '#required' => TRUE,
+    '#pre_render' => array('file_managed_file_pre_render', 'file_entity_upload_validators_pre_render'),
+  );
+
+  $form['pattern'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Pattern'),
+    '#description' => t('Only files matching this pattern will be imported. For example, to import all jpg and gif files, the pattern would be <em>*.jpg|*.gif</em>. Use <em>.*</em> to extract all files in the archive.'),
+    '#default_value' => '.*',
+    '#required' => TRUE,
+  );
+
+  $form['actions'] = array('#type' => 'actions');
+  $form['actions']['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Submit'),
+  );
+
+  form_load_include($form_state, 'inc', 'file_entity', 'file_entity.pages');
+
+  return $form;
+}
+
+/**
+ * Upload a file.
+ */
+function file_entity_upload_archive_form_submit($form, &$form_state) {
+  $form_state['files'] = array();
+
+  if ($archive = file_load($form_state['values']['upload'])) {
+    if ($archiver = archiver_get_archiver($archive->uri)) {
+      $files = $archiver->listContents();
+
+      $extract_dir = file_default_scheme() . '://' . pathinfo($archive->filename, PATHINFO_FILENAME);
+      $extract_dir = file_destination($extract_dir, FILE_EXISTS_RENAME);
+      if (!file_prepare_directory($extract_dir, FILE_MODIFY_PERMISSIONS | FILE_CREATE_DIRECTORY)) {
+        throw new Exception(t('Unable to prepar, e directory %dir for extraction.', array('%dir' => $extract_dir)));
+      }
+
+      $archiver->extract($extract_dir);
+      $pattern = '/' . $form_state['values']['pattern'] . '/';
+      if ($files = file_scan_directory($extract_dir, $pattern)) {
+        foreach ($files as $file) {
+          $file->status = FILE_STATUS_PERMANENT;
+          $file->uid = $archive->uid;
+          file_save($file);
+          $form_state['files'][$file->fid] = $file;
+        }
+      }
+      drupal_set_message(t('Extracted %file and added @count new files.', array('%file' => $archive->filename, '@count' => count($files))));
+    }
+    else {
+      throw new Exception(t('Cannot extract %file, not a valid archive.', array('%file' => $archive->uri)));
+    }
+  }
+
+  // Redirect to the file edit page.
+  if (file_entity_access('edit') && module_exists('multiform')) {
+    $destination = array('destination' => 'admin/content/file');
+    if (isset($_GET['destination'])) {
+      $destination = drupal_get_destination();
+      unset($_GET['destination']);
+    }
+    $form_state['redirect'] = array('admin/content/file/edit-multiple/' . implode(' ', array_keys($form_state['files'])), array('query' => $destination));
+  }
+  else {
+    $form_state['redirect'] = 'admin/content/file';
+  }
+}
diff --git a/drupal7/sites/all/modules/file_entity/file_entity.test b/drupal7/sites/all/modules/file_entity/file_entity.test
index acc10926..4cc4b9a7 100644
--- a/drupal7/sites/all/modules/file_entity/file_entity.test
+++ b/drupal7/sites/all/modules/file_entity/file_entity.test
@@ -17,10 +17,19 @@ class FileEntityTestHelper extends DrupalWebTestCase {
     parent::setUp($modules);
   }
 
-  protected function setUpFiles() {
+  protected function setUpFiles($defaults = array()) {
+    // Populate defaults array.
+    $defaults += array(
+      'uid' => 1,
+      'status' => FILE_STATUS_PERMANENT,
+    );
+
     $types = array('text', 'image');
     foreach ($types as $type) {
       foreach ($this->drupalGetTestFiles($type) as $file) {
+        foreach ($defaults as $key => $value) {
+          $file->$key = $value;
+        }
         $this->files[$type][] = file_save($file);
       }
     }
@@ -261,7 +270,7 @@ class FileEntityUnitTestCase extends FileEntityTestHelper {
 
   function setUp() {
     parent::setUp();
-    parent::setUpFiles();
+    $this->setUpFiles();
   }
 
   /**
@@ -665,7 +674,7 @@ class FileEntityReplaceTestCase extends FileEntityTestHelper {
 
   function setUp() {
     parent::setUp();
-    parent::setUpFiles();
+    $this->setUpFiles();
   }
 
   /**
@@ -705,7 +714,8 @@ class FileEntityReplaceTestCase extends FileEntityTestHelper {
     $this->assertEqual($file->filename, $original->filename, 'Updated file name did not change.');
     $this->assertNotEqual($file->filesize, $original->filesize, 'Updated file size changed from previous file.');
     $this->assertEqual($file->filesize, $replacement->filesize, 'Updated file size matches uploaded file.');
-    $this->assertEqual(file_get_contents($replacement->uri), file_get_contents($file->uri), 'Updated file contents matches uploaded file.');
+    $this->assertEqual(file_get_contents($file->uri), file_get_contents($replacement->uri), 'Updated file contents matches uploaded file.');
+    $this->assertFalse(entity_load('file', FALSE, array('status' => 0)), 'Temporary file used for replacement was deleted.');
 
     // Get an image file.
     $image = reset($this->files['image']);
@@ -746,7 +756,7 @@ class FileEntityTokenTestCase extends FileEntityTestHelper {
 
   function setUp() {
     parent::setUp();
-    parent::setUpFiles();
+    $this->setUpFiles();
   }
 
   function testFileEntityTokens() {
@@ -800,7 +810,7 @@ class FileEntityTypeTestCase extends FileEntityTestHelper {
 
   function setUp() {
     parent::setUp();
-    parent::setUpFiles();
+    $this->setUpFiles();
   }
 
   /**
@@ -1069,13 +1079,22 @@ class FileEntityAccessTestCase extends FileEntityTestHelper {
 
   function setUp() {
     parent::setUp();
-    parent::setUpFiles();
+    $this->setUpFiles(array('uid' => 0));
+
+    // Unset the fact that file_entity_install() adds the 'view files'
+    // permission to all user roles. This messes with being able to fully unit
+    // test the file_entity_access() function.
+    $roles = user_roles();
+    foreach ($roles as $rid => $role) {
+      user_role_revoke_permissions($rid, array('view files'));
+    }
   }
 
   /**
    * Asserts file_entity_access correctly grants or denies access.
    */
   function assertFileEntityAccess($ops, $file, $account) {
+    drupal_static_reset('file_entity_access');
     foreach ($ops as $op => $result) {
       $msg = t("file_entity_access returns @result with operation '@op'.", array('@result' => $result ? 'true' : 'false', '@op' => $op));
       $this->assertEqual($result, file_entity_access($op, $file, $account), $msg);
@@ -1107,32 +1126,24 @@ class FileEntityAccessTestCase extends FileEntityTestHelper {
     $web_user = $this->drupalCreateUser(array('create files', 'view own files'));
     $this->assertFileEntityAccess(array('view' => FALSE), $file, $web_user);
     $file->uid = $web_user->uid;
-    $file->status = FILE_STATUS_PERMANENT;
-    file_save($file);
     $this->assertFileEntityAccess(array('view' => TRUE), $file, $web_user);
 
     // User can download own files but no other files.
     $web_user = $this->drupalCreateUser(array('create files', 'download own image files'));
     $this->assertFileEntityAccess(array('download' => FALSE), $file, $web_user);
     $file->uid = $web_user->uid;
-    $file->status = FILE_STATUS_PERMANENT;
-    file_save($file);
     $this->assertFileEntityAccess(array('download' => TRUE), $file, $web_user);
 
     // User can update own files but no other files.
     $web_user = $this->drupalCreateUser(array('create files', 'view own files', 'edit own image files'));
     $this->assertFileEntityAccess(array('update' => FALSE), $file, $web_user);
     $file->uid = $web_user->uid;
-    $file->status = FILE_STATUS_PERMANENT;
-    file_save($file);
     $this->assertFileEntityAccess(array('update' => TRUE), $file, $web_user);
 
     // User can delete own files but no other files.
     $web_user = $this->drupalCreateUser(array('create files', 'view own files', 'edit own image files', 'delete own image files'));
     $this->assertFileEntityAccess(array('delete' => FALSE), $file, $web_user);
     $file->uid = $web_user->uid;
-    $file->status = FILE_STATUS_PERMANENT;
-    file_save($file);
     $this->assertFileEntityAccess(array('delete' => TRUE), $file, $web_user);
 
     // User can view any file.
@@ -1172,8 +1183,6 @@ class FileEntityAccessTestCase extends FileEntityTestHelper {
     $this->assertResponse(200, 'Users with access can access the file add page');
 
     $file = reset($this->files['text']);
-    $file->status = FILE_STATUS_PERMANENT;
-    file_save($file);
 
     // This fails.. No clue why but, tested manually and works as should.
     //$web_user = $this->drupalCreateUser(array('view own files'));
@@ -1188,16 +1197,19 @@ class FileEntityAccessTestCase extends FileEntityTestHelper {
     $url = "file/{$file->fid}/download";
     $web_user = $this->drupalCreateUser(array());
     $this->drupalLogin($web_user);
-    $this->drupalGet($url, array('query' => array('token' => $this->drupalGetToken($url))));
+    $this->drupalGet($url, array('query' => array('token' => file_entity_get_download_token($file))));
     $this->assertResponse(403, 'Users without access can not download the file');
     $web_user = $this->drupalCreateUser(array('download any document files'));
     $this->drupalLogin($web_user);
-    $this->drupalGet($url, array('query' => array('token' => $this->drupalGetToken($url))));
+    $this->drupalGet($url, array('query' => array('token' => file_entity_get_download_token($file))));
     $this->assertResponse(200, 'Users with access can download the file');
     $this->drupalGet($url, array('query' => array('token' => 'invalid-token')));
     $this->assertResponse(403, 'Cannot download file with in invalid token.');
     $this->drupalGet($url);
     $this->assertResponse(403, 'Cannot download file without a token.');
+    variable_set('file_entity_allow_insecure_download', TRUE);
+    $this->drupalGet($url);
+    $this->assertResponse(200, 'Users with access can download the file without a token when file_entity_allow_insecure_download is set.');
 
     $web_user = $this->drupalCreateUser(array());
     $this->drupalLogin($web_user);
@@ -1233,7 +1245,6 @@ class FileEntityAccessTestCase extends FileEntityTestHelper {
       // Create private, permanent files owned by this user only he's an owner.
       if (!empty($case['owner'])) {
         $file = next($this->files['text']);
-        $file->status = FILE_STATUS_PERMANENT;
         $file->uid = $account->uid;
         file_save($file);
         $file = file_move($file, 'private://');
@@ -1256,3 +1267,47 @@ class FileEntityAccessTestCase extends FileEntityTestHelper {
     }
   }
 }
+
+class FileEntityAttributeOverrideTestCase extends FileEntityTestHelper {
+
+  public static function getInfo() {
+    return array(
+      'name' => 'File entity attribute override',
+      'description' => 'Test overriding file entity attributes.',
+      'group' => 'File entity',
+    );
+  }
+
+  function setUp() {
+    parent::setUp();
+    $this->setUpFiles();
+  }
+
+  /**
+   * Test to see if file attributes can be overridden.
+   */
+  function testFileEntityFileAttributeOverrides() {
+    $overrides = array(
+      'width' => 40,
+      'height' => 20,
+      'alt' => $this->randomName(),
+      'title' => $this->randomName(),
+
+    );
+
+    // Retrieve an image file entity for testing.
+    $file = reset($this->files['image']);
+
+    // Override a variety of attributes.
+    foreach ($overrides as $override => $value) {
+      $file->override['attributes'][$override] = $value;
+    }
+
+    // Test that the attributes have been overridden.
+    $build = file_view_file($file, 'full');
+
+    foreach ($overrides as $attribute => $expected_value) {
+      $this->assertEqual($build['#item'][$attribute], $expected_value, format_string('The %attribute was overridden correctly.', array('%attribute' => $attribute)));
+    }
+  }
+}
diff --git a/drupal7/sites/all/modules/file_entity/file_entity.theme.inc b/drupal7/sites/all/modules/file_entity/file_entity.theme.inc
index 123b83ed..1819d979 100644
--- a/drupal7/sites/all/modules/file_entity/file_entity.theme.inc
+++ b/drupal7/sites/all/modules/file_entity/file_entity.theme.inc
@@ -58,9 +58,9 @@ function theme_file_entity_download_link($variables) {
     $variables['text'] = t('Download [file:name]');
   }
 
-  // Peform unsanitized token replacement if $uri['options']['html'] is empty
+  // Perform unsanitized token replacement if $uri['options']['html'] is empty
   // since then l() will escape the link text.
-  $variables['text'] = token_replace($variables['text'], array('file' => $file), array('clear' => TRUE, 'sanitize' => empty($uri['options']['html'])));
+  $variables['text'] = token_replace($variables['text'], array('file' => $file), array('clear' => TRUE, 'sanitize' => !empty($uri['options']['html'])));
 
   $output = '<span class="file">' . $icon . ' ' . l($variables['text'], $uri['path'], $uri['options']);
   $output .= ' ' . '<span class="file-size">(' . format_size($file->filesize) . ')</span>';
@@ -142,8 +142,10 @@ function theme_file_entity_file_video($variables) {
   if ($variables['muted']) {
     $video_attributes['muted'] = 'muted';
   }
-  if ($variables['width'] && $variables['height']) {
+  if ($variables['width']) {
     $video_attributes['width'] = $variables['width'];
+  }
+  if ($variables['height']) {
     $video_attributes['height'] = $variables['height'];
   }
 
diff --git a/drupal7/sites/all/modules/file_entity/file_entity.views.inc b/drupal7/sites/all/modules/file_entity/file_entity.views.inc
index ea8b5a1e..6a37901d 100644
--- a/drupal7/sites/all/modules/file_entity/file_entity.views.inc
+++ b/drupal7/sites/all/modules/file_entity/file_entity.views.inc
@@ -27,6 +27,16 @@ function file_entity_views_data() {
       'handler' => 'views_handler_argument_file_type',
     ),
   );
+
+  // File schema type.
+  $data['file_managed']['schema_type'] = array(
+    'title' => t('Schema type'),
+    'help' => t('Filter files by schema, such as public or private.'),
+    'filter' => array(
+      'handler' => 'views_handler_filter_schema_type',
+    ),
+  );
+
   // Rendered file.
   $data['file_managed']['rendered'] = array(
     'title' => t('Rendered'),
@@ -99,11 +109,15 @@ function file_entity_views_data() {
     'help' => t('Provide a simple link to view the usage of the file entity.'),
     'field' => array(
       'handler' => 'views_handler_field_file_link_usage',
+      'click sortable' => TRUE,
       'real field' => 'fid',
       'additional fields' => array(
         'fid',
       ),
     ),
+    'sort' => array(
+      'handler' => 'views_handler_sort',
+    ),
   );
 
   return $data;
diff --git a/drupal7/sites/all/modules/file_entity/tests/file_entity_test.info b/drupal7/sites/all/modules/file_entity/tests/file_entity_test.info
index 39040fbf..cf354022 100644
--- a/drupal7/sites/all/modules/file_entity/tests/file_entity_test.info
+++ b/drupal7/sites/all/modules/file_entity/tests/file_entity_test.info
@@ -5,9 +5,9 @@ core = 7.x
 dependencies[] = file_entity
 hidden = TRUE
 
-; Information added by drupal.org packaging script on 2013-10-25
-version = "7.x-2.0-alpha3"
+; Information added by Drupal.org packaging script on 2014-10-04
+version = "7.x-2.0-beta1"
 core = "7.x"
 project = "file_entity"
-datestamp = "1382744726"
+datestamp = "1412420930"
 
diff --git a/drupal7/sites/all/modules/file_entity/views/views_handler_field_file_link_download.inc b/drupal7/sites/all/modules/file_entity/views/views_handler_field_file_link_download.inc
index 088d18cc..21c27295 100644
--- a/drupal7/sites/all/modules/file_entity/views/views_handler_field_file_link_download.inc
+++ b/drupal7/sites/all/modules/file_entity/views/views_handler_field_file_link_download.inc
@@ -24,7 +24,7 @@ class views_handler_field_file_link_download extends views_handler_field_file_li
     $this->options['alter']['make_link'] = TRUE;
     $uri = file_entity_download_uri($file);
     $this->options['alter']['path'] = $uri['path'];
-    $this->options['alter'] += $uri['options'];
+    $this->options['alter'] = drupal_array_merge_deep($this->options['alter'], $uri['options']);
 
     $text = !empty($this->options['text']) ? $this->options['text'] : t('Download');
     return $text;
diff --git a/drupal7/sites/all/modules/file_entity/views/views_handler_field_file_link_usage.inc b/drupal7/sites/all/modules/file_entity/views/views_handler_field_file_link_usage.inc
index f4f64c24..49e1df8d 100644
--- a/drupal7/sites/all/modules/file_entity/views/views_handler_field_file_link_usage.inc
+++ b/drupal7/sites/all/modules/file_entity/views/views_handler_field_file_link_usage.inc
@@ -25,7 +25,17 @@ class views_handler_field_file_link_usage extends views_handler_field_file_link
     $this->options['alter']['path'] = "file/$file->fid/usage";
     $this->options['alter']['query'] = drupal_get_destination();
 
-    $text = !empty($this->options['text']) ? $this->options['text'] : t('Usage');
+    // Get total count for each file.
+    $total_count = 0;
+    foreach (file_usage_list($file) as $module => $usage) {
+      foreach ($usage as $entity_type => $entity_ids) {
+        foreach ($entity_ids as $id => $count) {
+          $total_count += $count;
+        }
+      }
+    }
+
+    $text = !empty($this->options['text']) ? $this->options['text'] : format_plural((int) $total_count, '1 place', '@count places');
     return $text;
   }
 }
diff --git a/drupal7/sites/all/modules/file_entity/views/views_handler_filter_schema_type.inc b/drupal7/sites/all/modules/file_entity/views/views_handler_filter_schema_type.inc
new file mode 100644
index 00000000..d3d8fbb8
--- /dev/null
+++ b/drupal7/sites/all/modules/file_entity/views/views_handler_filter_schema_type.inc
@@ -0,0 +1,41 @@
+<?php
+/**
+ * @file
+ * Filter by the file schema type.
+ */
+
+class views_handler_filter_schema_type extends views_handler_filter_in_operator {
+  function get_value_options() {
+    if (!isset($this->value_options)) {
+      $this->value_title = t('File Schema types');
+      $types = file_get_stream_wrappers(STREAM_WRAPPERS_VISIBLE);
+      $options = array();
+      foreach ($types as $type => $info) {
+        $options[$type] = t($info['name']);
+      }
+      asort($options);
+      $this->value_options = $options;
+    }
+  }
+
+  function op_simple() {
+    if (empty($this->value)) {
+      return;
+    }
+    $this->ensure_my_table();
+
+    // We use array_values() because the checkboxes keep keys and that can cause
+    // array addition problems.
+    $statements = array();
+
+    $not_in = $this->operator == 'not in' ? TRUE : FALSE;
+    $schema_operator = $not_in ? 'NOT LIKE' : 'LIKE';
+    $composite = $not_in ? ' AND ' : ' OR ';
+
+    foreach ($this->value as $schema) {
+      $statements[] = 'uri ' . $schema_operator . ' \'' . db_like($schema) . '://%\'';
+    }
+
+    $this->query->add_where_expression($this->options['group'], implode($composite, $statements));
+  }
+}
diff --git a/drupal7/sites/all/modules/media/API.txt b/drupal7/sites/all/modules/media/API.txt
deleted file mode 100644
index 9f5f5ecf..00000000
--- a/drupal7/sites/all/modules/media/API.txt
+++ /dev/null
@@ -1,152 +0,0 @@
-
-/**
- *  API documentation for the Media module.
- */
-
-The Media module provides a robust API for developers to extend functionality
-in useful and novel ways.
-
-CAUTION: This is pretty old!
-
-Architecture
-------------
-
-To understand the API, it is first important to understand the underlying
-architecture and the decisions behind its current implementation.
-
-Stream Wrappers
----------------
-
-First, the Media module makes heavy use of the core Stream Wrappers now
-provided with Drupal 7. Streams are classes that encapsulate PHP file
-functions, allowing an automatic override when calling the basic function.
-For instance, a wrapper implementing an Amazon S3 Stream might override the
-file_get_contents() using ->stream_open(), or a Flickr Stream Wrapper might
-implement its own ->getExternalUrl to return the HTML URI for a specific
-Flickr image.
-
-See http://api.drupal.org/file/includes/stream_wrappers.inc/7 for more
-information about Stream Wrappers in Drupal.
-
-Schemes
--------
-
-All Stream Wrappers will be registered to handle a specific scheme, which is
-the part of a URI before ://, such as core Drupal's public:// and private://
-schemes. (Technically, a scheme only requires :, but a bug in PHP 5.2
-requires ://, so Drupal currently keeps the same requirement.)
-
-The target after the scheme:// will be a unique identifier that the
-implementing Stream Wrapper will use to determine the file resource being
-accessed. For instance, public://my-document.txt might refer to a local file
-stored in the server at /sites/example.com/files/my-document.txt, while a URI
-of youtube://fe3fg8u34i might be the video stored at
-http://youtube.com/v/fe3fg8u34i, and flickr://photoset/224 might use a lookup
-table to determine this is a photoset accessed at
-http://flickr.com/user/markam/photoset/325hsd89.
-
-All files in Drupal are stored in the database with this unique URI, in
-addition to its unique serial FID. In general, file objects are accessed
-and loaded by the URI, which will automatically use the correct stream wrapper
-implementation for its scheme.
-
-File Field Widget
------------------
-
-The Media module extends the core File field to make use of its browser for
-editors, which is in turn exposed for other modules to extend. It does this
-by create a new widget definition, defining a File (media) 'generic' file
-widget, and suppressing the original File widget definition to avoid
-confusion. All existing file fields will be converted to this new widget on
-installation of the module, and if uninstalled, any defined media_generic file
-fields will be reverted to their original definition to avoid loss of data.
-
-Media Formatters
-----------------
-
-By default, the File (media) widget will use the original display behavior,
-which is to display a generic icon followed by a link to the file. However, in
-many (if not most) cases, a site administrator will want to display media in
-very specific ways. For instance, they might want an image uploaded to be
-displayed as a cropped thumbnail, as with any Flickr images attached to that
-field, while a YouTube video might be displayed as a thumbnail that pops up
-in a Shadowbox, and finally a PDF might be displayed in an iFrame. And that's
-only when it's displayed in a node teaser...
-
-To manage the various display formatting needs of an editor, the Media module
-offers a Media Style API for other modules to implement and extend. Media
-Styles of various mimetypes are grouped together and made available as new
-formatters for field display, whether for a node, a comment, in a view, or
-elsewhere.
-
-To implement a new Media Style, a module needs to register itself for a
-specific mimetype, with the following hook. Note that Media styles will be
-properly namespaced by the module, to avoid conflicts.
-
-function hook_media_styles($mimetype = NULL) {
-  switch ($mimetype) {
-    case 'video/x-youtube':
-      return array(
-        'youtube_video' => t('YouTube Video'),
-        'youtube_thumbnail' => t('YouTube Thumbnail'),
-        'youtube_shadowbox' => t('YouTube Shadowbox'),
-        'youtube_link' => t('Youtube (link to original)'),
-    case 'image/x-flickr':
-      $styles = array(
-        'flickr__original' => t('Flickr (Original size)'),
-      );
-      foreach (image_styles() as $style_name => $style) {
-        $styles[$style_name] = t('Flickr (@style)', array('@style' => $style->name));
-      }
-      return $styles;
-  }
-}
-
-These styles will be available from the Media Styles configuration page, where
-multiple formatters can be grouped together to create new formatter Style
-bundles, available and intelligently applied to files of the appropriate
-mimetypes.
-
-For instance, a new Media Style might be created, named 'Small image', which
-will bundle an Image style for the various image mimetypes, another for Flickr
-images, a shadowbox for YouTube thumbnails, and a fallback to a size styled
-File icon. Then this style would be made available as a display formatter, and
-the Media module will apply the correct style for the mimetype of the
-particular instance.
-
-A module may also define default Media styles to be made available, by
-implementing hook_media_default_style_bundles(). Unlike the individual Media Styles,
-Media Style bundles are not namespaced by module. If two or more modules use
-the same Style bundle names, the behavior is undefined. Also note that the
-administrator may override a specific Style bundle, for instance by replacing
-the Style for a specific mimetype.
-
-function hook_media_default_style_bundles() {
-  return array(
-    'shadowbox_images' => array(
-      'label' => t('Shadowbox images'),
-      'mimetypes' => array(
-        'image/*' => 'mymodule_image_shadowbox',
-        'video/*' => 'mymodule_video_shadowbox',
-        '*' => 'mymodule_default_shadowbox',
-      ),
-    ),
-  );
-}
-
-@TODO
-convert existing file fields to media_generic on hook_install
-convert existing media_generic to file fields on hook_uninstall
-allow theme_file_icon file directory override in widget display settings
-  (Requires http://drupal.org/node/650732)
-create new default file icons and set its folder as the new default
-maybe instead/in addition have fallbacks if icon not present?
-rename image style square_thumbnail to use the media_ namespace
-review Media Styles for feasibility, usability, and architecture
-create Media Styles UI .inc file
-look at hook_field_info_alter to see if we can affect file widget that way
-CLEAN CRUFT (lots of functions that no longer apply or need to be rethought)
-why do we want to override the file field widget again?
-should we also move 'media_styles' to its own module, perhaps file_styles?
-in media_field_formatter_info(),
-  should 'field types' => array('media_generic', 'file'), be only one or other?
diff --git a/drupal7/sites/all/modules/media/CHANGELOG.txt b/drupal7/sites/all/modules/media/CHANGELOG.txt
deleted file mode 100644
index f5d9199a..00000000
--- a/drupal7/sites/all/modules/media/CHANGELOG.txt
+++ /dev/null
@@ -1 +0,0 @@
-This is outdated.  For a changelog see the appropriate branch or tag on http://drupalcode.org/project/media.git/heads
diff --git a/drupal7/sites/all/modules/media/css/media.css b/drupal7/sites/all/modules/media/css/media.css
index 0873b28d..a9371562 100644
--- a/drupal7/sites/all/modules/media/css/media.css
+++ b/drupal7/sites/all/modules/media/css/media.css
@@ -10,6 +10,9 @@
 .ui-tabs {
   padding: 0;
 }
+.ui-front {
+  z-index: 10001 !important;
+}
 
 .ui-dialog.media-wrapper .ui-dialog-content {
   padding: 0;
@@ -58,38 +61,38 @@
   margin-right: 0;
 }
 
-.media-browser-tab.ui-tabs-panel {
-  border: 1px solid #cccccc;
-}
-
 /* *********************************************************** */
 /* Media item display */
 
 .media-item {
-  background: #FFFFFF;
+  background: #eee;
   border: 1px solid #CCCCCC;
+  box-shadow: inset 0 0 15px rgba(0,0,0,.1), inset 0 0 0 1px rgba(0,0,0,.05);
+  display: inline-block;
   padding: 5px;
-   position: relative;
+  position: relative;
 }
 
 .media-item img {
-  margin-bottom: 10px;
+  display: block;
 }
 
 .media-item .label-wrapper {
-  text-align: center;
-  position: absolute;
+  background: rgba(255,255,255,.8);
   bottom: 0;
-  margin-left: auto;
-  margin-right: auto;
-  width: 90%;
+  box-shadow: inset 0 0 0 1px rgba(0,0,0,.15);
+  left: 0;
+  max-height: 100%;
+  overflow: hidden;
+  position: absolute;
+  right: 0;
+  text-align: center;
+  word-wrap: break-word;
 }
 
 .media-item .label-wrapper label {
   font-size: 10px;
-  overflow: hidden;
-  text-overflow: ellipsis;
-  white-space: nowrap;
+  padding: 5px 10px;
 }
 
 /* Media item lists */
@@ -128,66 +131,17 @@
 }
 
 .media-list-thumbnails .form-type-checkbox {
-  bottom: 135px;
-  left: 8px;
+  bottom: 117px;
+  left: 6px;
   margin: 0;
   padding: 0;
   position: relative;
 }
 
-/* Format form */
-
-#media-format-form {
-  margin: 20px;
-}
-
-#media-format-form .media-item {
-  float: left;
-  margin-right: 10px;
-}
-
-#media-format-form .form-item-format label {
-  display: inline;
-}
-
 /* File field */
 
 .media-widget .preview {
   display: inline-block;
-  vertical-align: middle;
-}
-
-.media-widget .preview a {
-  text-decoration: none;
-}
-
-.media-widget .preview .media-item {
   margin-right: 10px;
-}
-
-.media-widget .preview .media-item:hover {
-  border-color: #058AC5;
-  cursor: pointer;
-}
-
-.media-widget .preview .media-item .label-wrapper label {
-  color: #058AC5;
-}
-
-.media-widget .preview .media-item .label-wrapper label:hover {
-  cursor: pointer;
-}
-
-/* Plupload */
-
-body.page-media-format-form #media-browser-page .plupload_start {
-  display: none;
-}
-
-/* Multiedit */
-
-.media-multiedit-form .media-edit-form {
-  border-bottom: 1px solid #AAAAAA;
-  margin-bottom: 1em;
-  margin-top: 1.5em;
+  vertical-align: middle;
 }
diff --git a/drupal7/sites/all/modules/media/images/file-unknown.png b/drupal7/sites/all/modules/media/images/file-unknown.png
deleted file mode 100644
index fb1b2f10..00000000
Binary files a/drupal7/sites/all/modules/media/images/file-unknown.png and /dev/null differ
diff --git a/drupal7/sites/all/modules/media/includes/MediaBrowserUpload.inc b/drupal7/sites/all/modules/media/includes/MediaBrowserUpload.inc
index 65e99778..57721cb9 100644
--- a/drupal7/sites/all/modules/media/includes/MediaBrowserUpload.inc
+++ b/drupal7/sites/all/modules/media/includes/MediaBrowserUpload.inc
@@ -25,13 +25,7 @@ class MediaBrowserUpload extends MediaBrowserPlugin {
     module_load_include('inc', 'file_entity', 'file_entity.pages');
 
     $build = array();
-    if ($this->params['multiselect'] && module_exists('plupload')) {
-      $build['form'] = drupal_get_form('file_entity_add_upload_multiple', $this->params);
-      $build['#attached']['js'][] = drupal_get_path('module', 'media') . '/js/plugins/media.upload_multiple.js';
-    }
-    else {
-      $build['form'] = drupal_get_form('file_entity_add_upload', $this->params);
-    }
+    $build['form'] = drupal_get_form('file_entity_add_upload', $this->params);
 
     return $build;
   }
diff --git a/drupal7/sites/all/modules/media/includes/media.admin.inc b/drupal7/sites/all/modules/media/includes/media.admin.inc
index c0288a23..9cc9fa14 100644
--- a/drupal7/sites/all/modules/media/includes/media.admin.inc
+++ b/drupal7/sites/all/modules/media/includes/media.admin.inc
@@ -2,243 +2,135 @@
 
 /**
  * @file
- * This file contains the admin functions for the Media module.
+ * Administration page callbacks for the Media module.
  */
 
 /**
- * Include media.pages.inc since it has some form definitions we will use.
- */
-require_once dirname(__FILE__) . '/media.pages.inc';
-
-/**
- * Form callback for mass import.
- */
-function media_import($form, &$form_state) {
-  if (!isset($form_state['storage']['files'])) {
-    $form_state['storage']['step'] = 'choose';
-    $form_state['storage']['next_step'] = 'preview';
-    $form['directory'] = array(
-      '#type' => 'textfield',
-      '#title' => t('Directory'),
-      '#description' => t('Enter the absolute directory on the web server to look for files. Subdirectories inside this directory will not be scanned.'),
-      '#required' => TRUE,
-    );
-
-    $form['pattern'] = array(
-      '#type' => 'textarea',
-      '#title' => t('Pattern'),
-      '#description' => t("Only files matching these patterns will be imported. Enter one pattern per line. The '*' character is a wildcard. Example patterns are %png_example to import all PNG files.", array('%png_example' => '*.png')),
-      '#default_value' => '*',
-      '#required' => TRUE,
-    );
-
-    $form['actions'] = array('#type' => 'actions');
-    $form['actions']['submit'] = array(
-      '#type' => 'submit',
-      '#value' => t('Preview'),
-    );
-    $form['actions']['cancel'] = array(
-      '#type' => 'link',
-      '#title' => t('Cancel'),
-      '#href' => isset($_GET['destination']) ? $_GET['destination'] : 'admin/content/file',
-    );
-  }
-  else {
-    $form['preview'] = array(
-      '#markup' => theme('item_list', array('items' => $form_state['storage']['files'])),
-    );
-
-    $form = confirm_form($form, t('Import these files?'), 'admin/content/file/import');
-  }
-  return $form;
-
-}
-
-/**
- * Validate handler for media_import().
- */
-function media_import_validate($form, &$form_state) {
-  if ($form_state['values']['op'] != t('Confirm')) {
-    $directory = $form_state['values']['directory'];
-    $pattern = $form_state['values']['pattern'];
-    if (!is_dir($directory)) {
-      form_set_error('directory', t('The provided directory does not exist.'));
-    }
-    if (!is_readable($directory)) {
-      form_set_error('directory', t('The provided directory is not readable.'));
-    }
-
-    $pattern_quoted = preg_quote($pattern, '/');
-    $pattern_quoted = preg_replace('/(\r\n?|\n)/', '|', $pattern_quoted);
-    $pattern_quoted = strtr($pattern_quoted, array(
-      '\\|' => '|',
-      '\\*' => '.*',
-      '\\?' => '.?',
-    ));
-    $files = file_scan_directory($directory, '/^(' . $pattern_quoted . ')$/', array('recurse' => FALSE));
-    $files = array_keys($files);
-    if (empty($files)) {
-      form_set_error('pattern', t('No files were found in %directory matching the regular expression %pattern', array('%directory' => $directory, '%pattern' => $pattern_quoted)));
-    }
-    $form_state['storage']['files'] = $files;
-  }
-}
-
-/**
- * Submit handler for media_import().
- */
-function media_import_submit($form, &$form_state) {
-  if ($form_state['values']['op'] == t('Confirm')) {
-    $files = $form_state['storage']['files'];
-    $batch = array(
-      'title' => t('Importing'),
-      'operations' => array(
-        array('media_import_batch_import_files', array($files)),
-      ),
-      'finished' => 'media_import_batch_import_complete',
-      'file' => drupal_get_path('module', 'media') . '/includes/media.admin.inc',
-    );
-    batch_set($batch);
-    return;
-
-  }
-  $form_state['rebuild'] = TRUE;
-}
-
-/**
- * BatchAPI callback op for media import.
- */
-function media_import_batch_import_files($files, &$context) {
-  if (!isset($context['sandbox']['files'])) {
-    // This runs the first time the batch runs.
-    // This is stupid, but otherwise, I don't think it will work...
-    $context['results'] = array('success' => array(), 'errors' => array());
-    $context['sandbox']['max'] = count($files);
-    $context['sandbox']['files'] = $files;
-  }
-  $files =& $context['sandbox']['files'];
-
-  // Take a cut of files.  Let's do 10 at a time.
-  $import_batch_size = variable_get('media__import_batch_size', 20);
-  $length = (count($files) > $import_batch_size) ? $import_batch_size : count($files);
-  $to_process = array_splice($files, 0, $length);
-  $image_in_message = '';
-
-  foreach ($to_process as $file) {
-    try {
-      $file_obj = media_parse_to_file($file);
-      $context['results']['success'][] = $file;
-      if (!$image_in_message) {
-        // @todo Is this load step really necessary? When there's time, test
-        //   this, and either remove it, or comment why it's needed.
-        $loaded_file = file_load($file_obj->fid);
-        $image_in_message = file_view_file($loaded_file, 'preview');
-      }
-    }
-    catch (Exception $e) {
-      $context['results']['errors'][] = $file . " Reason: " . $e->getMessage();
-    }
-  }
-
-  $context['message'] = "Importing " . theme('item_list', array('items' => $to_process));
-  // Show the image that is being imported.
-  $context['message'] .= drupal_render($image_in_message);
-
-  $context['finished'] = ($context['sandbox']['max'] - count($files)) / $context['sandbox']['max'];
-}
-
-/**
- * BatchAPI complete callback for media import.
- */
-function media_import_batch_import_complete($success, $results, $operations) {
-  if ($results['errors']) {
-    drupal_set_message(theme('item_list', array('items' => $results['errors'])), 'error');
-  }
-  if ($results['success']) {
-    drupal_set_message(theme('item_list', array('items' => $results['success'])));
-  }
-}
-
-/**
- * Admin configruation form for media browser settings.
+ * Displays the media administration page.
  */
 function media_admin_config_browser($form, &$form_state) {
   $theme_options = array();
-  $theme_options[NULL] = 'Default administration theme';
+  $theme_options[NULL] = t('Default administration theme');
+
   foreach (list_themes() as $key => $theme) {
     if ($theme->status) {
       $theme_options[$key] = $theme->info['name'];
     }
   }
 
-  $form['media__dialog_theme'] = array(
+  $form['media_dialog_theme'] = array(
     '#type' => 'select',
     '#title' => t('Media browser theme'),
     '#options' => $theme_options,
-    '#description' => t("This theme will be used for all media related dialogs.
-      It can be different from your site's theme because many site themes do not
-      work well in the small windows which media uses."),
-    '#default_value' => variable_get('media__dialog_theme', ''),
+    '#description' => t("This theme will be used for all media related dialogs. It can be different from your site's theme because many site themes do not work well in the small windows which media uses."),
+    '#default_value' => variable_get('media_dialog_theme', ''),
   );
 
-  // Additional configuration if the WYSIWYG module is enabled.
-  $form['wysiwyg'] = array(
+  $form['array_filter'] = array(
+    '#type' => 'value',
+    '#value' => TRUE,
+  );
+
+  $form['mediapopup'] = array(
     '#type' => 'fieldset',
-    '#title' => t('WYSIWYG configuration'),
+    '#title' => t('Media Popup'),
     '#collapsible' => TRUE,
-    '#collapsed' => FALSE,
-    '#access' => module_exists('wysiwyg'),
+    '#collapsed' => TRUE,
   );
-  $plugins = media_get_browser_plugin_info();
-  $form['wysiwyg']['media__wysiwyg_browser_plugins'] = array(
-    '#type' => 'checkboxes',
-    '#title' => t('Enabled browser plugins'),
-    '#options' => array(),
-    '#required' => FALSE,
-    '#default_value' => variable_get('media__wysiwyg_browser_plugins', array()),
-    '#description' => t('If no plugins are selected, they will all be available.'),
+  $form['mediapopup']['media_dialogclass'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Dialog Class'),
+    '#default_value' => variable_get('media_dialogclass', 'media-wrapper'),
+    '#description' => t('The class used to identify the popup wrapper element.'),
   );
-  foreach ($plugins as $key => $plugin) {
-    $form['wysiwyg']['media__wysiwyg_browser_plugins']['#options'][$key] = !empty($plugin['title']) ? $plugin['title'] : $key;
-  }
-  $form['wysiwyg']['media__wysiwyg_upload_directory'] = array(
+  $form['mediapopup']['media_modal'] = array(
+    '#type' => 'select',
+    '#title' => t('Modal'),
+    '#options' => array(
+      FALSE => t('False'),
+      TRUE => t('True'),
+    ),
+    '#default_value' => variable_get('media_modal', TRUE),
+    '#description' => t('Open as modal window.'),
+  );
+  $form['mediapopup']['media_draggable'] = array(
+    '#type' => 'select',
+    '#title' => t('Draggable'),
+    '#options' => array(
+      FALSE => t('False'),
+      TRUE => t('True'),
+    ),
+    '#default_value' => variable_get('media_draggable', FALSE),
+    '#description' => t('Draggable modal window.'),
+  );
+  $form['mediapopup']['media_resizable'] = array(
+    '#type' => 'select',
+    '#title' => t('Resizable'),
+    '#options' => array(
+      FALSE => t('False'),
+      TRUE => t('True'),
+    ),
+    '#default_value' => variable_get('media_resizable', FALSE),
+    '#description' => t('Resizable modal window.'),
+  );
+  $form['mediapopup']['media_minwidth'] = array(
     '#type' => 'textfield',
-    '#title' => t("File directory for uploaded media"),
-    '#default_value' => variable_get('media__wysiwyg_upload_directory', ''),
-    '#description' => t('Optional subdirectory within the upload destination where files will be stored. Do not include preceding or trailing slashes.'),
+    '#title' => t('Min Width'),
+    '#default_value' => variable_get('media_minwidth', 500),
+    '#description' => t('CSS property min-width.'),
   );
-
-  if (module_exists('token')) {
-    $form['wysiwyg']['media__wysiwyg_upload_directory']['#description'] .= t('This field supports tokens.');
-    $form['wysiwyg']['tokens'] = array(
-      '#theme' => 'token_tree',
-      '#dialog' => TRUE,
-    );
-  }
-
-  $form['wysiwyg']['media__wysiwyg_allowed_types'] = array(
-    '#type' => 'checkboxes',
-    '#title' => t('Allowed types in WYSIWYG'),
-    '#options' => file_entity_type_get_names(),
-    '#default_value' => variable_get('media__wysiwyg_allowed_types', array('audio', 'image', 'video', 'document')),
+  $form['mediapopup']['media_width'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Width'),
+    '#default_value' => variable_get('media_width', 670),
+    '#description' => t('CSS property width.'),
+  );
+  $form['mediapopup']['media_height'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Height'),
+    '#default_value' => variable_get('media_height', 280),
+    '#description' => t('CSS property height.'),
+  );
+  $form['mediapopup']['media_position'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Position'),
+    '#default_value' => variable_get('media_position', 'center'),
+    '#description' => t('CSS property position.'),
+  );
+  $form['mediapopup']['media_zindex'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Z-Index'),
+    '#default_value' => variable_get('media_zindex', 10000),
+    '#description' => t('CSS property z-index.'),
+  );
+  $form['mediapopup']['overlay'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Overlay'),
+  );
+  $form['mediapopup']['overlay']['media_backgroundcolor'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Background Color'),
+    '#default_value' => variable_get('media_backgroundcolor', '#000000'),
+    '#description' => t('CSS property background-color; used with overlay.'),
+  );
+  $form['mediapopup']['overlay']['media_opacity'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Opacity'),
+    '#default_value' => variable_get('media_opacity', 0.4),
+    '#description' => t('CSS property opacity; used with overlay.'),
   );
-  $form['array_filter'] = array('#type' => 'value', '#value' => TRUE);
 
   $form['#submit'][] = 'media_admin_config_browser_pre_submit';
+
   return system_settings_form($form);
 }
 
 /**
- * Manipulate values before form is submitted.
+ * Form submission handler for media_admin_config_browser().
  */
 function media_admin_config_browser_pre_submit(&$form, &$form_state) {
-  if (!$form_state['values']['media__dialog_theme']) {
-    variable_del('media__dialog_theme');
-    unset($form_state['values']['media__dialog_theme']);
-  }
-  $wysiwyg_browser_plugins = array_unique(array_values($form_state['values']['media__wysiwyg_browser_plugins']));
-  if (empty($wysiwyg_browser_plugins[0])) {
-    variable_del('media__wysiwyg_browser_plugins');
-    unset($form_state['values']['media__wysiwyg_browser_plugins']);
+  if (!$form_state['values']['media_dialog_theme']) {
+    variable_del('media_dialog_theme');
+    unset($form_state['values']['media_dialog_theme']);
   }
 }
diff --git a/drupal7/sites/all/modules/media/includes/media.browser.inc b/drupal7/sites/all/modules/media/includes/media.browser.inc
index 626fc006..d8037221 100644
--- a/drupal7/sites/all/modules/media/includes/media.browser.inc
+++ b/drupal7/sites/all/modules/media/includes/media.browser.inc
@@ -12,7 +12,7 @@ function media_browser($selected = NULL) {
   $output = array();
   $output['#attached']['library'][] = array('media', 'media_browser_page');
 
-  $params = media_set_browser_params();
+  $params = media_get_browser_params();
 
   // If one or more files have been selected, the browser interaction is now
   // complete. Return empty page content to the dialog which now needs to close,
@@ -77,8 +77,8 @@ function media_browser($selected = NULL) {
       continue;
     }
 
-    // We need to get a submit and cancel button on each tab. If the plugin
-    // is not returning a form element we need to add a submit button.
+    // We need to ensure that a submit button is available on each tab. If the
+    // plugin is not returning a form element we need to add a submit button.
     // This is a fairly broad assumption.
     if (empty($plugin_output[$key]['#form']) && !empty($plugin_output[$key]['#markup'])) {
       $fake_buttons = '<div class="form-actions form-wrapper">';
@@ -87,34 +87,9 @@ function media_browser($selected = NULL) {
           'class' => array('button', 'button-yes', 'fake-submit', $key),
         ),
       ));
-      $fake_buttons .= l(t('Cancel'), '', array(
-        'attributes' => array(
-          'class' => array('button', 'button-no', 'fake-cancel', $key),
-        ),
-      ));
       $fake_buttons .= '</div>';
       $plugin_output[$key]['#markup'] .= $fake_buttons;
     }
-
-    // I'm not sure if it is ever the case that a plugin form will ever have
-    // the correct cancel button so we add it here. Put it inline with the
-    // current submit button. This is a fairly broad assumption.
-    if (!empty($plugin_output[$key]['form']['actions']) && !isset($plugin_output[$key]['form']['actions']['cancel'])) {
-      $plugin_output[$key]['form']['actions']['cancel'] = array(
-        '#type' => 'link',
-        '#title' => t('Cancel'),
-        '#href' => '',
-        '#attributes' => array(
-          'class' => array(
-            'button',
-            'button-no',
-            'fake-cancel',
-            $key,
-          ),
-        ),
-        '#weight' => 100,
-      );
-    }
   }
 
   // Allow modules to change the tab names or whatever else they want to change
@@ -162,10 +137,6 @@ function media_browser($selected = NULL) {
 
   drupal_add_js($settings, 'setting');
 
-  $output['title'] = array(
-    '#markup' => t('Select a file')
-  );
-
   $output['tabset']['tabs'] = array(
     '#theme' => 'menu_local_tasks',
     '#attributes' => array('class' => array('tabs', 'primary')),
@@ -177,59 +148,6 @@ function media_browser($selected = NULL) {
   return $output;
 }
 
-/**
- * Provides a singleton of the params passed to the media browser.
- *
- * This is useful in situations like form alters because callers can pass
- * id="wysiywg_form" or whatever they want, and a form alter could pick this up.
- * We may want to change the hook_media_browser_plugin_view() implementations to
- * use this function instead of being passed params for consistency.
- *
- * It also offers a chance for some meddler to meddle with them.
- *
- * @see media_browser()
- */
-function media_set_browser_params() {
-  $params = &drupal_static(__FUNCTION__, array());
-
-  if (empty($params)) {
-    // Build out browser settings. Permissions- and security-related behaviors
-    // should not rely on these parameters, since they come from the HTTP query.
-    // @TODO make sure we treat parameters as user input.
-    $params = drupal_get_query_parameters() + array(
-      'types' => array(),
-      'multiselect' => FALSE,
-    );
-
-    // Transform text 'true' and 'false' to actual booleans.
-    foreach ($params as $k => $v) {
-      if ($v === 'true') {
-        $params[$k] = TRUE;
-      }
-      elseif ($v === 'false') {
-        $params[$k] = FALSE;
-      }
-    }
-
-    array_walk_recursive($params, 'media_recursive_check_plain');
-
-    // Allow modules to alter the parameters.
-    drupal_alter('media_browser_params', $params);
-  }
-
-  return $params;
-}
-
-
-/**
- * For sanity in grammar.
- *
- * @see media_set_browser_params()
- */
-function media_get_browser_params() {
-  return media_set_browser_params();
-}
-
 /**
  * Attaches media browser javascript to an element.
  *
@@ -251,27 +169,43 @@ function media_attach_browser_js(&$element) {
 function media_browser_js() {
   $settings = array(
     'browserUrl' => url('media/browser', array(
-        'query' => array('render' => 'media-popup'),
-      )
+      'query' => array(
+        'render' => 'media-popup'
+      ))
     ),
     'styleSelectorUrl' => url('media/-media_id-/format-form', array(
-        'query' => array('render' => 'media-popup'),
-      )
+      'query' => array(
+        'render' => 'media-popup'
+      ))
+    ),
+    'dialogOptions' => array(
+      'dialogclass' => variable_get('media_dialogclass', 'media-wrapper'),
+      'modal' => (boolean)variable_get('media_modal', TRUE),
+      'draggable' => (boolean)variable_get('media_draggable', FALSE),
+      'resizable' => (boolean)variable_get('media_resizable', FALSE),
+      'minwidth' => (int)variable_get('media_minwidth', 500),
+      'width' => (int)variable_get('media_width', 670),
+      'height' => (int)variable_get('media_height', 280),
+      'position' => variable_get('media_position', 'center'),
+      'overlay' => array(
+        'backgroundcolor' => variable_get('media_backgroundcolor', '#000000'),
+        'opacity' => (float)variable_get('media_opacity', 0.4),
+      ),
+      'zindex' => (int)variable_get('media_zindex', 10000),
     ),
   );
 
-  $js = array(
+  return array(
     'library' => array(
       array('media', 'media_browser'),
     ),
     'js' => array(
       array(
-        'data' => array('media' => $settings),
-        'type' => 'setting',
+       'data' => array('media' => $settings),
+       'type' => 'setting',
       ),
     ),
   );
-  return $js;
 }
 
 /**
diff --git a/drupal7/sites/all/modules/media/includes/media.fields.inc b/drupal7/sites/all/modules/media/includes/media.fields.inc
index 29b63a97..c3132116 100644
--- a/drupal7/sites/all/modules/media/includes/media.fields.inc
+++ b/drupal7/sites/all/modules/media/includes/media.fields.inc
@@ -2,8 +2,8 @@
 
 /**
  * @file
- * Provide the media file selector widget and media field formatters to the
- * Fields API.
+ * Provide the media selector widget and media field formatters to the Fields
+ * API.
  */
 
 /**
@@ -12,110 +12,64 @@
 function media_field_widget_info() {
   return array(
     'media_generic' => array(
-      'label' => t('Media file selector'),
+      'label' => t('Media browser'),
       'field types' => array('file', 'image'),
       'settings' => array(
-        'progress_indicator' => 'throbber',
         'allowed_types' => array('image'),
         'browser_plugins' => array(),
         'allowed_schemes' => array('public', 'private'),
       ),
       'behaviors' => array(
-        'multiple values' => FIELD_BEHAVIOR_DEFAULT,
+        'multiple values' => FIELD_BEHAVIOR_CUSTOM,
         'default value' => FIELD_BEHAVIOR_NONE,
       ),
     ),
   );
 }
 
-/**
- * Implements hook_field_formatter_info().
- *
- * Provides legacy support for the "Large filetype icon" file field formatter.
- * This was originally used when media entities contained file fields. The
- * current file entity architecture no longer needs this, but people may
- * have used this formatter for other file fields on their website.
- *
- * @todo Some day, remove this.
- */
-function media_field_formatter_info() {
-  $formatters = array(
-    'media_large_icon' => array(
-      'label' => t('Large filetype icon'),
-      'field types' => array('file'),
-    ),
-  );
-  return $formatters;
-}
-
-/**
- * Implements hook_field_formatter_view().
- *
- * Legacy support for the "Large filetype icon" file field formatter.
- * @see media_field_formatter_info()
- */
-function media_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
-  $element = array();
-
-  if ($display['type'] == 'media_large_icon') {
-    // Use the media_thumbnail image style so that the output in media browser
-    // is consistent.
-    foreach ($items as $delta => $item) {
-      $element[$delta] = array(
-        '#theme' => 'media_formatter_large_icon',
-        '#file' => (object) $item,
-      );
-    }
-  }
-
-  return $element;
-}
-
 /**
  * Implements hook_field_widget_settings_form().
  */
 function media_field_widget_settings_form($field, $instance) {
   $widget = $instance['widget'];
   $settings = $widget['settings'];
-  $form = array();
 
-  $streams = file_get_stream_wrappers(STREAM_WRAPPERS_VISIBLE);
+  $plugins = media_get_browser_plugin_info();
+  $options = array();
+  foreach ($plugins as $key => $plugin) {
+    $options[$key] = check_plain($plugin['title']);
+  }
+
+  $form['browser_plugins'] = array(
+    '#type' => 'checkboxes',
+    '#title' => t('Enabled browser plugins'),
+    '#options' => $options,
+    '#default_value' => $settings['browser_plugins'],
+    '#description' => t('Media browser plugins which are allowed for this field. If no plugins are selected, they will all be available.'),
+  );
 
   $form['allowed_types'] = array(
     '#type' => 'checkboxes',
-    '#title' => t('Allowed remote media types'),
+    '#title' => t('Allowed file types'),
     '#options' => file_entity_type_get_names(),
     '#default_value' => $settings['allowed_types'],
-    '#description' => t('Media types which are allowed for this field when using remote streams.'),
-    '#weight' => 1,
-    '#access' => count(file_get_stream_wrappers(STREAM_WRAPPERS_VISIBLE | STREAM_WRAPPERS_LOCAL)) != count($streams),
+    '#description' => t('File types which are allowed for this field. If no file types are selected, they will all be available.'),
   );
 
+  $visible_steam_wrappers = file_get_stream_wrappers(STREAM_WRAPPERS_VISIBLE);
   $options = array();
-  foreach ($streams as $scheme => $data) {
-    $options[$scheme] = t('@scheme (@name)', array('@scheme' => $scheme . '://', '@name' => $data['name']));
+  foreach ($visible_steam_wrappers as $scheme => $information) {
+    $options[$scheme] = check_plain($information['name']);
   }
+
   $form['allowed_schemes'] = array(
     '#type' => 'checkboxes',
     '#title' => t('Allowed URI schemes'),
     '#options' => $options,
     '#default_value' => $settings['allowed_schemes'],
-    '#description' => t('URI schemes include public:// and private:// which are the Drupal files directories, and may also refer to remote sites.'),
-    '#weight' => 2,
+    '#description' => t('URI schemes which are allowed for this field. If no schemes are selected, they will all be available.'),
   );
 
-  $plugins = media_get_browser_plugin_info();
-  $form['browser_plugins'] = array(
-    '#type' => 'checkboxes',
-    '#title' => t('Enabled browser plugins'),
-    '#options' => array(),
-    '#default_value' => $settings['browser_plugins'],
-    '#description' => t('If no plugins are selected, they will all be available.'),
-  );
-  foreach ($plugins as $key => $plugin) {
-    $form['browser_plugins']['#options'][$key] = !empty($plugin['title']) ? $plugin['title'] : $key;
-  }
-
   return $form;
 }
 
@@ -123,95 +77,496 @@ function media_field_widget_settings_form($field, $instance) {
  * Implements hook_field_widget_form().
  */
 function media_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
-  $field_settings = $instance['settings'];
-  $widget_settings = $instance['widget']['settings'];
 
-  // @todo The Field API supports automatic serialization / unserialization, so
-  //   this should no longer be needed. After verifying with a module that uses
-  //   the 'data' column, remove this.
-  // @see media_field_widget_value()
-  $current_value = array();
-  if (isset($items[$delta])) {
-    $current_value = $items[$delta];
-    // @todo $items[$delta] is sometimes a loaded media entity (an object)
-    //   rather than an array. This conflicts with Field API expectations (for
-    //   example, it results in fatal errors when previewing a node with a
-    //   multi-valued media field), so should be fixed. In the meantime, don't
-    //   assume that $current_value is an array.
-    if (is_array($current_value) && isset($current_value['data']) && is_string($current_value['data'])) {
-      $current_value['data'] = unserialize($current_value['data']);
-    }
+  // Add display_field setting to field because media_field_widget_form() assumes it is set.
+  if (!isset($field['settings']['display_field'])) {
+    $field['settings']['display_field'] = 0;
   }
 
+  $defaults = array(
+    'fid' => 0,
+    'display' => !empty($field['settings']['display_default']),
+    'description' => '',
+  );
+
+  // Load the items for form rebuilds from the field state as they might not be
+  // in $form_state['values'] because of validation limitations. Also, they are
+  // only passed in as $items when editing existing entities.
+  $field_state = field_form_get_state($element['#field_parents'], $field['field_name'], $langcode, $form_state);
+  if (isset($field_state['items'])) {
+    $items = $field_state['items'];
+  }
+
+  $field_settings = $instance['settings'];
+  $widget_settings = $instance['widget']['settings'];
+
+  // Essentially we use the media type, extended with some enhancements.
+  $element_info = element_info('media');
   $element += array(
-    // @todo This should be a fieldset, but throws a warning about
-    // element_children.
     '#type' => 'media',
-    '#collapsed' => TRUE,
-    '#default_value' => $current_value,
-    '#required' => $instance['required'],
+    '#value_callback' => 'media_field_widget_value',
+    '#process' => array_merge($element_info['#process'], array('media_field_widget_process')),
     '#media_options' => array(
       'global' => array(
         'types' => array_filter($widget_settings['allowed_types']),
         'enabledPlugins' => array_filter($instance['widget']['settings']['browser_plugins']),
-        'schemes' => $widget_settings['allowed_schemes'],
+        'schemes' => array_filter($widget_settings['allowed_schemes']),
         'file_directory' => isset($field_settings['file_directory']) ? $field_settings['file_directory'] : '',
         'file_extensions' => isset($field_settings['file_extensions']) ? $field_settings['file_extensions'] : variable_get('file_entity_default_allowed_extensions', 'jpg jpeg gif png txt doc docx xls xlsx pdf ppt pptx pps ppsx odt ods odp mp3 mov mp4 m4a m4v mpeg avi ogg oga ogv weba webp webm'),
         'max_filesize' => isset($field_settings['max_filesize']) ? $field_settings['max_filesize'] : 0,
         'uri_scheme' => !empty($field['settings']['uri_scheme']) ? $field['settings']['uri_scheme'] : file_default_scheme(),
       ),
     ),
+    // Allows this field to return an array instead of a single value.
+    '#extended' => TRUE,
   );
 
-  if ($field['cardinality'] != 1) {
-    $element['#title'] = check_plain($instance['label']);
-    $element['#title_display'] = 'invisible';
+  // Add image field specific validators.
+  if ($field['type'] == 'image') {
+    if ($field_settings['min_resolution'] || $field_settings['max_resolution']) {
+      $element['#media_options']['global']['min_resolution'] = $field_settings['min_resolution'];
+      $element['#media_options']['global']['max_resolution'] = $field_settings['max_resolution'];
+    }
+  }
+
+  if ($field['cardinality'] == 1) {
+    // Set the default value.
+    $element['#default_value'] = !empty($items) ? $items[0] : $defaults;
+    // If there's only one field, return it as delta 0.
+    if (empty($element['#default_value']['fid'])) {
+      $element['#description'] = theme('media_upload_help', array('description' => $element['#description']));
+    }
+    $elements = array($element);
+  }
+  else {
+    // If there are multiple values, add an element for each existing one.
+    foreach ($items as $item) {
+      $elements[$delta] = $element;
+      $elements[$delta]['#default_value'] = $item;
+      $elements[$delta]['#weight'] = $delta;
+      $delta++;
+    }
+    // And then add one more empty row for new uploads except when this is a
+    // programmed form as it is not necessary.
+    if (($field['cardinality'] == FIELD_CARDINALITY_UNLIMITED || $delta < $field['cardinality']) && empty($form_state['programmed'])) {
+      $elements[$delta] = $element;
+      $elements[$delta]['#default_value'] = $defaults;
+      $elements[$delta]['#weight'] = $delta;
+      $elements[$delta]['#required'] = ($element['#required'] && $delta == 0);
+    }
+    // The group of elements all-together need some extra functionality
+    // after building up the full list (like draggable table rows).
+    $elements['#file_upload_delta'] = $delta;
+    $elements['#theme'] = 'media_widget_multiple';
+    $elements['#theme_wrappers'] = array('fieldset');
+    $elements['#process'] = array('media_field_widget_process_multiple');
+    $elements['#title'] = $element['#title'];
+    $elements['#description'] = $element['#description'];
+    $elements['#field_name'] = $element['#field_name'];
+    $elements['#language'] = $element['#language'];
+    $elements['#display_field'] = $field['settings']['display_field'];
+
+    // Add some properties that will eventually be added to the media upload
+    // field. These are added here so that they may be referenced easily through
+    // a hook_form_alter().
+    $elements['#file_upload_title'] = t('Attach media');
+    $elements['#file_upload_description'] = theme('media_upload_help', array('description' => ''));
+  }
+
+  return $elements;
+}
+
+/**
+ * The #value_callback for the media field element.
+ */
+function media_field_widget_value($element, $input = FALSE, $form_state) {
+  if ($input) {
+    // Checkboxes lose their value when empty.
+    // If the display field is present make sure its unchecked value is saved.
+    $field = field_widget_field($element, $form_state);
+    if (empty($input['display'])) {
+      $input['display'] = $field['settings']['display_field'] ? 0 : 1;
+    }
   }
 
-  if ($field['type'] == 'file') {
+  // We depend on the media element to handle uploads.
+  $return = media_file_value($element, $input, $form_state);
+
+  // Ensure that all the required properties are returned even if empty.
+  $return += array(
+    'fid' => 0,
+    'display' => 1,
+    'description' => '',
+  );
+
+  return $return;
+}
+
+/**
+ * An element #process callback for the media field type.
+ *
+ * Expands the media type to include the description and display fields.
+ */
+function media_field_widget_process($element, &$form_state, $form) {
+  $item = $element['#value'];
+  $item['fid'] = $element['fid']['#value'];
+
+  $field = field_widget_field($element, $form_state);
+  $instance = field_widget_instance($element, $form_state);
+  $settings = $instance['widget']['settings'];
+
+  $element['#theme'] = 'media_widget';
+
+  // Add the display field if enabled.
+  if (!empty($field['settings']['display_field']) && $item['fid']) {
     $element['display'] = array(
-      '#type' => 'value',
-      '#value' => 1,
+      '#type' => empty($item['fid']) ? 'hidden' : 'checkbox',
+      '#title' => t('Include file in display'),
+      '#value' => isset($item['display']) ? $item['display'] : $field['settings']['display_default'],
+      '#attributes' => array('class' => array('file-display')),
+    );
+  }
+  else {
+    $element['display'] = array(
+      '#type' => 'hidden',
+      '#value' => '1',
     );
   }
 
-  // Add image field specific validators.
-  if ($field['type'] == 'image') {
-    if ($field_settings['min_resolution'] || $field_settings['max_resolution']) {
-      $element['#media_options']['global']['min_resolution'] = $field_settings['min_resolution'];
-      $element['#media_options']['global']['max_resolution'] = $field_settings['max_resolution'];
+  // Add the description field if enabled.
+  if (!empty($instance['settings']['description_field']) && $item['fid']) {
+    $element['description'] = array(
+      '#type' => variable_get('file_description_type', 'textfield'),
+      '#title' => t('Description'),
+      '#value' => isset($item['description']) ? $item['description'] : '',
+      '#maxlength' => variable_get('file_description_length', 128),
+      '#description' => t('The description may be used as the label of the link to the file.'),
+    );
+  }
+
+  // Adjust the Ajax settings so that on upload and remove of any individual
+  // file, the entire group of file fields is updated together.
+  if ($field['cardinality'] != 1) {
+    $parents = array_slice($element['#array_parents'], 0, -1);
+    $new_path = 'media/ajax/' . implode('/', $parents) . '/' . $form['form_build_id']['#value'];
+    $field_element = drupal_array_get_nested_value($form, $parents);
+    $new_wrapper = $field_element['#id'] . '-ajax-wrapper';
+    foreach (element_children($element) as $key) {
+      if (isset($element[$key]['#ajax'])) {
+        $element[$key]['#ajax']['path'] = $new_path;
+        $element[$key]['#ajax']['wrapper'] = $new_wrapper;
+      }
+    }
+    unset($element['#prefix'], $element['#suffix']);
+  }
+
+  // Add another submit handler to the upload and remove buttons, to implement
+  // functionality needed by the field widget. This submit handler, along with
+  // the rebuild logic in media_field_widget_form() requires the entire field,
+  // not just the individual item, to be valid.
+  foreach (array('attach_button', 'remove_button') as $key) {
+    $element[$key]['#submit'][] = 'media_field_widget_submit';
+    $element[$key]['#limit_validation_errors'] = array(array_slice($element['#parents'], 0, -1));
+  }
+
+  return $element;
+}
+
+/**
+ * An element #process callback for a group of media fields.
+ *
+ * Adds the weight field to each row so it can be ordered and adds a new Ajax
+ * wrapper around the entire group so it can be replaced all at once.
+ */
+function media_field_widget_process_multiple($element, &$form_state, $form) {
+  $element_children = element_children($element, TRUE);
+  $count = count($element_children);
+
+  foreach ($element_children as $delta => $key) {
+    if ($key != $element['#file_upload_delta']) {
+      $description = _media_field_get_description_from_element($element[$key]);
+      $element[$key]['_weight'] = array(
+        '#type' => 'weight',
+        '#title' => $description ? t('Weight for @title', array('@title' => $description)) : t('Weight for new file'),
+        '#title_display' => 'invisible',
+        '#delta' => $count,
+        '#default_value' => $delta,
+      );
+    }
+    else {
+      // The title needs to be assigned to the attach field so that validation
+      // errors include the correct widget label.
+      $element[$key]['#title'] = $element['#title'];
+      $element[$key]['_weight'] = array(
+        '#type' => 'hidden',
+        '#default_value' => $delta,
+      );
     }
   }
 
+  // Add a new wrapper around all the elements for Ajax replacement.
+  $element['#prefix'] = '<div id="' . $element['#id'] . '-ajax-wrapper">';
+  $element['#suffix'] = '</div>';
+
   return $element;
 }
 
 /**
- * Widget value.
+ * Retrieves the file description from a media field element.
  *
- * @todo Is this function ever called? If not, remove it. The Field API now
- *   supports automatic serialization / unserialization, so this should no
- *   longer be needed. After verifying with a module that uses the 'data'
- *   column, remove this.
+ * This helper function is used by media_field_widget_process_multiple().
  *
+ * @param $element
+ *   The element being processed.
+ *
+ * @return
+ *   A description of the file suitable for use in the administrative interface.
+ */
+function _media_field_get_description_from_element($element) {
+  // Use the actual file description, if it's available.
+  if (!empty($element['#default_value']['description'])) {
+    return $element['#default_value']['description'];
+  }
+  // Otherwise, fall back to the filename.
+  if (!empty($element['#default_value']['filename'])) {
+    return $element['#default_value']['filename'];
+  }
+  // This is probably a newly uploaded file; no description is available.
+  return FALSE;
+}
+
+/**
+ * Form submission handler for attach/remove button of media_field_widget_form().
+ *
+ * This runs in addition to and after media_field_widget_submit().
+ *
+ * @see media_field_widget_submit()
  * @see media_field_widget_form()
+ * @see media_field_widget_process()
+ */
+function media_field_widget_submit($form, &$form_state) {
+  // During the form rebuild, media_field_widget_form() will create field item
+  // widget elements using re-indexed deltas, so clear out $form_state['input']
+  // to avoid a mismatch between old and new deltas. The rebuilt elements will
+  // have #default_value set appropriately for the current state of the field,
+  // so nothing is lost in doing this.
+  $parents = array_slice($form_state['triggering_element']['#parents'], 0, -2);
+  drupal_array_set_nested_value($form_state['input'], $parents, NULL);
+
+  $button = $form_state['triggering_element'];
+
+  // Go one level up in the form, to the widgets container.
+  $element = drupal_array_get_nested_value($form, array_slice($button['#array_parents'], 0, -1));
+  $field_name = $element['#field_name'];
+  $langcode = $element['#language'];
+  $parents = $element['#field_parents'];
+
+  $submitted_values = drupal_array_get_nested_value($form_state['values'], array_slice($button['#parents'], 0, -2));
+  foreach ($submitted_values as $delta => $submitted_value) {
+    if (!$submitted_value['fid']) {
+      unset($submitted_values[$delta]);
+    }
+  }
+
+  // Re-index deltas after removing empty items.
+  $submitted_values = array_values($submitted_values);
+
+  // Update form_state values.
+  drupal_array_set_nested_value($form_state['values'], array_slice($button['#parents'], 0, -2), $submitted_values);
+
+  // Update items.
+  $field_state = field_form_get_state($parents, $field_name, $langcode, $form_state);
+  $field_state['items'] = $submitted_values;
+  field_form_set_state($parents, $field_name, $langcode, $form_state, $field_state);
+}
+
+/**
+ * Returns HTML for an individual media widget.
+ *
+ * @param $variables
+ *   An associative array containing:
+ *   - element: A render element representing the widget.
+ *
+ * @ingroup themeable
+ */
+function theme_media_widget($variables) {
+  $element = $variables['element'];
+  $output = '';
+
+  // The "form-media" class is required for proper Ajax functionality.
+  $output .= '<div id="' . $element['#id'] . '" class="media-widget form-media clearfix">';
+  $output .= drupal_render_children($element);
+  $output .= '</div>';
+
+  return $output;
+}
+
+/**
+ * Returns HTML for a group of media widgets.
+ *
+ * @param $variables
+ *   An associative array containing:
+ *   - element: A render element representing the widgets.
+ *
+ * @ingroup themeable
  */
-function media_field_widget_value($element, $input, $form_state) {
-  $return = $input;
+function theme_media_widget_multiple($variables) {
+  $element = $variables['element'];
+
+  // Special ID and classes for draggable tables.
+  $weight_class = $element['#id'] . '-weight';
+  $table_id = $element['#id'] . '-table';
 
-  if (!is_array($return)) {
-    $return = array();
+  // Build up a table of applicable fields.
+  $headers = array();
+  $headers[] = t('File information');
+  if ($element['#display_field']) {
+    $headers[] = array(
+      'data' => t('Display'),
+      'class' => array('checkbox'),
+    );
   }
+  $headers[] = t('Weight');
+  $headers[] = t('Operations');
 
-  if (isset($return['data'])) {
-    $return['data'] = serialize($return['data']);
+  // Get our list of widgets in order (needed when the form comes back after
+  // preview or failed validation).
+  $widgets = array();
+  foreach (element_children($element) as $key) {
+    $widgets[] = &$element[$key];
   }
+  usort($widgets, '_field_sort_items_value_helper');
 
-  $return += array(
-    'fid' => 0,
-    'title' => '',
-    'data' => NULL,
+  $rows = array();
+  foreach ($widgets as $key => &$widget) {
+    // Save the uploading row for last.
+    if ($widget['#file'] == FALSE) {
+      $widget['#title'] = $element['#file_upload_title'];
+      $widget['#description'] = $element['#file_upload_description'];
+      continue;
+    }
+
+    // Delay rendering of the buttons, so that they can be rendered later in the
+    // "operations" column.
+    $operations_elements = array();
+    foreach (element_children($widget) as $sub_key) {
+      if (isset($widget[$sub_key]['#type']) && $widget[$sub_key]['#type'] == 'submit') {
+        hide($widget[$sub_key]);
+        $operations_elements[] = &$widget[$sub_key];
+      }
+    }
+
+    // Delay rendering of the "Display" option and the weight selector, so that
+    // each can be rendered later in its own column.
+    if ($element['#display_field']) {
+      hide($widget['display']);
+    }
+    hide($widget['_weight']);
+
+    // Render everything else together in a column, without the normal wrappers.
+    $widget['#theme_wrappers'] = array();
+    $information = drupal_render($widget);
+
+    // Render the previously hidden elements, using render() instead of
+    // drupal_render(), to undo the earlier hide().
+    $operations = '';
+    foreach ($operations_elements as $operation_element) {
+      $operations .= render($operation_element);
+    }
+    $display = '';
+    if ($element['#display_field']) {
+      unset($widget['display']['#title']);
+      $display = array(
+        'data' => render($widget['display']),
+        'class' => array('checkbox'),
+      );
+    }
+    $widget['_weight']['#attributes']['class'] = array($weight_class);
+    $weight = render($widget['_weight']);
+
+    // Arrange the row with all of the rendered columns.
+    $row = array();
+    $row[] = $information;
+    if ($element['#display_field']) {
+      $row[] = $display;
+    }
+    $row[] = $weight;
+    $row[] = $operations;
+    $rows[] = array(
+      'data' => $row,
+      'class' => isset($widget['#attributes']['class']) ? array_merge($widget['#attributes']['class'], array('draggable')) : array('draggable'),
+    );
+  }
+
+  drupal_add_tabledrag($table_id, 'order', 'sibling', $weight_class);
+
+  $output = '';
+  $output = empty($rows) ? '' : theme('table', array('header' => $headers, 'rows' => $rows, 'attributes' => array('id' => $table_id)));
+  $output .= drupal_render_children($element);
+  return $output;
+}
+
+/**
+ * Returns HTML for help text.
+ *
+ * @param $variables
+ *   An associative array containing:
+ *   - description: The normal description for this field, specified by the
+ *     user.
+ *
+ * @ingroup themeable
+ */
+function theme_media_upload_help($variables) {
+  $description = $variables['description'];
+
+  $descriptions = array();
+
+  if (strlen($description)) {
+    $descriptions[] = $description;
+  }
+
+  return implode('<br />', $descriptions);
+}
+
+/**
+ * Implements hook_field_formatter_info().
+ *
+ * Provides legacy support for the "Large filetype icon" file field formatter.
+ * This was originally used when media entities contained file fields. The
+ * current file entity architecture no longer needs this, but people may
+ * have used this formatter for other file fields on their website.
+ *
+ * @todo Some day, remove this.
+ */
+function media_field_formatter_info() {
+  $formatters = array(
+    'media_large_icon' => array(
+      'label' => t('Large filetype icon'),
+      'field types' => array('file'),
+    ),
   );
+  return $formatters;
+}
 
-  return $return;
+/**
+ * Implements hook_field_formatter_view().
+ *
+ * Legacy support for the "Large filetype icon" file field formatter.
+ * @see media_field_formatter_info()
+ */
+function media_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
+  $element = array();
+
+  if ($display['type'] == 'media_large_icon') {
+    // Use the media_thumbnail image style so that the output in media browser
+    // is consistent.
+    foreach ($items as $delta => $item) {
+      $element[$delta] = array(
+        '#theme' => 'media_formatter_large_icon',
+        '#file' => (object) $item,
+      );
+    }
+  }
+
+  return $element;
 }
diff --git a/drupal7/sites/all/modules/media/includes/media.filter.inc b/drupal7/sites/all/modules/media/includes/media.filter.inc
deleted file mode 100644
index 19362325..00000000
--- a/drupal7/sites/all/modules/media/includes/media.filter.inc
+++ /dev/null
@@ -1,782 +0,0 @@
-<?php
-
-/**
- * @file
- * Functions related to the WYSIWYG editor and the media input filter.
- *
- * @TODO: Rename this file?
- */
-
-define('MEDIA_TOKEN_REGEX', '/\[\[.*?\]\]/s');
-define('MEDIA_TOKEN_REGEX_ALT', '/%7B.*?%7D/s');
-
-/**
- * Implements hook_wysiwyg_include_directory().
- */
-function media_wysiwyg_include_directory($type) {
-  switch ($type) {
-    case 'plugins':
-      return 'wysiwyg_plugins';
-
-    break;
-  }
-}
-
-/**
- * Implements hook_field_attach_insert().
- *
- * Track file usage for media files included in formatted text. Note that this
- * is heavy-handed, and should be replaced when Drupal's filter system is
- * context-aware.
- */
-function media_field_attach_insert($entity_type, $entity) {
-  _media_filter_add_file_usage_from_fields($entity_type, $entity);
-}
-
-/**
- * Implements hook_field_attach_update().
- *
- * @see media_field_attach_insert().
- */
-function media_field_attach_update($entity_type, $entity) {
-  _media_filter_add_file_usage_from_fields($entity_type, $entity);
-}
-
-/**
- * Add file usage from file references in an entity's text fields.
- */
-function _media_filter_add_file_usage_from_fields($entity_type, $entity) {
-  // Track the total usage for files from all fields combined.
-  $entity_files = media_entity_field_count_files($entity_type, $entity);
-
-  list($entity_id, $entity_vid, $entity_bundle) = entity_extract_ids($entity_type, $entity);
-
-  // When an entity has revisions and then is saved again NOT as new version the
-  // previous revision of the entity has be loaded to get the last known good
-  // count of files. The saved data is compared against the last version
-  // so that a correct file count can be created for that (the current) version
-  // id. This code may assume some things about entities that are only true for
-  // node objects. This should be reviewed.
-  // @TODO this conditional can probably be condensed
-  if (empty($entity->revision) && empty($entity->old_vid) && empty($entity->is_new) && ! empty($entity->original)) {
-    $old_files = media_entity_field_count_files($entity_type, $entity->original);
-    foreach ($old_files as $fid => $old_file_count) {
-      // Were there more files on the node just prior to saving?
-      if (empty($entity_files[$fid])) {
-        $entity_files[$fid] = 0;
-      }
-      if ($old_file_count > $entity_files[$fid]) {
-        $deprecate = $old_file_count - $entity_files[$fid];
-        // Now deprecate this usage
-        $file = file_load($fid);
-        if ($file) {
-          file_usage_delete($file, 'media', $entity_type, $entity_id, $deprecate);
-        }
-        // Usage is deleted, nothing more to do with this file
-        unset($entity_files[$fid]);
-      }
-      // There are the same number of files, nothing to do
-      elseif ($entity_files[$fid] ==  $old_file_count) {
-        unset($entity_files[$fid]);
-      }
-      // There are more files now, adjust the difference for the greater number.
-      // file_usage incrementing will happen below.
-      else {
-        // We just need to adjust what the file count will account for the new
-        // images that have been added since the increment process below will
-        // just add these additional ones in
-        $entity_files[$fid] = $entity_files[$fid] - $old_file_count;
-      }
-    }
-  }
-
-  // Each entity revision counts for file usage. If versions are not enabled
-  // the file_usage table will have no entries for this because of the delete
-  // query above.
-  foreach ($entity_files as $fid => $entity_count) {
-    if ($file = file_load($fid)) {
-      file_usage_add($file, 'media', $entity_type, $entity_id, $entity_count);
-    }
-  }
-
-}
-
-/**
- * Parse file references from an entity's text fields and return them as an array.
- */
-function media_filter_parse_from_fields($entity_type, $entity) {
-  $file_references = array();
-
-  foreach (_media_filter_fields_with_text_filtering($entity_type, $entity) as $field_name) {
-    if ($field_items = field_get_items($entity_type, $entity, $field_name)) {
-      foreach ($field_items as $field_item) {
-        preg_match_all(MEDIA_TOKEN_REGEX, $field_item['value'], $matches);
-        foreach ($matches[0] as $tag) {
-          $tag = str_replace(array('[[', ']]'), '', $tag);
-          $tag_info = drupal_json_decode($tag);
-          if (isset($tag_info['fid']) && $tag_info['type'] == 'media') {
-            $file_references[] = $tag_info;
-          }
-        }
-
-        preg_match_all(MEDIA_TOKEN_REGEX_ALT, $field_item['value'], $matches_alt);
-        foreach ($matches_alt[0] as $tag) {
-          $tag = urldecode($tag);
-          $tag_info = drupal_json_decode($tag);
-          if (isset($tag_info['fid']) && $tag_info['type'] == 'media') {
-            $file_references[] = $tag_info;
-          }
-        }
-      }
-    }
-  }
-
-  return $file_references;
-}
-
-/**
- * Returns an array containing the names of all fields that perform text filtering.
- */
-function _media_filter_fields_with_text_filtering($entity_type, $entity) {
-  list($entity_id, $revision_id, $bundle) = entity_extract_ids($entity_type, $entity);
-  $fields = field_info_instances($entity_type, $bundle);
-
-  // Get all of the fields on this entity that allow text filtering.
-  $fields_with_text_filtering = array();
-  foreach ($fields as $field_name => $field) {
-    if (!empty($field['settings']['text_processing'])) {
-      $fields_with_text_filtering[] = $field_name;
-    }
-  }
-
-  return $fields_with_text_filtering;
-}
-
-/**
- * Utility function to get the file count in this entity
- *
- * @param type $entity
- * @param type $entity_type
- * @return int
- */
-function media_entity_field_count_files($entity_type, $entity) {
-  $entity_files = array();
-  foreach (media_filter_parse_from_fields($entity_type, $entity) as $file_reference) {
-    if (empty($entity_files[$file_reference['fid']])) {
-      $entity_files[$file_reference['fid']] = 1;
-    }
-    else {
-      $entity_files[$file_reference['fid']]++;
-    }
-  }
-  return $entity_files;
-}
-
-/**
- * Implements hook_entity_delete().
- */
-function media_entity_delete($entity, $type) {
-  list($entity_id) = entity_extract_ids($type, $entity);
-
-  db_delete('file_usage')
-    ->condition('module', 'media')
-    ->condition('type', $type)
-    ->condition('id', $entity_id)
-    ->execute();
-}
-
-/**
- * Implements hook_field_attach_delete_revision().
- *
- * @param type $entity_type
- * @param type $entity
- */
-function media_field_attach_delete_revision($entity_type, $entity) {
-  list($entity_id) = entity_extract_ids($entity_type, $entity);
-  $files = media_entity_field_count_files($entity_type, $entity);
-  foreach ($files as $fid => $count) {
-    if ($file = file_load($fid)) {
-      file_usage_delete($file, 'media', $entity_type , $entity_id, $count);
-    }
-  }
-}
-
-/**
- * Filter callback for media markup filter.
- *
- * @TODO check for security probably pass text through filter_xss
- */
-function media_filter($text) {
-  $text = preg_replace_callback(MEDIA_TOKEN_REGEX, 'media_token_to_markup', $text);
-  return $text;
-}
-
-/**
- * Parses the contents of a CSS declaration block.
- *
- * @param string $declarations
- *   One or more CSS declarations delimited by a semicolon. The same as a CSS
- *   declaration block (see http://www.w3.org/TR/CSS21/syndata.html#rule-sets),
- *   but without the opening and closing curly braces. Also the same as the
- *   value of an inline HTML style attribute.
- *
- * @return array
- *   A keyed array. The keys are CSS property names, and the values are CSS
- *   property values.
- */
-function media_parse_css_declarations($declarations) {
-  $properties = array();
-  foreach (array_map('trim', explode(";", $declarations)) as $declaration) {
-    if ($declaration != '') {
-      list($name, $value) = array_map('trim', explode(':', $declaration, 2));
-      $properties[strtolower($name)] = $value;
-    }
-  }
-  return $properties;
-}
-
-/**
- * Replace callback to convert a media file tag into HTML markup.
- *
- * @param string $match
- *   Takes a match of tag code
- * @param bool $wysiwyg
- *   Set to TRUE if called from within the WYSIWYG text area editor.
- *
- * @return string
- *   The HTML markup representation of the tag, or an empty string on failure.
- *
- * @see media_get_file_without_label()
- * @see hook_media_token_to_markup_alter()
- */
-function media_token_to_markup($match, $wysiwyg = FALSE) {
-  $settings = array();
-  $match = str_replace("[[", "", $match);
-  $match = str_replace("]]", "", $match);
-  $tag = $match[0];
-
-  try {
-    if (!is_string($tag)) {
-      throw new Exception('Unable to find matching tag');
-    }
-
-    $tag_info = drupal_json_decode($tag);
-
-    if (!isset($tag_info['fid'])) {
-      throw new Exception('No file Id');
-    }
-
-    // Ensure the 'link_text' key is always defined.
-    if (!isset($tag_info['link_text'])) {
-      $tag_info['link_text'] = NULL;
-    }
-
-    // Ensure a valid view mode is being requested.
-    if (!isset($tag_info['view_mode'])) {
-      $tag_info['view_mode'] = variable_get('media__wysiwyg_default_view_mode', 'full');
-    }
-    elseif ($tag_info['view_mode'] != 'default') {
-      $file_entity_info = entity_get_info('file');
-      if (!in_array($tag_info['view_mode'], array_keys($file_entity_info['view modes']))) {
-        // Media 1.x defined some old view modes that have been superseded by
-        // more semantically named ones in File Entity. The media_update_7203()
-        // function updates field settings that reference the old view modes,
-        // but it's impractical to update all text content, so adjust
-        // accordingly here.
-        static $view_mode_updates = array(
-          'media_preview' => 'preview',
-          'media_small' => 'teaser',
-          'media_large' => 'full',
-        );
-        if (isset($view_mode_updates[$tag_info['view_mode']])) {
-          $tag_info['view_mode'] = $view_mode_updates[$tag_info['view_mode']];
-        }
-        else {
-          throw new Exception('Invalid view mode');
-        }
-      }
-    }
-
-    $file = file_load($tag_info['fid']);
-    if (!$file) {
-      throw new Exception('Could not load media object');
-    }
-    $tag_info['file'] = $file;
-
-    // The class attributes is a string, but drupal requires it to be
-    // an array, so we fix it here.
-    if (!empty($tag_info['attributes']['class'])) {
-      $tag_info['attributes']['class'] = explode(" ", $tag_info['attributes']['class']);
-    }
-
-    // Grab the potentially overrided fields from the file.
-    $fields = media_filter_field_parser($tag_info);
-
-    $attributes = is_array($tag_info['attributes']) ? $tag_info['attributes'] : array();
-    $attribute_whitelist = variable_get('media__wysiwyg_allowed_attributes', array('height', 'width', 'hspace', 'vspace', 'border', 'align', 'style', 'class', 'id', 'usemap', 'data-picture-group', 'data-picture-align'));
-    $settings['attributes'] = array_intersect_key($attributes, array_flip($attribute_whitelist));
-    $settings['fields'] = $fields;
-
-    if (!empty($tag_info['attributes']) && is_array($tag_info['attributes'])) {
-      $attribute_whitelist = variable_get('media__wysiwyg_allowed_attributes', array('height', 'width', 'hspace', 'vspace', 'border', 'align', 'style', 'class', 'id', 'usemap', 'data-picture-group', 'data-picture-align'));
-      $settings['attributes'] = array_intersect_key($tag_info['attributes'], array_flip($attribute_whitelist));
-      $settings['fields'] = $fields;
-
-      // Many media formatters will want to apply width and height independently
-      // of the style attribute or the corresponding HTML attributes, so pull
-      // these two out into top-level settings. Different WYSIWYG editors have
-      // different behavior with respect to whether they store user-specified
-      // dimensions in the HTML attributes or the style attribute - check both.
-      // Per http://www.w3.org/TR/html5/the-map-element.html#attr-dim-width, the
-      // HTML attributes are merely hints: CSS takes precedence.
-      if (isset($settings['attributes']['style'])) {
-        $css_properties = media_parse_css_declarations($settings['attributes']['style']);
-        foreach (array('width', 'height') as $dimension) {
-          if (isset($css_properties[$dimension]) && substr($css_properties[$dimension], -2) == 'px') {
-            $settings[$dimension] = substr($css_properties[$dimension], 0, -2);
-          }
-          elseif (isset($settings['attributes'][$dimension])) {
-            $settings[$dimension] = $settings['attributes'][$dimension];
-          }
-        }
-      }
-    }
-  }
-  catch (Exception $e) {
-    watchdog('media', 'Unable to render media from %tag. Error: %error', array('%tag' => $tag, '%error' => $e->getMessage()));
-    return '';
-  }
-
-  // If the tag has link text stored with it, override the filename with it for
-  // the rest of this function, so that if the file is themed as a link, the
-  // desired text will be used (see, for example, theme_file_link()).
-  // @todo: Try to find a less hacky way to do this.
-  if (isset($tag_info['link_text'])) {
-    // The link text will have characters such as "&" encoded for HTML, but the
-    // filename itself needs the raw value when it is used to build the link,
-    // in order to avoid double encoding.
-    $file->filename = decode_entities($tag_info['link_text']);
-  }
-
-  if ($wysiwyg) {
-    $settings['wysiwyg'] = $wysiwyg;
-    // If sending markup to a WYSIWYG, we need to pass the file infomation so
-    // that a inline macro can be generated when the WYSIWYG is detached.
-    // The WYSIWYG plugin is expecting this information in the format of a
-    // urlencoded JSON string stored in the data-file_info attribute of the
-    // element.
-    $element = media_get_file_without_label($file, $tag_info['view_mode'], $settings);
-    $data = drupal_json_encode(array(
-      'type' => 'media',
-      'fid' => $file->fid,
-      'view_mode' => $tag_info['view_mode'],
-      'link_text' => $tag_info['link_text'],
-    ));
-    $element['#attributes']['data-file_info'] = urlencode($data);
-    $element['#attributes']['class'][] = 'media-element';
-  }
-  else {
-    // Display the field elements.
-    $element = array();
-    $element['content']['file'] = media_get_file_without_label($file, $tag_info['view_mode'], $settings);
-    // Overwrite or set the file #alt attribute if it has been set in this
-    // instance.
-    if (!empty($element['content']['file']['#attributes']['alt'])) {
-      $element['content']['file']['#alt'] = $element['content']['file']['#attributes']['alt'];
-    }
-    // Overwrite or set the file #title attribute if it has been set in this
-    // instance.
-    if (!empty($element['content']['file']['#attributes']['title'])) {
-      $element['content']['file']['#title'] = $element['content']['file']['#attributes']['title'];
-    }
-    field_attach_prepare_view('file', array($file->fid => $file), $tag_info['view_mode']);
-    entity_prepare_view('file', array($file->fid => $file));
-    $element['content'] += field_attach_view('file', $file, $tag_info['view_mode']);
-    if (count(element_children($element['content'])) > 1) {
-      // Add surrounding divs to group them together.
-      // We dont want divs when there are no additional fields to allow files
-      // to display inline with text, without breaking p tags.
-      $element['content']['#type'] = 'container';
-      $element['content']['#attributes']['class'] = array(
-        'media',
-        'media-element-container',
-        'media-' . $element['content']['file']['#view_mode']
-      );
-    }
-  }
-  drupal_alter('media_token_to_markup', $element, $tag_info, $settings);
-  return drupal_render($element);
-}
-
-/**
- * Parse the field array from the collapsed AJAX string.
- */
-function media_filter_field_parser($tag_info) {
-  $fields = array();
-  if (isset($tag_info['fields'])) {
-    foreach($tag_info['fields'] as $field_name => $field_value) {
-      if (strpos($field_name, 'field_') === 0) {
-        $parsed_field = explode('[', str_replace(']', '', $field_name));
-        if(isset($parsed_field[2])) {
-          if(isset($parsed_field[3])) {
-            $fields[$parsed_field[0]][$parsed_field[1]][$parsed_field[2]][$parsed_field[3]] = $field_value;
-          } else {
-            $fields[$parsed_field[0]][$parsed_field[1]][$parsed_field[2]] = $field_value;
-          }
-        } else {
-          $fields[$parsed_field[0]][$parsed_field[1]] = $field_value;
-        }
-      }
-    }
-  }
-  return $fields;
-}
-/**
- * Builds a map of media tags in the element.
- *
- * Builds a map of the media tags in an element that are being rendered to their
- * rendered HTML. The map is stored in JS, so we can transform them when the
- * editor is being displayed.
- */
-function media_pre_render_text_format($element) {
-  // filter_process_format() copies properties to the expanded 'value' child
-  // element.
-  if (!isset($element['format'])) {
-    return $element;
-  }
-
-  $field = &$element['value'];
-  $settings = array(
-    'field' => $field['#id'],
-  );
-
-  $tagmap = _media_generate_tagMap($field['#value']);
-
-  if (isset($tagmap)) {
-    drupal_add_js(array('tagmap' => $tagmap), 'setting');
-  }
-  return $element;
-}
-
-/**
- * Creates map of inline media tags.
- *
- * Generates an array of [inline tags] => <html> to be used in filter
- * replacement and to add the mapping to JS.
- *
- * @param string $text
- *   The String containing text and html markup of textarea
- *
- * @return array
- *   An associative array with tag code as key and html markup as the value.
- *
- * @see media_process_form()
- * @see media_token_to_markup()
- */
-function _media_generate_tagMap($text) {
-  // Making $tagmap static as this function is called many times and
-  // adds duplicate markup for each tag code in Drupal.settings JS,
-  // so in media_process_form it adds something like tagCode:<markup>,
-  // <markup> and when we replace in attach see two duplicate images
-  // for one tagCode. Making static would make function remember value
-  // between function calls. Since media_process_form is multiple times
-  // with same form, this function is also called multiple times.
-  static $tagmap = array();
-  preg_match_all("/\[\[.*?\]\]/s", $text, $matches, PREG_SET_ORDER);
-  foreach ($matches as $match) {
-    // We see if tagContent is already in $tagMap, if not we add it
-    // to $tagmap.  If we return an empty array, we break embeddings of the same
-    // media multiple times.
-    if (empty($tagmap[$match[0]])) {
-      // @TODO: Total HACK, but better than nothing.
-      // We should find a better way of cleaning this up.
-      if ($markup_for_media = media_token_to_markup($match, TRUE)) {
-        $tagmap[$match[0]] = $markup_for_media;
-      }
-      else {
-        $missing = file_create_url(drupal_get_path('module', 'media') . '/images/icons/default/image-x-generic.png');
-        $tagmap[$match[0]] = '<div><img src="' . $missing . '" width="100px" height="100px"/></div>';
-      }
-    }
-  }
-  return $tagmap;
-}
-
-/**
- * Return a list of view modes allowed for a file embedded in the WYSIWYG.
- *
- * @param object $file
- *   A file entity.
- *
- * @return array
- *   An array of view modes that can be used on the file when embedded in the
- *   WYSIWYG.
- */
-function media_get_wysiwyg_allowed_view_modes($file) {
-  $enabled_view_modes = &drupal_static(__FUNCTION__, array());
-
-  // @todo Add more caching for this.
-  if (!isset($enabled_view_modes[$file->type])) {
-    $enabled_view_modes[$file->type] = array();
-
-    // Add the default view mode by default.
-    $enabled_view_modes[$file->type]['default'] = array('label' => t('Default'), 'custom settings' => TRUE);
-
-    $entity_info = entity_get_info('file');
-    $view_mode_settings = field_view_mode_settings('file', $file->type);
-    foreach ($entity_info['view modes'] as $view_mode => $view_mode_info) {
-      // Do not show view modes that don't have their own settings and will
-      // only fall back to the default view mode.
-      if (empty($view_mode_settings[$view_mode]['custom_settings'])) {
-        continue;
-      }
-
-      // Don't present the user with an option to choose a view mode in which
-      // the file is hidden.
-      $extra_fields = field_extra_fields_get_display('file', $file->type, $view_mode);
-      if (empty($extra_fields['file']['visible'])) {
-        continue;
-      }
-
-      // Add the view mode to the list of enabled view modes.
-      $enabled_view_modes[$file->type][$view_mode] = $view_mode_info;
-    }
-  }
-
-  $view_modes = $enabled_view_modes[$file->type];
-  drupal_alter('media_wysiwyg_allowed_view_modes', $view_modes, $file);
-  return $view_modes;
-}
-
-/**
- * Form callback used when embedding media.
- *
- * Allows the user to pick a format for their media file.
- * Can also have additional params depending on the media type.
- */
-function media_format_form($form, $form_state, $file) {
-  $form = array();
-  $form['#media'] = $file;
-
-  // Allow for overrides to the fields.
-  $query_fields = isset($_GET['fields']) ? drupal_json_decode($_GET['fields']) : array();
-  $fields = media_filter_field_parser(array('fields' => $query_fields), $file);
-
-  $view_modes = media_get_wysiwyg_allowed_view_modes($file);
-  $formats = $options = array();
-  foreach ($view_modes as $view_mode => $view_mode_info) {
-    // @TODO: Display more verbose information about which formatter and what it
-    // does.
-    $options[$view_mode] = $view_mode_info['label'];
-    $element = media_get_file_without_label($file, $view_mode, array('wysiwyg' => TRUE));
-
-    // Make a pretty name out of this.
-    $formats[$view_mode] = drupal_render($element);
-  }
-
-  // Add the previews back into the form array so they can be altered.
-  $form['#formats'] = &$formats;
-
-  if (!count($formats)) {
-    throw new Exception('Unable to continue, no available formats for displaying media.');
-    return;
-  }
-
-  // Allow for overrides to the display format.
-  $default_view_mode = is_array($query_fields) && isset($query_fields['format']) ? $query_fields['format'] : variable_get('media__wysiwyg_default_view_mode', 'full');
-  if (!isset($formats[$default_view_mode])) {
-    $default_view_mode = key($formats);
-  }
-
-  // Add the previews by reference so that they can easily be altered by
-  // changing $form['#formats'].
-  $settings['media']['formatFormFormats'] = &$formats;
-  $form['#attached']['js'][] = array('data' => $settings, 'type' => 'setting');
-
-  // Add the required libraries, JavaScript and CSS for the form.
-  $form['#attached']['library'][] = array('media', 'media_base');
-  $form['#attached']['library'][] = array('system', 'form');
-  $form['#attached']['js'][] = drupal_get_path('module', 'media') . '/js/media.format_form.js';
-
-  $form['title'] = array(
-    '#markup' => t('Embedding %filename', array('%filename' => $file->filename)),
-  );
-
-  $preview = media_get_thumbnail_preview($file);
-
-  $form['preview'] = array(
-    '#type' => 'markup',
-    '#title' => check_plain(basename($file->uri)),
-    '#markup' => drupal_render($preview),
-  );
-
-  // These will get passed on to WYSIWYG.
-  $form['options'] = array(
-    '#type' => 'fieldset',
-    '#title' => t('options'),
-  );
-
-  $form['options']['format'] = array(
-    '#type' => 'select',
-    '#title' => t('Display as'),
-    '#options' => $options,
-    '#default_value' => $default_view_mode,
-    '#description' => t('Choose the type of display you would like for this
-      file. Please be aware that files may display differently than they do when
-      they are inserted into an editor.')
-  );
-
-  // Add fields from the file, so that we can override them if neccesary.
-  $form['options']['fields'] = array();
-  foreach ($fields as $field_name => $field_value) {
-    $file->{$field_name} = $field_value;
-  }
-  field_attach_form('file', $file, $form['options']['fields'], $form_state);
-  $instance = field_info_instances('file', $file->type);
-  foreach ($instance as $field_name => $field_value) {
-    if (isset($instance[$field_name]['settings']) && isset($instance[$field_name]['settings']['wysiwyg_override']) && !$instance[$field_name]['settings']['wysiwyg_override']) {
-      unset($form['options']['fields'][$field_name]);
-    }
-  }
-
-  // Similar to a form_alter, but we want this to run first so that
-  // media.types.inc can add the fields specific to a given type (like alt tags
-  // on media). If implemented as an alter, this might not happen, making other
-  // alters not be able to work on those fields.
-  // @todo: We need to pass in existing values for those attributes.
-  drupal_alter('media_format_form_prepare', $form, $form_state, $file);
-
-  if (!element_children($form['options'])) {
-    $form['options']['#attributes'] = array('style' => 'display:none');
-  }
-
-  return $form;
-}
-
-/**
- * Returns a drupal_render() array for just the file portion of a file entity.
- *
- * Optional custom settings can override how the file is displayed.
- */
-function media_get_file_without_label($file, $view_mode, $settings = array()) {
-  $file->override = $settings;
-
-  $element = file_view_file($file, $view_mode);
-
-  // The formatter invoked by file_view_file() can use $file->override to
-  // customize the returned render array to match the requested settings. To
-  // support simple formatters that don't do this, set the element attributes to
-  // what was requested, but not if the formatter applied its own logic for
-  // element attributes.
-  if (!isset($element['#attributes']) && isset($settings['attributes'])) {
-    $element['#attributes'] = $settings['attributes'];
-
-    // While this function may be called for any file type, images are a common
-    // use-case. theme_image() and theme_image_style() require the 'alt'
-    // attribute to be passed separately from the 'attributes' array (see
-    // http://drupal.org/node/999338). Until that's fixed, implement this
-    // special-case logic. Image formatters using other theme functions are
-    // responsible for their own 'alt' attribute handling. See
-    // theme_media_formatter_large_icon() for an example.
-    if (isset($settings['attributes']['alt']) && !isset($element['#alt']) && isset($element['#theme']) && in_array($element['#theme'], array('image', 'image_style'))) {
-      $element['#alt'] = $settings['attributes']['alt'];
-    }
-  }
-
-  return $element;
-}
-
-/**
- * Implements hook_entity_dependencies().
- */
-function media_entity_dependencies($entity, $entity_type) {
-  // Go through all the entity's text fields and add a dependency on any files
-  // that are referenced there.
-  $dependencies = array();
-  foreach (media_filter_parse_from_fields($entity_type, $entity) as $file_reference) {
-    $dependencies[] = array('type' => 'file', 'id' => $file_reference['fid']);
-  }
-  return $dependencies;
-}
-
-/**
- * Implements hook_entity_uuid_load().
- */
-function media_entity_uuid_load(&$entities, $entity_type) {
-  // Go through all the entity's text fields and replace file IDs in media
-  // tokens with the corresponding UUID.
-  foreach ($entities as $entity) {
-    media_filter_replace_tokens_in_all_text_fields($entity_type, $entity, 'media_token_fid_to_uuid');
-  }
-}
-
-/**
- * Implements hook_entity_uuid_presave().
- */
-function media_entity_uuid_presave(&$entity, $entity_type) {
-  // Go through all the entity's text fields and replace UUIDs in media tokens
-  // with the corresponding file ID.
-  media_filter_replace_tokens_in_all_text_fields($entity_type, $entity, 'media_token_uuid_to_fid');
-}
-
-/**
- * Replaces media tokens in an entity's text fields, using the specified callback function.
- */
-function media_filter_replace_tokens_in_all_text_fields($entity_type, $entity, $callback) {
-  $text_field_names = _media_filter_fields_with_text_filtering($entity_type, $entity);
-  foreach ($text_field_names as $field_name) {
-    if (!empty($entity->{$field_name})) {
-      $field = field_info_field($field_name);
-      $all_languages = field_available_languages($entity_type, $field);
-      $field_languages = array_intersect($all_languages, array_keys($entity->{$field_name}));
-      foreach ($field_languages as $language) {
-        if (!empty($entity->{$field_name}[$language])) {
-          foreach ($entity->{$field_name}[$language] as &$item) {
-            $item['value'] = preg_replace_callback(MEDIA_TOKEN_REGEX, $callback, $item['value']);
-          }
-        }
-      }
-    }
-  }
-}
-
-/**
- * Callback to replace file IDs with UUIDs in a media token.
- */
-function media_token_fid_to_uuid($matches) {
-  return _media_token_uuid_replace($matches, 'entity_get_uuid_by_id');
-}
-
-/**
- * Callback to replace UUIDs with file IDs in a media token.
- */
-function media_token_uuid_to_fid($matches) {
-  return _media_token_uuid_replace($matches, 'entity_get_id_by_uuid');
-}
-
-/**
- * Helper function to replace UUIDs with file IDs or vice versa.
- *
- * @param array $matches
- *   An array of matches for media tokens, from a preg_replace_callback()
- *   callback function.
- * @param string $entity_uuid_function
- *   Either 'entity_get_uuid_by_id' (to replace file IDs with UUIDs in the
- *   token) or 'entity_get_id_by_uuid' (to replace UUIDs with file IDs).
- *
- * @return string
- *   A string representing the JSON-encoded token, with the appropriate
- *   replacement between file IDs and UUIDs.
- */
-function _media_token_uuid_replace($matches, $entity_uuid_function) {
-  $tag = $matches[0];
-  $tag = str_replace(array('[[', ']]'), '', $tag);
-  $tag_info = drupal_json_decode($tag);
-  if (isset($tag_info['fid'])) {
-    if ($new_ids = $entity_uuid_function('file', array($tag_info['fid']))) {
-      $new_id = reset($new_ids);
-      $tag_info['fid'] = $new_id;
-    }
-  }
-  return '[[' . drupal_json_encode($tag_info) . ']]';
-}
diff --git a/drupal7/sites/all/modules/media/includes/media.pages.inc b/drupal7/sites/all/modules/media/includes/media.pages.inc
index 28a6d7ee..b22a8b14 100644
--- a/drupal7/sites/all/modules/media/includes/media.pages.inc
+++ b/drupal7/sites/all/modules/media/includes/media.pages.inc
@@ -5,67 +5,6 @@
  * Common pages for the Media module.
  */
 
-
-/**
- * Menu callback; Edit multiple files on the same page using multiform module.
- *
- * @todo When http://drupal.org/node/1227706 is fixed, filter the $files
- * array using file_access($file, 'edit').
- *
- * @see media_file_operation_edit_multiple()
- */
-function media_file_page_edit_multiple($files) {
-  if (empty($files)) {
-    return MENU_ACCESS_DENIED;
-  }
-
-  $forms = array();
-  foreach ($files as $file) {
-    // To maintain unique form_ids, append the file id.
-    $forms[] = array('media_edit_' . $file->fid, $file);
-  }
-
-  $form = call_user_func_array('multiform_get_form', $forms);
-  $form['#attributes']['class'][] = 'media-multiedit-form';
-
-  // Add the title to each 'subform'.
-  foreach (element_children($form['multiform']) as $key) {
-    $fid = $form['multiform'][$key]['fid']['#value'];
-    $file = $files[$fid];
-    $title = t('<em>Edit @type</em> @title', array('@type' => $file->type, '@title' => $file->filename));
-    $form['multiform'][$key]['#prefix'] = '<h2>' . $title . '</h2>';
-    $form['multiform'][$key]['actions']['#access'] = FALSE;
-  }
-
-  if (isset($form['buttons']['Delete'])) {
-    $form['buttons']['Delete']['#access'] = FALSE;
-  }
-
-  // Add a cancel button at the bottom of the form.
-  $form['buttons']['cancel'] = array(
-    '#type' => 'link',
-    '#title' => t('Cancel'),
-    '#weight' => 50,
-  );
-  if (isset($_GET['destination'])) {
-    $form['buttons']['cancel']['#href'] = $_GET['destination'];
-  }
-  else if (user_access('administer files')) {
-    $form['buttons']['cancel']['#href'] = 'admin/content/file';
-  }
-  else {
-    $form['buttons']['cancel']['#href'] = '<front>';
-  }
-
-  // Override the page title since each file form sets a title.
-  drupal_set_title(t('Edit multiple files'));
-
-  // Allow other modules to alter the form.
-  drupal_alter('media_edit_multiple_form', $form);
-
-  return $form;
-}
-
 /**
  * CTools modal callback for editing a file.
  */
@@ -92,196 +31,3 @@ function media_file_edit_modal($form, &$form_state, $file, $js) {
   // Otherwise, just return the output.
   return $output;
 }
-
-/**
- * File type migration page.
- *
- * Allows site administrator to execute migration of old/disabled/deleted
- * file types to new ones.
- */
-function media_upgrade_file_types($form, &$form_state) {
-  $migratable_types = _media_get_migratable_file_types();
-
-  // Silently return if there are no file types that need migration.
-  if (empty($migratable_types)) {
-    return array(
-      'message' => array(
-        '#markup' => t('There are no file types that need migration.'),
-      ),
-    );
-  }
-
-  $form['message'] = array(
-    'message' => array(
-      '#markup' => t('This page allows you to migrate deprecated and/or disabled file types to new ones. It will migrate files from old type to new one and optionally migrate fields and delete old type.'),
-    ),
-  );
-
-  $form['migrate_fields'] = array(
-    '#type' => 'checkbox',
-    '#title' => t('Migrate fields'),
-    '#default_value' => TRUE,
-    '#description' => t('Migrate fields and their values from old file types to new ones.'),
-  );
-  $form['delete_old_type'] = array(
-    '#type' => 'checkbox',
-    '#title' => t('Delete old type'),
-    '#default_value' => FALSE,
-    '#description' => t('Delete old file type if migration was successful and delete operation is possible (type is not exported in code).'),
-  );
-  $form['migrate_mimes'] = array(
-    '#type' => 'checkbox',
-    '#title' => t('Migrate type mime-type'),
-    '#default_value' => TRUE,
-    '#description' => t('Move mime-type from old type to new one.'),
-  );
-
-  $form['upgradable_types'] = array(
-    '#type' => 'fieldset',
-    '#title' => t('Upgradable file types'),
-  );
-
-  $options = array('- ' . t('Do not upgrade') . ' -');
-  foreach (file_type_get_enabled_types() as $type) {
-    $options[$type->type] = $type->label;
-  }
-
-  foreach ($migratable_types as $machine_name) {
-    $type = file_type_load($machine_name);
-    if (!$type) {
-      $type = new stdClass;
-      $type->label = $type->type = $machine_name;
-    }
-    $form['upgradable_types'][$machine_name] = array(
-      '#type' => 'select',
-      '#title' => $type->label,
-      '#options' => $options,
-      '#description' => t(
-        'Select file type which you want to migrate @type to. Select %no_upgrade if type should stay as it is.',
-        array('@type' => $type->label, '%no_upgrade' => '- ' . t('Do not upgrade') . ' -')),
-    );
-  }
-
-  $form['submit'] = array(
-    '#type' => 'submit',
-    '#value' => t('Start migraton'),
-  );
-
-  return $form;
-}
-
-/**
- * File type migration page submit handler.
- */
-function media_upgrade_file_types_submit($form, &$form_state) {
-  $migratable_types = _media_get_migratable_file_types();
-  $migrate = FALSE;
-  foreach ($migratable_types as $type) {
-    if ($form_state['values'][$type]) {
-      $migrate = TRUE;
-      break;
-    }
-  }
-
-  // Return silently if no types were selected for migration.
-  if (!$migrate) {
-    return;
-  }
-
-  // Use confirmation page/form.
-  $query = $form_state['values'];
-  unset($query['op']);
-  unset($query['submit']);
-  unset($query['form_id']);
-  unset($query['form_token']);
-  unset($query['form_build_id']);
-
-  $form_state['redirect'] = array(
-    'admin/structure/file-types/upgrade/confirm',
-    array('query' => $query),
-  );
-}
-
-/**
- * File types migration confirmation page.
- */
-function media_upgrade_file_types_confirm($form, &$form_state) {
-  return confirm_form(
-    $form,
-    t('Do you really want to migrate selected file types?'),
-    'admin/structure/file-types/upgrade',
-    NULL,
-    t('Migrate')
-  );
-}
-
-/**
- * File types migration confirmation page sumit. Executes actual migration.
- */
-function media_upgrade_file_types_confirm_submit($form, &$form_state) {
-  $migratable_types = _media_get_migratable_file_types();
-  foreach ($migratable_types as $type) {
-    if ($_GET[$type] && $bundle_new = file_type_load($_GET[$type])) {
-      // Old bundle might be deleted so let's fake some values.
-      $bundle_old = file_type_load($type);
-      if (empty($bundle_old)) {
-        $bundle_old = new stdClass;
-        $bundle_old->type = $type;
-        $bundle_old->mimetypes = array();
-        $bundle_old->export_type = 2;
-      }
-
-      // Migrate fields to new bundle.
-      if ($_GET['migrate_fields']) {
-        $old_fields = db_select('field_config_instance', 'fc')->fields('fc', array('field_name'))->condition('entity_type',  'file')->condition('bundle', $bundle_old->type)->execute()->fetchCol();
-        $new_fields = db_select('field_config_instance', 'fc')->fields('fc', array('field_name'))->condition('entity_type',  'file')->condition('bundle', $bundle_new->type)->execute()->fetchCol();
-        $fields_to_move = array_diff($old_fields, $new_fields);
-        $fields_to_drop = array_diff($old_fields, $fields_to_move);
-
-        db_update('field_config_instance')
-          ->fields(array('bundle' => $bundle_new->type))
-          ->condition('entity_type',  'file')
-          ->condition('bundle', $bundle_old->type)
-          ->condition('field_name', $fields_to_move, 'IN')
-          ->execute();
-
-        db_delete('field_config_instance')
-          ->condition('entity_type',  'file')
-          ->condition('bundle', $bundle_old->type)
-          ->condition('field_name', $fields_to_drop, 'IN')
-          ->execute();
-
-        field_cache_clear();
-        module_invoke_all('field_attach_rename_bundle', 'file', $bundle_old->type, $bundle_new->type);
-      }
-
-      // Migrate mimetypes to new bundle.
-      if ($_GET['migrate_mimes']) {
-        $changed = FALSE;
-        foreach ($bundle_old->mimetypes as $mime) {
-          if (!file_entity_match_mimetypes($bundle_new->mimetypes, $mime)) {
-            $bundle_new->mimetypes[] = $mime;
-            $changed = TRUE;
-          }
-        }
-
-        if ($changed) {
-          file_type_save($bundle_new);
-        }
-      }
-
-      // Delete old bundle.
-      if ($_GET['delete_old_type'] && $bundle_old->export_type == 1) {
-        file_type_delete($bundle_old);
-      }
-
-      // Migrate files.
-      db_update('file_managed')
-        ->fields(array('type' => $bundle_new->type))
-        ->condition('type', $bundle_old->type)
-        ->execute();
-    }
-  }
-
-  $form_state['redirect'] = 'admin/structure/file-types';
-}
diff --git a/drupal7/sites/all/modules/media/includes/media.theme.inc b/drupal7/sites/all/modules/media/includes/media.theme.inc
index 204cedc7..2b57782e 100644
--- a/drupal7/sites/all/modules/media/includes/media.theme.inc
+++ b/drupal7/sites/all/modules/media/includes/media.theme.inc
@@ -7,28 +7,6 @@
  * Theming functions for the Media module.
  */
 
-
-/**
- * Display a media file list.
- *
- * @param array $element
- *   The form element.
- *
- * @return string
- *   HTML of the file list
- */
-function theme_media_file_list($element) {
-  // Add the CSS for our display.
-  return '<div class="media-file-list">' . theme('form_element', $element, $element['#children']) . '</div>';
-}
-
-/**
- * Add messages to the page.
- */
-function template_preprocess_media_dialog_page(&$variables) {
-  $variables['messages'] = theme('status_messages');
-}
-
 /**
  * Adds a wrapper around a preview of a media file.
  */
@@ -47,11 +25,18 @@ function theme_media_thumbnail($variables) {
 
   // Arguments for the thumbnail link.
   $thumb = $element['#children'];
-  $target = 'file/' . $element['#file']->fid . '/edit';
+  if (file_entity_access('update', $element['#file'])) {
+    $target = 'file/' . $element['#file']->fid . '/edit';
+    $title = t('Click to edit details');
+  }
+  else {
+    $target = 'file/' . $element['#file']->fid;
+    $title = t('Click to view details');
+  }
   $options = array(
     'query' => drupal_get_destination(),
     'html' => TRUE,
-    'attributes' => array('title' => t('Click to edit details')),
+    'attributes' => array('title' => $title),
   );
 
   // Element should be a field renderable array. This should be improved.
@@ -85,7 +70,7 @@ function template_preprocess_media_thumbnail(&$variables) {
  */
 function theme_media_formatter_large_icon($variables) {
   $file = $variables['file'];
-  $icon_dir = variable_get('media__icon_base_directory', 'public://media-icons') . '/' . variable_get('media__icon_set', 'default');
+  $icon_dir = variable_get('media_icon_base_directory', 'public://media-icons') . '/' . variable_get('media_icon_set', 'default');
   $icon = file_icon_path($file, $icon_dir);
   $variables['path'] = $icon;
 
@@ -108,3 +93,10 @@ function theme_media_formatter_large_icon($variables) {
   }
   return $output;
 }
+
+/**
+ * Add messages to the page.
+ */
+function template_preprocess_media_dialog_page(&$variables) {
+  $variables['messages'] = theme('status_messages');
+}
diff --git a/drupal7/sites/all/modules/media/js/media.browser.js b/drupal7/sites/all/modules/media/js/media.browser.js
index c81e7331..d16e52aa 100644
--- a/drupal7/sites/all/modules/media/js/media.browser.js
+++ b/drupal7/sites/all/modules/media/js/media.browser.js
@@ -7,7 +7,6 @@
 namespace('Drupal.media.browser');
 
 Drupal.media.browser.selectedMedia = [];
-Drupal.media.browser.activeTab = 0;
 Drupal.media.browser.mediaAdded = function () {};
 Drupal.media.browser.selectionFinalized = function (selectedMedia) {
   // This is intended to be overridden if a callee wants to be triggered
@@ -24,23 +23,42 @@ Drupal.behaviors.MediaBrowser = {
     }
 
     // Instantiate the tabs.
+    var showFunc = function(event, ui) {
+      // Store index of the tab being activated.
+      if (parent_iframe = Drupal.media.browser.getParentIframe(window)) {
+        $(parent_iframe).attr('current_tab', $('#media-tabs-wrapper > ul > li.ui-state-active').index());
+      }
+    };
+    var activeTab = Drupal.media.browser.tabFromHash();
     $('#media-browser-tabset').tabs({
-      // Ensure that the modal resizes to the content on each tab switch.
-      show: Drupal.media.browser.resizeIframe, // jquery ui < 1.8
-      activate: Drupal.media.browser.resizeIframe // jquery ui >= 1.8
-    });
-
-    $('.ui-tabs-nav li').mouseup(function() {
-      Drupal.media.browser.activeTab = $(this).index();
+      selected: activeTab, // jquery < 1.9
+      active: activeTab, // jquery >= 1.9
+      show: showFunc, // jquery ui < 1.8
+      activate: showFunc // jquery ui >= 1.8
     });
 
     $('.media-browser-tab').each( Drupal.media.browser.validateButtons );
+  }
+  // Wait for additional params to be passed in.
+};
 
-    Drupal.media.browser.selectActiveTab();
-    Drupal.media.browser.selectErrorTab();
+Drupal.media.browser.getParentIframe = function (window) {
+  var arrFrames = parent.document.getElementsByTagName("IFRAME");
+  for (var i = 0; i < arrFrames.length; i++) {
+    if (arrFrames[i].contentWindow === window) {
+      return arrFrames[i];
+    }
+  }
+}
 
+/**
+ * Get index of the active tab from window.location.hash
+ */
+Drupal.media.browser.tabFromHash = function () {
+  if (parent_iframe = Drupal.media.browser.getParentIframe(window)) {
+    return $(parent_iframe).attr('current_tab');
   }
-  // Wait for additional params to be passed in.
+  return 0;
 };
 
 Drupal.media.browser.launch = function () {
@@ -49,17 +67,16 @@ Drupal.media.browser.launch = function () {
 
 Drupal.media.browser.validateButtons = function() {
   // The media browser runs in an IFRAME. The Drupal.media.popups.mediaBrowser()
-  // function sets up the IFRAME and "OK" and "Cancel" buttons that are outside
-  // of the IFRAME, so that their click handlers can destroy the IFRAME while
-  // retaining information about what media items were selected. However,
-  // Drupal UI convention is to place all action buttons on the same "line"
-  // at the bottom of the form, so if the form within the IFRAME contains a
-  // "Submit" button or other action buttons, then the "OK" and "Cancel"
-  // buttons below the IFRAME break this convention and confuse the user.
-  // Therefore, we add "Submit" and "Cancel" buttons inside the IFRAME, and
-  // have their click action trigger the click action of the corresonding
-  // "OK" and "Cancel" buttons that are outside the IFRAME. media.css contains
-  // CSS rules that hide the outside buttons.
+  // function sets up the IFRAME and an "OK" button that is outside of the
+  // IFRAME, so that its click handlers can destroy the IFRAME while retaining
+  // information about what media items were selected. However, Drupal UI
+  // convention is to place all action buttons on the same "line" at the bottom
+  // of the form, so if the form within the IFRAME contains a "Submit" button or
+  // other action buttons, then the "OK" button will appear below the IFRAME
+  // which breaks this convention and is confusing to the user. Therefore, we
+  // add a "Submit" button inside the IFRAME, and have its click action trigger
+  // the click action of the corresponding "OK" button that is outside the
+  // IFRAME. media.css contains CSS rules that hide the outside buttons.
 
   // If a submit button is present, another round-trip to the server is needed
   // before the user's selection is finalized. For these cases, when the form's
@@ -69,24 +86,18 @@ Drupal.media.browser.validateButtons = function() {
   // Drupal.media.popups.mediaBrowser.mediaBrowserOnLoad() auto-triggers the
   // "OK" button action to finalize the selection and remove the IFRAME.
 
-  // We need to check for the fake submit/cancel buttons that are used on
-  // non-form based pane content. On these items we need to bind the clicks
-  // so that media can be selected or the window can be closed. This is still a
-  // hacky approach, but it is a step in the right direction.
+  // We need to check for the fake submit button that is used on non-form based
+  // pane content. On these items we need to bind the clicks so that media can
+  // be selected or the window can be closed. This is still a hacky approach,
+  // but it is a step in the right direction.
 
   $('a.button.fake-submit', this).once().bind('click', Drupal.media.browser.submit);
-  $('a.button.fake-cancel', this).once().bind('click', Drupal.media.browser.submit);
 };
 
 Drupal.media.browser.submit = function () {
   // @see Drupal.media.browser.validateButtons().
   var buttons = $(parent.window.document.body).find('#mediaBrowser').parent('.ui-dialog').find('.ui-dialog-buttonpane button');
-  if ($(this).hasClass('fake-cancel')) {
-    buttons[1].click();
-  }
-  else {
-    buttons[0].click();
-  }
+  buttons[0].click();
 
   // Return false to prevent the fake link "click" from continuing.
   return false;
@@ -105,56 +116,4 @@ Drupal.media.browser.finalizeSelection = function () {
   }
 };
 
-/**
- * Resize the Media Browser to the content height.
- */
-Drupal.media.browser.resizeIframe = function (event) {
-  var h = $('body').height();
-  $(parent.window.document).find('#mediaBrowser').height(h);
-};
-
-Drupal.media.browser.selectErrorTab = function() {
-  // Find the ID of a tab with an error in it
-  var errorTabID = $('#media-browser-tabset')
-    .find('.error')
-    .parents('.media-browser-tab')
-    .attr('id');
-
-  if (errorTabID !== undefined) {
-    // Find the Tab Link with errorTabID
-    var tab = $('a[href="#' + errorTabID + '"]');
-    // Find the index of the tab
-    var index = $('#media-browser-tabset a').index(tab);
-    // Select the tab
-    Drupal.media.browser.selectTab(index);
-  }
-}
-
-Drupal.media.browser.selectActiveTab = function() {
-  // Find the index of the last active tab.
-  setTimeout(function() {
-    Drupal.media.browser.selectTab(Drupal.media.browser.activeTab);
-    Drupal.media.browser.resizeIframe();
-  }, 10);
-};
-
-/**
- * Helper function to change the media browser jQuery UI tabs
- * since it requires two different methods dependingon the version.
- */
-Drupal.media.browser.selectTab = function(index) {
-  var ver = jQuery.ui.version.split('.');
-  if (ver[0] == '1' && parseInt(ver[1]) <= 8) {
-    // jQuery UI <= 1.8
-    $('#media-browser-tabset').tabs('select', index);
-  }
-  else {
-    // jQuery UI 1.9+
-    $('#media-browser-tabset').tabs('option', 'active', index);
-  }
-
-  // Update the active tab variable.
-  Drupal.media.browser.activeTab = index;
-};
-
 }(jQuery));
diff --git a/drupal7/sites/all/modules/media/js/media.filter.js b/drupal7/sites/all/modules/media/js/media.filter.js
deleted file mode 100644
index 29936fd1..00000000
--- a/drupal7/sites/all/modules/media/js/media.filter.js
+++ /dev/null
@@ -1,250 +0,0 @@
-/**
- *  @file
- *  File with utilities to handle media in html editing.
- */
-(function ($) {
-
-  Drupal.media = Drupal.media || {};
-  /**
-   * Utility to deal with media tokens / placeholders.
-   */
-  Drupal.media.filter = {
-    /**
-     * Replaces media tokens with the placeholders for html editing.
-     * @param content
-     */
-    replaceTokenWithPlaceholder: function(content) {
-      var tagmap = Drupal.media.filter.ensure_tagmap(),
-        matches = content.match(/\[\[.*?\]\]/g),
-        media_definition,
-        id = 0;
-
-      if (matches) {
-        var i = 1;
-        for (var macro in tagmap) {
-          var index = $.inArray(macro, matches);
-          if (index !== -1) {
-            var media_json = macro.replace('[[', '').replace(']]', '');
-
-            // Make sure that the media JSON is valid.
-            try {
-              media_definition = JSON.parse(media_json);
-            }
-            catch (err) {
-              media_definition = null;
-            }
-            if (media_definition) {
-              // Apply attributes.
-              var element = Drupal.media.filter.create_element(tagmap[macro], media_definition);
-              var markup = Drupal.media.filter.outerHTML(element);
-
-              content = content.replace(macro, Drupal.media.filter.getWrapperStart(i) + markup + Drupal.media.filter.getWrapperEnd(i));
-            }
-          }
-          i++;
-        }
-      }
-      return content;
-    },
-
-    /**
-     * Replaces the placeholders for html editing with the media tokens to store.
-     * @param content
-     */
-    replacePlaceholderWithToken: function(content) {
-      var tagmap = Drupal.media.filter.ensure_tagmap();
-      var i = 1;
-      for (var macro in tagmap) {
-        var startTag = Drupal.media.filter.getWrapperStart(i), endTag = Drupal.media.filter.getWrapperEnd(i);
-        var startPos = content.indexOf(startTag), endPos = content.indexOf(endTag);
-        if (startPos !== -1 && endPos !== -1) {
-          // If the placeholder wrappers are empty, remove the macro too.
-          if (endPos - startPos - startTag.length === 0) {
-            macro = '';
-          }
-          content = content.substr(0, startPos) + macro + content.substr(endPos + (new String(endTag)).length);
-        }
-        i++;
-      }
-      return content;
-    },
-
-    getWrapperStart: function(i) {
-      return '<!--MEDIA-WRAPPER-START-' + i + '-->';
-    },
-
-    getWrapperEnd: function(i) {
-      return '<!--MEDIA-WRAPPER-END-' + i + '-->';
-    },
-
-    /**
-     * Register new element and returns the placeholder markup.
-     *
-     * @param formattedMedia a formatted media object as given by the onSubmit
-     * function of the media Style popup.
-     * @param fid the file id.
-     *
-     * @return The registered element.
-     */
-    registerNewElement: function (formattedMedia, fid) {
-      var element = Drupal.media.filter.create_element(formattedMedia.html, {
-        fid: fid,
-        view_mode: formattedMedia.type,
-        attributes: formattedMedia.options
-      });
-
-      var markup = Drupal.media.filter.outerHTML(element),
-        macro = Drupal.media.filter.create_macro(element);
-
-      // Store macro/markup pair in the tagmap.
-      Drupal.media.filter.ensure_tagmap();
-      Drupal.settings.tagmap[macro] = markup;
-
-      return element;
-    },
-
-    /**
-     * Serializes file information as a url-encoded JSON object and stores it as a
-     * data attribute on the html element.
-     *
-     * @param html (string)
-     *    A html element to be used to represent the inserted media element.
-     * @param info (object)
-     *    A object containing the media file information (fid, view_mode, etc).
-     */
-    create_element: function (html, info) {
-      if ($('<div></div>').append(html).text().length === html.length) {
-        // Element is not an html tag. Surround it in a span element
-        // so we can pass the file attributes.
-        html = '<span>' + html + '</span>';
-      }
-      var element = $(html);
-
-      // Move attributes from the file info array to the placeholder element.
-      if (info.attributes) {
-        $.each(Drupal.media.filter.allowed_attributes(), function(i, a) {
-          if (info.attributes[a]) {
-            element.attr(a, info.attributes[a]);
-          }
-        });
-        delete(info.attributes);
-      }
-
-      // Important to url-encode the file information as it is being stored in an
-      // html data attribute.
-      info.type = info.type || "media";
-      element.attr('data-file_info', encodeURI(JSON.stringify(info)));
-
-      // Adding media-element class so we can find markup element later.
-      var classes = ['media-element'];
-
-      if(info.view_mode){
-        classes.push('file-' + info.view_mode.replace(/_/g, '-'));
-      }
-      element.addClass(classes.join(' '));
-
-      return element;
-    },
-
-    /**
-     * Create a macro representation of the inserted media element.
-     *
-     * @param element (jQuery object)
-     *    A media element with attached serialized file info.
-     */
-    create_macro: function (element) {
-      var file_info = Drupal.media.filter.extract_file_info(element);
-      if (file_info) {
-        return '[[' + JSON.stringify(file_info) + ']]';
-      }
-      return false;
-    },
-
-    /**
-     * Extract the file info from a WYSIWYG placeholder element as JSON.
-     *
-     * @param element (jQuery object)
-     *    A media element with attached serialized file info.
-     */
-    extract_file_info: function (element) {
-      var file_json = $.data(element, 'file_info') || element.data('file_info'),
-        file_info,
-        value;
-
-      try {
-        file_info = JSON.parse(decodeURIComponent(file_json));
-      }
-      catch (err) {
-        file_info = null;
-      }
-
-      if (file_info) {
-        file_info.attributes = {};
-
-        // Extract whitelisted attributes.
-        $.each(Drupal.media.filter.allowed_attributes(), function(i, a) {
-          if (value = element.attr(a)) {
-            file_info.attributes[a] = value;
-          }
-        });
-        delete(file_info.attributes['data-file_info']);
-      }
-
-      return file_info;
-    },
-
-    /**
-     * Gets the HTML content of an element.
-     *
-     * @param element (jQuery object)
-     */
-    outerHTML: function (element) {
-      return $('<div>').append(element.eq(0).clone()).html();
-    },
-
-    /**
-     * Gets the wrapped HTML content of an element to insert into the wysiwyg.
-     *
-     * It also registers the element in the tag map so that the token
-     * replacement works.
-     *
-     * @param element (jQuery object) The element to insert.
-     *
-     * @see Drupal.media.filter.replacePlaceholderWithToken()
-     */
-    getWysiwygHTML: function (element) {
-      // Create the markup and the macro.
-      var markup = Drupal.media.filter.outerHTML(element),
-        macro = Drupal.media.filter.create_macro(element);
-
-      // Store macro/markup in the tagmap.
-      Drupal.media.filter.ensure_tagmap();
-      var i = 1;
-      for (var key in Drupal.settings.tagmap) {
-        i++;
-      }
-      Drupal.settings.tagmap[macro] = markup;
-
-      // Return the wrapped html code to insert in an editor and use it with
-      // replacePlaceholderWithToken()
-      return Drupal.media.filter.getWrapperStart(i) + markup + Drupal.media.filter.getWrapperEnd(i);
-    },
-
-    /**
-     * Ensures the tag map has been initialized and returns it.
-     */
-    ensure_tagmap: function () {
-      Drupal.settings.tagmap = Drupal.settings.tagmap || {};
-      return Drupal.settings.tagmap;
-    },
-
-    /**
-     * Ensures the wysiwyg_allowed_attributes and returns it.
-     * In case of an error the default settings are returned.
-     */
-    allowed_attributes: function () {
-      Drupal.settings.wysiwyg_allowed_attributes = Drupal.settings.wysiwyg_allowed_attributes || ['height', 'width', 'hspace', 'vspace', 'border', 'align', 'style', 'alt', 'title', 'class', 'id', 'usemap'];
-      return Drupal.settings.wysiwyg_allowed_attributes;
-    }
-  }
-})(jQuery);
diff --git a/drupal7/sites/all/modules/media/js/media.format_form.js b/drupal7/sites/all/modules/media/js/media.format_form.js
deleted file mode 100644
index 6c5196a1..00000000
--- a/drupal7/sites/all/modules/media/js/media.format_form.js
+++ /dev/null
@@ -1,67 +0,0 @@
-
-/**
- *  @file
- *  Attach behaviors to formatter radio select when selecting a media's display
- *  formatter.
- */
-
-(function ($) {
-namespace('Drupal.media.formatForm');
-
-Drupal.media.mediaFormatSelected = {};
-
-Drupal.behaviors.mediaFormatForm = {
-  attach: function (context, settings) {
-
-    // Add "Submit" and "Cancel" buttons inside the IFRAME that trigger the
-    // behavior of the hidden "OK" and "Cancel" buttons that are outside the
-    // IFRAME. See Drupal.media.browser.validateButtons() for more details.
-
-    // @note I think this should be handled in media.browser.js in
-    //       Drupal.media.browser.validateButtons but I'm not sure how crufty
-    //       this particular functionality is. We should evaluate if it is still
-    //       needed.
-
-    // @TODO can these be added to the content being displayed via form_alter?
-
-    // Adding the buttons should only be done once in order to prevent multiple
-    // buttons from being added if part of the form is updated via AJAX
-    $('#media-format-form').once('format', function() {
-      $('<a class="button fake-ok">' + Drupal.t('Submit') + '</a>').appendTo($('#media-format-form')).bind('click', Drupal.media.formatForm.submit);
-      $('<a class="button fake-cancel">' + Drupal.t('Cancel') + '</a>').appendTo($('#media-format-form')).bind('click', Drupal.media.formatForm.submit);
-    });
-
-    // Resize the window on load.
-    // @TODO this duplicates Drupal.media.browser.resizeIframe()
-    //       can we put a resize function into media.core.js?
-    $(document).ready(function () {
-      // Get the height and add a bit of padding to acomidate the form buttons.
-      var h = $('body').height() + 20;
-      $(parent.window.document).find('#mediaStyleSelector').height(h);
-    });
-
-  }
-};
-
-Drupal.media.formatForm.getOptions = function () {
-  // Get all the values
-  var ret = {}; $.each($('#media-format-form fieldset#edit-options *').serializeArray(), function (i, field) { ret[field.name] = field.value; });
-  return ret;
-};
-
-Drupal.media.formatForm.getFormattedMedia = function () {
-  var formatType = $("select#edit-format option:selected").val();
-  return { type: formatType, options: Drupal.media.formatForm.getOptions(), html: Drupal.settings.media.formatFormFormats[formatType] };
-};
-
-Drupal.media.formatForm.submit = function () {
-  // @see Drupal.behaviors.mediaFormatForm.attach().
-  var buttons = $(parent.window.document.body).find('#mediaStyleSelector').parent('.ui-dialog').find('.ui-dialog-buttonpane button');
-  if ($(this).hasClass('fake-cancel')) {
-    buttons[1].click();
-  } else {
-    buttons[0].click();
-  }
-}
-
-})(jQuery);
diff --git a/drupal7/sites/all/modules/media/js/media.js b/drupal7/sites/all/modules/media/js/media.js
index 04585bde..5288dd30 100644
--- a/drupal7/sites/all/modules/media/js/media.js
+++ b/drupal7/sites/all/modules/media/js/media.js
@@ -1,97 +1,125 @@
-
 /**
- *  @file
- *  This file handles the JS for Media Module functions.
+ * @file
+ * Provides JavaScript additions to the media field widget.
+ *
+ * This file provides support for launching the media browser to select existing
+ * files and disabling of other media fields during Ajax uploads (which prevents
+ * separate media fields from accidentally attaching files).
  */
 
 (function ($) {
 
 /**
- * Loads media browsers and callbacks, specifically for media as a field.
+ * Attach behaviors to media element browse fields.
  */
 Drupal.behaviors.mediaElement = {
   attach: function (context, settings) {
-    // Options set from media.fields.inc for the types, etc to show in the browser.
-
-    // For each widget (in case of multi-entry)
-    $('.media-widget', context).once('mediaBrowserLaunch', function () {
-      var options = settings.media.elements[this.id];
-      globalOptions = {};
-      if (options.global != undefined) {
-        var globalOptions = options.global;
-      }
-      //options = Drupal.settings.media.fields[this.id];
-      var fidField = $('.fid', this);
-      var previewField = $('.preview', this);
-      var editButton = $('.edit', this);
-      var removeButton = $('.remove', this);
-
-      // Hide the edit and remove buttons if there is no file data yet.
-      if (fidField.val() == 0) {
-        if (editButton.length) {
-          editButton.hide();
-        }
-        removeButton.hide();
-      }
-
-      // When someone clicks the link to pick media (or clicks on an existing thumbnail)
-      $('.launcher', this).bind('click', function (e) {
-        // Launch the browser, providing the following callback function
-        // @TODO: This should not be an anomyous function.
-        Drupal.media.popups.mediaBrowser(function (mediaFiles) {
-          if (mediaFiles.length < 0) {
-            return;
-          }
-          var mediaFile = mediaFiles[0];
-          // Set the value of the filefield fid (hidden) and trigger a change.
-          fidField.val(mediaFile.fid);
-          fidField.trigger('change');
-          // Set the preview field HTML.
-          previewField.html(mediaFile.preview);
-        }, globalOptions);
-        e.preventDefault();
+    if (settings.media && settings.media.elements) {
+      $.each(settings.media.elements, function(selector) {
+        $(selector, context).once('media-browser-launch', function () {
+          var configuration = settings.media.elements[selector];
+          // The user has JavaScript enabled, so display the browse field and hide
+          // the upload and attach fields which are only used as a fallback in
+          // case the user is unable to use the media browser.
+          $(selector, context).children('.browse').show();
+          $(selector, context).children('.upload').hide();
+          $(selector, context).children('.attach').hide();
+          $(selector, context).children('.browse').bind('click', {configuration: configuration}, Drupal.media.openBrowser);
+        });
       });
+    }
+  }
+};
 
-      // When someone clicks the Remove button.
-      $('.remove', this).bind('click', function (e) {
-        // Set the value of the filefield fid (hidden) and trigger change.
-        fidField.val(0);
-        fidField.trigger('change');
-        // Set the preview field HTML.
-        previewField.html('');
-        e.preventDefault();
-      });
+/**
+ * Attach behaviors to the media attach and remove buttons.
+ */
+Drupal.behaviors.mediaButtons = {
+  attach: function (context) {
+    $('input.form-submit', context).bind('mousedown', Drupal.media.disableFields);
+  },
+  detach: function (context) {
+    $('input.form-submit', context).unbind('mousedown', Drupal.media.disableFields);
+  }
+};
 
-      // Show or hide the edit/remove buttons if the field has a file or not.
-      $('.fid', this).bind('change', function() {
-        if (fidField.val() == 0) {
-          if (editButton.length) {
-            editButton.hide();
-          }
-          removeButton.hide();
-        }
-        else {
-          if (editButton.length) {
-            var url = Drupal.settings.basePath + 'file/' + fidField.val() + '/edit';
-            $.ajax({
-              url: location.protocol + '//' + location.host + url,
-              type: 'HEAD',
-              success: function(data) {
-                editButton.attr('href', editButton.attr('href').replace(/media\/\d+\/edit/, 'media/' + fidField.val() + '/edit'));
-                // Re-process the edit link through CTools modal behaviors.
-                editButton.unbind('click');
-                editButton.removeClass('ctools-use-modal-processed');
-                // @todo Maybe add support for Drupal.detachBehaviors in Drupal.behaviors.ZZCToolsModal?
-                Drupal.attachBehaviors(editButton.parent(), Drupal.settings);
-                editButton.show();
-              }
-            });
-          }
-          removeButton.show();
-        }
-      });
-    });
+/**
+ * Media attach utility functions.
+ */
+Drupal.media = Drupal.media || {};
+
+/**
+ * Opens the media browser with the element's configuration settings.
+ */
+Drupal.media.openBrowser = function (event) {
+  var clickedButton = this;
+  var configuration = event.data.configuration.global;
+
+  // Find the file ID, preview and upload fields.
+  var fidField = $(this).siblings('.fid');
+  var previewField = $(this).siblings('.preview');
+  var uploadField = $(this).siblings('.upload');
+
+  // Find the edit and remove buttons.
+  var editButton = $(this).siblings('.edit');
+  var removeButton = $(this).siblings('.remove');
+
+  // Launch the media browser.
+  Drupal.media.popups.mediaBrowser(function (mediaFiles) {
+    // Ensure that there was at least one media file selected.
+    if (mediaFiles.length < 0) {
+      return;
+    }
+
+    // Grab the first of the selected media files.
+    var mediaFile = mediaFiles[0];
+
+    // Set the value of the hidden file ID field and trigger a change.
+    uploadField.val(mediaFile.fid);
+    uploadField.trigger('change');
+
+    // Find the attach button and automatically trigger it.
+    var attachButton = uploadField.siblings('.attach');
+    attachButton.trigger('mousedown');
+
+    // Display a preview of the file using the selected media file's display.
+    previewField.html(mediaFile.preview);
+  }, configuration);
+
+  return false;
+};
+
+/**
+ * Prevent media browsing when using buttons not intended to browse.
+ */
+Drupal.media.disableFields = function (event) {
+  var clickedButton = this;
+
+  // Only disable browse fields for Ajax buttons.
+  if (!$(clickedButton).hasClass('ajax-processed')) {
+    return;
   }
+
+  // Check if we're working with an "Attach" button.
+  var $enabledFields = [];
+  if ($(this).closest('div.media-widget').length > 0) {
+    $enabledFields = $(this).closest('div.media-widget').find('input.attach');
+  }
+
+  // Temporarily disable attach fields other than the one we're currently
+  // working with. Filter out fields that are already disabled so that they
+  // do not get enabled when we re-enable these fields at the end of behavior
+  // processing. Re-enable in a setTimeout set to a relatively short amount
+  // of time (1 second). All the other mousedown handlers (like Drupal's Ajax
+  // behaviors) are excuted before any timeout functions are called, so we
+  // don't have to worry about the fields being re-enabled too soon.
+  // @todo If the previous sentence is true, why not set the timeout to 0?
+  var $fieldsToTemporarilyDisable = $('div.media-widget input.attach').not($enabledFields).not(':disabled');
+  $fieldsToTemporarilyDisable.attr('disabled', 'disabled');
+  setTimeout(function (){
+    $fieldsToTemporarilyDisable.attr('disabled', false);
+  }, 1000);
 };
 
 })(jQuery);
+
diff --git a/drupal7/sites/all/modules/media/js/media.popups.js b/drupal7/sites/all/modules/media/js/media.popups.js
index 95b72e3f..2abb96e6 100644
--- a/drupal7/sites/all/modules/media/js/media.popups.js
+++ b/drupal7/sites/all/modules/media/js/media.popups.js
@@ -58,17 +58,15 @@ Drupal.media.popups.mediaBrowser = function (onSelect, globalOptions, pluginOpti
   var mediaIframe = Drupal.media.popups.getPopupIframe(browserSrc, 'mediaBrowser');
   // Attach the onLoad event
   mediaIframe.bind('load', options, options.widget.onLoad);
+
   /**
    * Setting up the modal dialog
    */
-
   var ok = 'OK';
-  var cancel = 'Cancel';
   var notSelected = 'You have not selected anything!';
 
   if (Drupal && Drupal.t) {
     ok = Drupal.t(ok);
-    cancel = Drupal.t(cancel);
     notSelected = Drupal.t(notSelected);
   }
 
@@ -85,14 +83,13 @@ Drupal.media.popups.mediaBrowser = function (onSelect, globalOptions, pluginOpti
     $(this).dialog("close");
   };
 
-  dialogOptions.buttons[cancel] = function () {
-    $(this).dialog("close");
-  };
+  var dialog = mediaIframe.dialog(dialogOptions);
+
+  Drupal.media.popups.sizeDialog(dialog);
+  Drupal.media.popups.resizeDialog(dialog);
+  Drupal.media.popups.scrollDialog(dialog);
+  Drupal.media.popups.overlayDisplace(dialog.parents(".ui-dialog"));
 
-  Drupal.media.popups.setDialogPadding(mediaIframe.dialog(dialogOptions));
-  // Remove the title bar.
-  mediaIframe.parents(".ui-dialog").find(".ui-dialog-titlebar").remove();
-  Drupal.media.popups.overlayDisplace(mediaIframe.parents(".ui-dialog"));
   return mediaIframe;
 };
 
@@ -149,7 +146,14 @@ Drupal.media.popups.mediaBrowser.finalizeSelection = function () {
 Drupal.media.popups.mediaStyleSelector = function (mediaFile, onSelect, options) {
   var defaults = Drupal.media.popups.mediaStyleSelector.getDefaults();
   // @todo: remove this awful hack :(
-  defaults.src = defaults.src.replace('-media_id-', mediaFile.fid) + '&fields=' + JSON.stringify(mediaFile.fields);
+  if (typeof defaults.src === 'string' ) {
+    defaults.src = defaults.src.replace('-media_id-', mediaFile.fid) + '&fields=' + encodeURIComponent(JSON.stringify(mediaFile.fields));
+  }
+  else {
+    var src = defaults.src.shift();
+    defaults.src.unshift(src);
+    defaults.src = src.replace('-media_id-', mediaFile.fid) + '&fields=' + encodeURIComponent(JSON.stringify(mediaFile.fields));
+  }
   options = $.extend({}, defaults, options);
   // Create it as a modal window.
   var mediaIframe = Drupal.media.popups.getPopupIframe(options.src, 'mediaStyleSelector');
@@ -160,12 +164,10 @@ Drupal.media.popups.mediaStyleSelector = function (mediaFile, onSelect, options)
    * Set up the button text
    */
   var ok = 'OK';
-  var cancel = 'Cancel';
   var notSelected = 'Very sorry, there was an unknown error embedding media.';
 
   if (Drupal && Drupal.t) {
     ok = Drupal.t(ok);
-    cancel = Drupal.t(cancel);
     notSelected = Drupal.t(notSelected);
   }
 
@@ -183,14 +185,13 @@ Drupal.media.popups.mediaStyleSelector = function (mediaFile, onSelect, options)
     $(this).dialog("close");
   };
 
-  dialogOptions.buttons[cancel] = function () {
-    $(this).dialog("close");
-  };
+  var dialog = mediaIframe.dialog(dialogOptions);
+
+  Drupal.media.popups.sizeDialog(dialog);
+  Drupal.media.popups.resizeDialog(dialog);
+  Drupal.media.popups.scrollDialog(dialog);
+  Drupal.media.popups.overlayDisplace(dialog.parents(".ui-dialog"));
 
-  Drupal.media.popups.setDialogPadding(mediaIframe.dialog(dialogOptions));
-  // Remove the title bar.
-  mediaIframe.parents(".ui-dialog").find(".ui-dialog-titlebar").remove();
-  Drupal.media.popups.overlayDisplace(mediaIframe.parents(".ui-dialog"));
   return mediaIframe;
 };
 
@@ -235,12 +236,10 @@ Drupal.media.popups.mediaFieldEditor = function (fid, onSelect, options) {
    * Set up the button text
    */
   var ok = 'OK';
-  var cancel = 'Cancel';
   var notSelected = 'Very sorry, there was an unknown error embedding media.';
 
   if (Drupal && Drupal.t) {
     ok = Drupal.t(ok);
-    cancel = Drupal.t(cancel);
     notSelected = Drupal.t(notSelected);
   }
 
@@ -257,14 +256,13 @@ Drupal.media.popups.mediaFieldEditor = function (fid, onSelect, options) {
     $(this).dialog("close");
   };
 
-  dialogOptions.buttons[cancel] = function () {
-    $(this).dialog("close");
-  };
+  var dialog = mediaIframe.dialog(dialogOptions);
+
+  Drupal.media.popups.sizeDialog(dialog);
+  Drupal.media.popups.resizeDialog(dialog);
+  Drupal.media.popups.scrollDialog(dialog);
+  Drupal.media.popups.overlayDisplace(dialog);
 
-  Drupal.media.popups.setDialogPadding(mediaIframe.dialog(dialogOptions));
-  // Remove the title bar.
-  mediaIframe.parents(".ui-dialog").find(".ui-dialog-titlebar").remove();
-  Drupal.media.popups.overlayDisplace(mediaIframe.parents(".ui-dialog"));
   return mediaIframe;
 };
 
@@ -291,49 +289,30 @@ Drupal.media.popups.mediaFieldEditor.getDefaults = function () {
 Drupal.media.popups.getDialogOptions = function () {
   return {
     buttons: {},
-    dialogClass: 'media-wrapper',
-    modal: true,
-    draggable: false,
-    resizable: false,
-    minWidth: 500,
-    width: 670,
-    height: 280,
-    position: 'center',
+    dialogClass: Drupal.settings.media.dialogOptions.dialogclass,
+    modal: Drupal.settings.media.dialogOptions.modal,
+    draggable: Drupal.settings.media.dialogOptions.draggable,
+    resizable: Drupal.settings.media.dialogOptions.resizable,
+    minWidth: Drupal.settings.media.dialogOptions.minwidth,
+    width: Drupal.settings.media.dialogOptions.width,
+    height: Drupal.settings.media.dialogOptions.height,
+    position: Drupal.settings.media.dialogOptions.position,
     overlay: {
-      backgroundColor: '#000000',
-      opacity: 0.4
+      backgroundColor: Drupal.settings.media.dialogOptions.overlay.backgroundcolor,
+      opacity: Drupal.settings.media.dialogOptions.overlay.opacity
     },
-    zIndex: 10000,
+    zIndex: Drupal.settings.media.dialogOptions.zindex,
     close: function (event, ui) {
       $(event.target).remove();
     }
   };
 };
 
-/**
- * Created padding on a dialog
- *
- * @param jQuery dialogElement
- *  The element which has .dialog() attached to it.
- */
-Drupal.media.popups.setDialogPadding = function (dialogElement) {
-  // @TODO: Perhaps remove this hardcoded reference to height.
-  // - It's included to make IE on Windows 7 display the dialog without
-  //   collapsing. 550 is the height that displays all of the tab panes
-  //   within the Add Media overlay. This is either a bug in the jQuery
-  //   UI library, a bug in IE on Windows 7 or a bug in the way the
-  //   dialog is instantiated. Or a combo of the three.
-  //   All browsers except IE on Win7 ignore these defaults and adjust
-  //   the height of the iframe correctly to match the content in the panes
-  dialogElement.height(dialogElement.dialog('option', 'height'));
-  dialogElement.width(dialogElement.dialog('option', 'width'));
-};
-
 /**
  * Get an iframe to serve as the dialog's contents. Common to both plugins.
  */
 Drupal.media.popups.getPopupIframe = function (src, id, options) {
-  var defaults = {width: '800px', scrolling: 'auto'};
+  var defaults = {width: '100%', scrolling: 'auto'};
   var options = $.extend({}, defaults, options);
 
   return $('<iframe class="media-modal-frame"/>')
@@ -352,4 +331,54 @@ Drupal.media.popups.overlayDisplace = function (dialog) {
   }
 }
 
+/**
+ * Size the dialog when it is first loaded and keep it centered when scrolling.
+ *
+ * @param jQuery dialogElement
+ *  The element which has .dialog() attached to it.
+ */
+Drupal.media.popups.sizeDialog = function (dialogElement) {
+  if (!dialogElement.is(':visible')) {
+    return;
+  }
+  var windowWidth = $(window).width();
+  var dialogWidth = windowWidth * 0.8;
+  var windowHeight = $(window).height();
+  var dialogHeight = windowHeight * 0.8;
+
+  dialogElement.dialog("option", "width", dialogWidth);
+  dialogElement.dialog("option", "height", dialogHeight);
+  dialogElement.dialog("option", "position", 'center');
+
+  $('.media-modal-frame').width('100%');
+}
+
+/**
+ * Resize the dialog when the window changes.
+ *
+ * @param jQuery dialogElement
+ *  The element which has .dialog() attached to it.
+ */
+Drupal.media.popups.resizeDialog = function (dialogElement) {
+  $(window).resize(function() {
+    Drupal.media.popups.sizeDialog(dialogElement);
+  });
+}
+
+/**
+ * Keeps the dialog centered when the window is scrolled.
+ *
+ * @param jQuery dialogElement
+ *  The element which has .dialog() attached to it.
+ */
+Drupal.media.popups.scrollDialog = function (dialogElement) {
+  // Keep the dialog window centered when scrolling.
+  $(window).scroll(function() {
+    if (!dialogElement.is(':visible')) {
+      return;
+    }
+    dialogElement.dialog("option", "position", 'center');
+  });
+}
+
 })(jQuery);
diff --git a/drupal7/sites/all/modules/media/js/plugins/media.upload_multiple.js b/drupal7/sites/all/modules/media/js/plugins/media.upload_multiple.js
deleted file mode 100644
index 3c5d1892..00000000
--- a/drupal7/sites/all/modules/media/js/plugins/media.upload_multiple.js
+++ /dev/null
@@ -1,21 +0,0 @@
-Drupal.behaviors.mediaUploadMultiple = {};
-
-Drupal.behaviors.mediaUploadMultiple.attach = function (context, settings) {
-  // When the plupload element initializes, it expands the size of the elements
-  // it has created, so we need to resize the browser iframe after it's done.
-  var uploader = jQuery('#edit-upload').pluploadQueue();
-  if (uploader) {
-    // Handle the case in which the uploader has already finished initializing.
-    Drupal.media.browser.resizeIframe();
-    // Handle the case in which the uploader has not yet initialized.
-    uploader.bind("PostInit", Drupal.media.browser.resizeIframe);
-
-    uploader.bind('StateChanged', Drupal.behaviors.mediaUploadMultiple.submit);
-  }
-};
-
-Drupal.behaviors.mediaUploadMultiple.submit = function (uploader, file) {
-  if (uploader.state == 2) {
-    jQuery('#media-add-upload-multiple .form-submit').val(Drupal.t('Loading...'));
-  }
-};
diff --git a/drupal7/sites/all/modules/media/media.api.php b/drupal7/sites/all/modules/media/media.api.php
index 187b70d4..4ff1c4f8 100644
--- a/drupal7/sites/all/modules/media/media.api.php
+++ b/drupal7/sites/all/modules/media/media.api.php
@@ -102,68 +102,3 @@ function hook_media_browser_params_alter(&$stored_params) {
   $stored_params['types'][] = 'document';
   unset($stored_params['enabledPlugins'][0]);
 }
-
-/**
- * Alter a list of view modes allowed for a file embedded in the WYSIWYG.
- *
- * @param array $view_modes
- *   An array of view modes that can be used on the file when embedded in the
- *   WYSIWYG.
- * @param object $file
- *   A file entity.
- *
- * @see media_get_wysiwyg_allowed_view_modes()
- */
-function hook_media_wysiwyg_allowed_view_modes_alter(&$view_modes, $file) {
-  $view_modes['default']['label'] = t('Display an unmodified version of the file');
-  unset($view_modes['preview']);
-}
-
-/**
- * Alter the WYSIWYG view mode selection form.
- *
- * Similar to a form_alter, but runs first so that modules can add
- * fields specific to a given file type (like alt tags on images) before alters
- * begin to work on the fields.
- *
- * @param array $form
- *   An associative array containing the structure of the form.
- * @param array $form_state
- *   An associative array containing the current state of the form.
- * @param object $file
- *   A file entity.
- *
- * @see media_format_form()
- */
-function hook_media_format_form_prepare_alter(&$form, &$form_state, $file) {
-  $form['preview']['#access'] = FALSE;
-
-  $file = $form['#media'];
-  $form['heading']['#markup'] = t('Embedding %filename of type %filetype', array('%filename' => $file->filename, '%filetype' => $file->type));
-}
-
-/**
- * Alter the output generated by Media filter tags.
- *
- * @param array $element
- *   The renderable array of output generated for the filter tag.
- * @param array $tag_info
- *   The filter tag converted into an associative array by
- *   media_token_to_markup() with the following elements:
- *   - 'fid': The ID of the media file being rendered.
- *   - 'file': The object from file_load() of the media file being rendered.
- *   - 'view_mode': The view mode being used to render the file.
- *   - 'attributes': An additional array of attributes that could be output
- *     with media_get_file_without_label().
- * @param array $settings
- *   An additional array of settings.
- *   - 'wysiwyg': A boolean if the output is for the WYSIWYG preview or FALSE
- *     if for normal rendering.
- *
- * @see media_token_to_markup()
- */
-function hook_media_token_to_markup_alter(&$element, $tag_info, $settings) {
-  if (empty($settings['wysiwyg'])) {
-    $element['#attributes']['alt'] = t('This media has been output using the @mode view mode.', array('@mode' => $tag_info['view_mode']));
-  }
-}
diff --git a/drupal7/sites/all/modules/media/media.file_default_displays.inc b/drupal7/sites/all/modules/media/media.file_default_displays.inc
new file mode 100644
index 00000000..ec7a378f
--- /dev/null
+++ b/drupal7/sites/all/modules/media/media.file_default_displays.inc
@@ -0,0 +1,61 @@
+<?php
+
+/**
+ * @file
+ * Default display configuration for the default file types.
+ */
+
+/**
+ * Implements hook_file_default_displays().
+ */
+function media_file_default_displays() {
+  $file_displays = array();
+
+  // Audio previews should be displayed using a large filetype icon.
+  $file_display = new stdClass();
+  $file_display->api_version = 1;
+  $file_display->name = 'audio__preview__file_field_media_large_icon';
+  $file_display->weight = 50;
+  $file_display->status = TRUE;
+  $file_display->settings = '';
+  $file_displays['audio__preview__file_field_media_large_icon'] = $file_display;
+
+  // Document previews should be displayed using a large filetype icon.
+  $file_display = new stdClass();
+  $file_display->api_version = 1;
+  $file_display->name = 'document__preview__file_field_media_large_icon';
+  $file_display->weight = 50;
+  $file_display->status = TRUE;
+  $file_display->settings = '';
+  $file_displays['document__preview__file_field_media_large_icon'] = $file_display;
+
+  // Image previews should be displayed using a large filetype icon.
+  $file_display = new stdClass();
+  $file_display->api_version = 1;
+  $file_display->name = 'image__preview__file_field_media_large_icon';
+  $file_display->weight = 50;
+  $file_display->status = TRUE;
+  $file_display->settings = '';
+  $file_displays['image__preview__file_field_media_large_icon'] = $file_display;
+
+  // Video previews should be displayed using a large filetype icon.
+  $file_display = new stdClass();
+  $file_display->api_version = 1;
+  $file_display->name = 'video__preview__file_field_media_large_icon';
+  $file_display->weight = 50;
+  $file_display->status = TRUE;
+  $file_display->settings = '';
+  $file_displays['video__preview__file_field_media_large_icon'] = $file_display;
+
+  return $file_displays;
+}
+
+/**
+ * Implements hook_file_default_displays_alter().
+ */
+function media_file_default_displays_alter(&$file_displays) {
+  // Image previews should be displayed using the media image style.
+  if (isset($file_displays['image__preview__file_field_image'])) {
+    $file_displays['image__preview__file_field_image']->settings['image_style'] = 'media_thumbnail';
+  }
+}
diff --git a/drupal7/sites/all/modules/media/media.info b/drupal7/sites/all/modules/media/media.info
index 2d146f35..27a92be0 100644
--- a/drupal7/sites/all/modules/media/media.info
+++ b/drupal7/sites/all/modules/media/media.info
@@ -18,14 +18,15 @@ files[] = includes/MediaEntityTranslationHandler.inc
 files[] = includes/media_views_plugin_display_media_browser.inc
 files[] = includes/media_views_plugin_style_media_browser.inc
 files[] = tests/media.test
-files[] = tests/media.entity.test
-files[] = tests/media.file.usage.test
 
 configure = admin/config/media/browser
 
-; Information added by drupal.org packaging script on 2013-10-25
-version = "7.x-2.0-alpha3"
+; We have to add a fake version so Git checkouts do not fail Media dependencies
+version = 7.x-2.x-dev
+
+; Information added by Drupal.org packaging script on 2014-10-04
+version = "7.x-2.0-alpha4"
 core = "7.x"
 project = "media"
-datestamp = "1382744872"
+datestamp = "1412422430"
 
diff --git a/drupal7/sites/all/modules/media/media.install b/drupal7/sites/all/modules/media/media.install
index 343ba7fd..43a17456 100644
--- a/drupal7/sites/all/modules/media/media.install
+++ b/drupal7/sites/all/modules/media/media.install
@@ -9,42 +9,12 @@
  * Implements hook_install().
  */
 function media_install() {
-  // Create initial display settings.
-  module_load_include('inc', 'file_entity', 'file_entity.file_api');
-  $default_image_styles = array(
-    'preview' => 'media_thumbnail',
-    'teaser' => 'medium',
-    'full' => 'large',
-  );
-  // Only needed by sites that updated from Media 1.x.
-  // @see media_entity_info_alter()
-  if (variable_get('media__show_deprecated_view_modes')) {
-    $default_image_styles['media_original'] = '';
-  }
-
-  foreach ($default_image_styles as $view_mode => $image_style) {
-    $existing_display = file_displays_load('image', $view_mode);
-
-    if (empty($existing_display)) {
-      $display_name = 'image__' . $view_mode . '__file_image';
-      $display = array(
-        'api_version' => 1,
-        'name' => $display_name,
-        'status' => 1,
-        'weight' => 5,
-        'settings' => array('image_style' => $image_style),
-        'export_type' => NULL,
-      );
-      file_display_save((object) $display);
-    }
-  }
-
   // Make sure that we set the icon base directory variable if it is not
   // already set.
-  $base = variable_get('media__icon_base_directory', NULL);
+  $base = variable_get('media_icon_base_directory', NULL);
   if (!isset($base)) {
     $default_base = 'public://media-icons';
-    variable_set('media__icon_base_directory', $default_base);
+    variable_set('media_icon_base_directory', $default_base);
   }
   try {
     _media_install_copy_icons();
@@ -58,12 +28,12 @@ function media_install() {
  * Copy the media file icons to files directory for use with image styles.
  */
 function _media_install_copy_icons() {
-  $destination = variable_get('media__icon_base_directory', 'public://media-icons') . '/' . variable_get('media__icon_set', 'default');
+  $destination = variable_get('media_icon_base_directory', 'public://media-icons') . '/' . variable_get('media_icon_set', 'default');
   if (!file_prepare_directory($destination, FILE_CREATE_DIRECTORY)) {
     throw new Exception("Unable to create directory $destination.");
   }
   // @todo If we ever add another default icon set, this should copy all images from one directory up.
-  $source = drupal_get_path('module', 'media') . '/images/icons/' . variable_get('media__icon_set', 'default');
+  $source = drupal_get_path('module', 'media') . '/images/icons/' . variable_get('media_icon_set', 'default');
   $files = file_scan_directory($source, '/.*\.(png|jpg)$/');
   foreach ($files as $file) {
     $result = file_unmanaged_copy($file->uri, $destination, FILE_EXISTS_REPLACE);
@@ -78,30 +48,23 @@ function _media_install_copy_icons() {
  */
 function media_uninstall() {
   // Remove variables.
-  variable_del('media__wysiwyg_title');
-  variable_del('media__wysiwyg_icon_title');
-  variable_del('media__wysiwyg_default_view_mode');
-  variable_del('media__wysiwyg_upload_directory');
-  variable_del('media__wysiwyg_allowed_types');
-  variable_del('media__wysiwyg_allowed_attributes');
-  variable_del('media__wysiwyg_browser_plugins');
-  variable_del('media__dialog_theme');
-  variable_del('media__max_filesize');
-  variable_del('media__debug');
-  variable_del('media__file_list_size');
-  variable_del('media__xml_cache_expire');
-  variable_del('media__import_batch_size');
-  variable_del('media__fromurl_supported_schemes');
-  variable_del('media__icon_base_directory');
-  variable_del('media__icon_set');
-  variable_del('media__show_deprecated_view_modes');
-  variable_del('media__show_file_type_rebuild_nag');
-  variable_del('media__field_select_media_text');
-  variable_del('media__field_remove_media_text');
-  variable_del('media__browser_library_empty_message');
-  variable_del('media__browser_pager_limit');
-  variable_del('media__browser_viewtype_default');
-  variable_del('media__display_types_migration_mess');
+  variable_del('media_dialog_theme');
+  variable_del('media_icon_base_directory');
+  variable_del('media_icon_set');
+  variable_del('media_show_deprecated_view_modes');
+
+  // Dialog options.
+  variable_del('media_dialogclass');
+  variable_del('media_modal');
+  variable_del('media_draggable');
+  variable_del('media_resizable');
+  variable_del('media_minwidth');
+  variable_del('media_width');
+  variable_del('media_height');
+  variable_del('media_position');
+  variable_del('media_zindex');
+  variable_del('media_backgroundcolor');
+  variable_del('media_opacity');
 }
 
 /**
@@ -129,6 +92,9 @@ function media_update_dependencies() {
   $dependencies['media'][7208] = array(
     'file_entity' => 7210,
   );
+  $dependencies['media'][7212] = array(
+    'file_entity' => 7210,
+  );
   return $dependencies;
 }
 
@@ -916,12 +882,15 @@ function media_update_7208() {
 }
 
 /**
- * DEPRECATED: Update {file_managed}.type with the new file types provided by
- * file_entity. (Types migration has been moved to admin/structure/file-types/upgrade',
- * where can be executed manually.)
+ * Enable the hidden media_migrate_file_types module to provide a UI to update
+ * {file_managed}.type with the new file types provided by file_entity.
  */
 function media_update_7209() {
+  drupal_load('module', 'media_migrate_file_types');
 
+  if (_media_migrate_file_types_get_migratable_file_types()) {
+    module_enable(array('media_migrate_file_types'));
+  }
 }
 
 /**
@@ -932,31 +901,43 @@ function media_update_7210() {
 }
 
 /**
- * Flush old version of the image style to make the thumbnails appear correctly.
+ * Save a square_thumbnail image style in the database for legacy support if one
+ * does not already exist.
  */
 function media_update_7211() {
-  $style = image_style_load('square_thumbnail');
+  $default_style = array(
+    'name' => 'square_thumbnail'
+  );
 
-  if ($style) {
-    $style['name'] = 'media_thumbnail';
-    image_style_save($style);
-  }
+  // Clear the image cache to remove any old image styles that only exist in
+  // code.
+  cache_clear_all('*', 'cache_image', TRUE);
+
+  // Check if the square_thumbnail image style exists.
+  // The style will only exist if the user has customized it, otherwise it would
+  // have been removed by clearing the image style cache.
+  $existing_style = image_style_load('square_thumbnail');
+
+  // Save a square_thumbnail image style in the database for legacy support.
+  // This is only necessary if a square_thumbnail image style doesn't already
+  // exist.
+  if (empty($existing_style)) {
+    $style = image_style_save($default_style);
+
+    $effect = array(
+      'name' => 'image_scale_and_crop',
+      'data' => array(
+        'width' => 180,
+        'height' => 180,
+        'weight' => 0,
+      ),
+      'isid' => $style['isid'],
+    );
 
-  // Replace any instances in display settings
-  module_load_include('inc', 'file_entity', 'file_entity.file_api');
-  $entity_info = entity_get_info('file');
-  $view_modes = array('default' => array('label' => t('Default'))) + $entity_info['view modes'];
-  foreach ($view_modes as $view_mode => $view_mode_info) {
-    $displays = file_displays_load('image', $view_mode);
-    foreach ($displays as $display) {
-      if ($display->settings['image_style'] == 'square_thumbnail') {
-        $display->settings['image_style'] = 'media_thumbnail';
-        file_display_save($display);
-      }
-    }
+    image_effect_save($effect);
   }
 
-  return t('Flushed image style and updated display styles.');
+  return t('Saved a square_thumbnail image style in the database for legacy support if one did not already exist.');
 }
 
 /**
@@ -1068,3 +1049,125 @@ function media_update_7218() {
 
   variable_del('media__xml_cache_expire');
 }
+
+/**
+ * Enable the Media WYSIWYG submodule.
+ */
+function media_update_7219() {
+  if (module_exists('wysiwyg')) {
+    module_enable(array('media_wysiwyg'));
+  }
+}
+
+/**
+ * Delete the deprecated media__file_list_size variable.
+ */
+function media_update_7220() {
+  variable_del('media__file_list_size');
+}
+
+/**
+ * Enable the Media Bulk Upload submodule.
+ */
+function media_update_7221() {
+  if (module_exists('multiform') && module_exists('plupload')) {
+    module_enable(array('media_bulk_upload'));
+  }
+}
+
+/**
+ * Delete the deprecated media__display_types_migration_mess variable.
+ */
+function media_update_7222() {
+  variable_del('media__display_types_migration_mess');
+}
+
+/**
+ * Delete legacy variables.
+ */
+function media_update_7223() {
+  variable_del('media__max_filesize');
+  variable_del('media__debug');
+  variable_del('media__xml_cache_expire');
+  variable_del('media__show_file_type_rebuild_nag');
+  variable_del('media__field_select_media_text');
+  variable_del('media__field_remove_media_text');
+  variable_del('media__browser_library_empty_message');
+  variable_del('media__browser_pager_limit');
+  variable_del('media__browser_viewtype_default');
+}
+
+/**
+ * Rename variables, removing variable namespace.
+ */
+function media_update_7224() {
+  // Create an array of variables sans 'media' prefix.
+  $variables = array('wysiwyg_title', 'wysiwyg_icon_title', 'wysiwyg_default_view_mode', 'wysiwyg_upload_directory', 'wysiwyg_allowed_types', 'wysiwyg_allowed_attributes', 'wysiwyg_browser_plugins', 'dialog_theme', 'import_batch_size', 'fromurl_supported_schemes', 'icon_base_directory', 'icon_set', 'show_deprecated_view_modes');
+
+  foreach ($variables as $variable) {
+    // Find the value of the old variable.
+    $value = variable_get('media__' . $variable);
+
+    // Port the value of the variable if it was set.
+    if (!is_null($value)) {
+      variable_set('media_' . $variable, $value);
+    }
+
+    // Remove the old variable.
+    variable_del('media__' . $variable);
+  }
+}
+
+/**
+ * Migrate variables to appropriate submodules.
+ */
+function media_update_7225() {
+  $data = array(
+    'media_wysiwyg' => array(
+      'wysiwyg_title',
+      'wysiwyg_icon_title',
+      'wysiwyg_default_view_mode',
+      'wysiwyg_upload_directory',
+      'wysiwyg_allowed_types',
+      'wysiwyg_allowed_attributes',
+      'wysiwyg_browser_plugins',
+    ),
+    'media_internet' => array(
+      'fromurl_supported_schemes',
+    ),
+    'media_bulk_upload' => array(
+      'import_batch_size',
+    ),
+  );
+
+  foreach ($data as $module => $variables) {
+    foreach ($variables as $variable) {
+      // Only port variables to submodules if the submodule exists.
+      if (module_exists($module)) {
+        // Find the value of the old variable.
+        $value = variable_get('media_' . $variable);
+
+        // Port the value of the variable if it was set.
+        if (!is_null($value)) {
+          variable_set($module . '_' . $variable, $value);
+        }
+      }
+
+      // Remove the old variable.
+      variable_del('media_' . $variable);
+    }
+  }
+}
+
+/**
+ * Accommodate the introduction of a new permission which restricts access to
+ * the media browser by granting it to existing users who were able to access
+ * it.
+ */
+function media_update_7226() {
+  $roles = user_roles(FALSE, 'create files');
+
+  foreach ($roles as $rid => $role) {
+    user_role_grant_permissions($rid, array('access media browser'));
+  }
+}
diff --git a/drupal7/sites/all/modules/media/media.media.inc b/drupal7/sites/all/modules/media/media.media.inc
index 4a20dee0..2700265f 100644
--- a/drupal7/sites/all/modules/media/media.media.inc
+++ b/drupal7/sites/all/modules/media/media.media.inc
@@ -40,97 +40,71 @@ function media_media_browser_plugin_info() {
 }
 
 /**
- * Implements hook_query_media_browser_alter().
+ * Implements hook_query_TAG_alter().
+ *
+ * @todo: Potentially move this into media.module in a future version of Media.
  */
 function media_query_media_browser_alter($query) {
   // Ensure that the query is against the file_managed table.
   $tables = $query->getTables();
+
   if (empty($tables['file_managed'])) {
     throw new Exception(t('Media browser being queried without the file_managed table.'));
   }
+
   $alias = $tables['file_managed']['alias'];
 
-  $params = drupal_get_query_parameters();
   // How do we validate these?  I don't know.
   // I think PDO should protect them, but I'm not 100% certain.
-  array_walk_recursive($params, 'media_recursive_check_plain');
-
-  $types = !empty($params['types']) ? $params['types'] : NULL;
-  $url_include_patterns = !empty($params['url_include_patterns']) ? $params['url_include_patterns'] : NULL;
-  $url_exclude_patterns = !empty($params['url_exclude_patterns']) ? $params['url_exclude_patterns'] : NULL;
-  $allowed_schemes = !empty($params['schemes']) ? array_filter($params['schemes']) : array();
-  $extensions = !empty($params['file_extensions']) ? array_filter(explode(' ', $params['file_extensions'])) : array();
-
-  $or_condition = db_or();
-
-  if (!empty($allowed_schemes)) {
-    // Include local files with the allowed extensions and types.
-    $local_wrappers = array_intersect_key(media_get_local_stream_wrappers(), $allowed_schemes);
-    if (!empty($extensions) && !empty($local_wrappers)) {
-      // Extension filtering.
-      $local_condition = db_or();
-      foreach (array_keys($local_wrappers) as $scheme) {
+  $params = media_get_browser_params();
+
+  // Gather any file restrictions.
+  $types = !empty($params['types']) ? $params['types'] : array();
+  $schemes = !empty($params['schemes']) ? $params['schemes'] : array();
+  $extensions = !empty($params['file_extensions']) ? explode(' ', $params['file_extensions']) : array();
+
+  $or = db_or();
+
+  // Filter out files with restricted types.
+  if (!empty($types)) {
+    $query->condition($alias . '.type', $types, 'IN');
+  }
+
+  // Filter out files with restricted schemes.
+  if (!empty($schemes)) {
+    $local_or = db_or();
+    $local_and = db_and();
+
+    // Gather all of the local stream wrappers.
+    $local_stream_wrappers = media_get_local_stream_wrappers();
+
+    foreach ($schemes as $scheme) {
+      // Only local files have extensions.
+      // Filter out files with restricted extensions.
+      if (!empty($extensions) && isset($local_stream_wrappers[$scheme])) {
+        $mimetypes = array();
         foreach ($extensions as $extension) {
-          $local_condition->condition($alias . '.uri', db_like($scheme . '://') . '%' . db_like('.' . $extension), 'LIKE');
+          $mimetype = media_get_extension_mimetype($extension);
+          if ($mimetype) {
+            $mimetypes[] = $mimetype;
+          }
         }
+        $local_and->condition($alias . '.uri', db_like($scheme . '://') . '%', 'LIKE');
+        if (count($mimetypes)) {
+          $local_and->condition($alias . '.filemime', $mimetypes, 'IN');
+        }
+        $local_or->condition($local_and);
+        $local_and = db_and();
       }
-      $or_condition->condition($local_condition);
-    }
-    if (!empty($types) && !empty($local_wrappers)) {
-      // Type filtering.
-      $local_condition = db_or();
-      foreach (array_keys($local_wrappers) as $scheme) {
-        $local_condition->condition($alias . '.type', $types, 'IN');
-      }
-      $or_condition->condition($local_condition);
-    }
-
-    // Include remote files with the allowed file types.
-    // We cant filter extensions here, because remote file filenames usually
-    // are a url or a parameter of a query.
-    $remote_wrappers = array_intersect_key(media_get_remote_stream_wrappers(), $allowed_schemes);
-    if (!empty($types) && !empty($remote_wrappers)) {
-      $remote_condition = db_and();
-      $wrapper_condition = db_or();
-      foreach (array_keys($remote_wrappers) as $scheme) {
-        $wrapper_condition->condition($alias . '.uri', db_like($scheme . '://') . '%', 'LIKE');
-      }
-      $remote_condition->condition($wrapper_condition);
-      $remote_condition->condition($alias . '.type', $types, 'IN');
-      $or_condition->condition($remote_condition);
-    }
-  }
-  else {
-    if (!empty($types)) {
-      $query->condition($alias . '.type', $types, 'IN');
-    }
-    if (!empty($extensions)) {
-      foreach ($extensions as $extension) {
-        $or_condition->condition($alias . '.uri', db_like('.' . $extension), 'LIKE');
+      else {
+        $local_or->condition($alias . '.uri', db_like($scheme . '://') . '%', 'LIKE');
       }
     }
-  }
 
-  if ($or_condition->count()) {
-    $query->condition($or_condition);
+    $or->condition($local_or);
   }
 
-  if ($url_include_patterns) {
-    $query->condition($alias . '.uri', '%' . db_like($url_include_patterns) . '%', 'LIKE');
-    // Insert stream related restrictions here.
-  }
-  if ($url_exclude_patterns) {
-    $query->condition($alias . '.uri', '%' . db_like($url_exclude_patterns) . '%', 'NOT LIKE');
-  }
-
-  if (!user_access('administer files')) {
-    $query->condition($alias . '.uri', db_like('private://') . '%', 'NOT LIKE');
-  }
-
-  // @todo This is possibly redundant since it's already filtered in the view.
-  $query->condition($alias . '.status', FILE_STATUS_PERMANENT);
-
-  foreach (array_keys(file_entity_get_hidden_stream_wrappers()) as $name) {
-    $query->condition($alias . '.uri', db_like($name . '://') . '%', 'NOT LIKE');
+  if ($or->count()) {
+    $query->condition($or);
   }
 }
diff --git a/drupal7/sites/all/modules/media/media.module b/drupal7/sites/all/modules/media/media.module
index da42a875..3c54914a 100644
--- a/drupal7/sites/all/modules/media/media.module
+++ b/drupal7/sites/all/modules/media/media.module
@@ -8,20 +8,9 @@
  * See http://drupal.org/project/media for more details.
  */
 
-/* ***************************************** */
-/* INCLUDES                                  */
-/* ***************************************** */
-
 // Code relating to using media as a field.
 require_once dirname(__FILE__) . '/includes/media.fields.inc';
 
- // Functions for working with [[inline tags]] and wysiwyg editors.
-require_once dirname(__FILE__) . '/includes/media.filter.inc';
-
-/* ***************************************** */
-/* Hook Implementations                      */
-/* ***************************************** */
-
 /**
  * Implements hook_hook_info().
  */
@@ -32,9 +21,6 @@ function media_hook_info() {
     'media_browser_plugin_info_alter',
     'media_browser_plugins_alter',
     'media_browser_params_alter',
-    'media_wysiwyg_allowed_view_modes_alter',
-    'media_format_form_prepare_alter',
-    'media_token_to_markup_alter',
     'query_media_browser_alter',
   );
 
@@ -71,35 +57,22 @@ function media_entity_info_alter(&$entity_info) {
   // For sites that updated from Media 1.x, continue to provide these deprecated
   // view modes.
   // @see http://drupal.org/node/1051090
-  if (variable_get('media__show_deprecated_view_modes', FALSE)) {
-    $entity_info['file']['view modes'] += array(
-      'media_link' => array(
-        'label' => t('Link'),
-        'custom settings' => TRUE,
-      ),
-      'media_original' => array(
-        'label' => t('Original'),
-        'custom settings' => TRUE,
-      ),
+  if (variable_get('media_show_deprecated_view_modes', FALSE)) {
+    $entity_info['file']['view modes']['media_link'] = array(
+      'label' => t('Link'),
+      'custom settings' => TRUE,
+    );
+    $entity_info['file']['view modes']['media_original'] = array(
+      'label' => t('Original'),
+      'custom settings' => TRUE,
     );
   }
 
   if (module_exists('entity_translation')) {
     $entity_info['file']['translation']['entity_translation']['class'] = 'MediaEntityTranslationHandler';
-    $entity_info['file']['translation']['entity_translation']['path schemes']['media'] = array('edit path' => 'media/%file/edit/%ctools_js');
   }
 }
 
-/**
- * Access callback for files. This function is deprecated.
- *
- * @todo Completely remove this function in favor of file_entity_access after
- * a few releases, to ensure rest of contib catches up.
- */
-function media_access($op, $account = NULL) {
-  return user_access('administer files', $account);
-}
-
 /**
  * Implements hook_menu().
  */
@@ -127,25 +100,19 @@ function media_menu() {
     'weight' => 10,
   );
 
-  // Used to import files from a local filesystem into Drupal.
-  $items['admin/content/file/import'] = array(
-    'title' => 'Import files',
-    'description' => 'Import files into your media library.',
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('media_import'),
-    'access arguments' => array('import media'),
-    'type' => MENU_LOCAL_ACTION,
-    'file' => 'includes/media.admin.inc',
-    'weight' => 10,
+  $items['media/ajax'] = array(
+    'page callback' => 'media_ajax_upload',
+    'delivery callback' => 'ajax_deliver',
+    'access arguments' => array('access content'),
+    'theme callback' => 'ajax_base_page_theme',
+    'type' => MENU_CALLBACK,
   );
-  $items['admin/content/file/thumbnails/import'] = $items['admin/content/file/import'];
 
   $items['media/browser'] = array(
     'title' => 'Media browser',
     'description' => 'Media Browser for picking media and uploading new media',
     'page callback' => 'media_browser',
-    'access callback' => 'file_entity_access',
-    'access arguments' => array('create'),
+    'access arguments' => array('access media browser'),
     'type' => MENU_CALLBACK,
     'file' => 'includes/media.browser.inc',
     'theme callback' => 'media_dialog_get_theme_name',
@@ -162,31 +129,6 @@ function media_menu() {
     'file' => 'includes/media.browser.inc',
   );
 
-  $items['media/%file/format-form'] = array(
-    'title' => 'Style selector',
-    'description' => 'Choose a format for a piece of media',
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('media_format_form', 1),
-    'access callback' => 'file_entity_access',
-    'access arguments' => array('view', 1),
-    'file' => 'includes/media.filter.inc',
-    'theme callback' => 'media_dialog_get_theme_name',
-    'type' => MENU_CALLBACK,
-  );
-
-  if (module_exists('multiform')) {
-    // @todo Investigate passing file IDs in query string rather than a menu
-    // argument and then deprecate media_multi_load().
-    $items['admin/content/file/edit-multiple/%media_multi'] = array(
-      'title' => 'Edit multiple files',
-      'page callback' => 'media_file_page_edit_multiple',
-      'page arguments' => array(4),
-      'access callback' =>  '_media_file_entity_access_recursive',
-      'access arguments' => array(4, 'update'),
-      'file' => 'includes/media.pages.inc',
-    );
-  }
-
   // We could re-use the file/%file/edit path for the modal callback, but
   // it is just easier to use our own namespace here.
   $items['media/%file/edit/%ctools_js'] = array(
@@ -195,24 +137,7 @@ function media_menu() {
     'page arguments' => array('media_file_edit_modal', 1, 3),
     'access callback' => 'file_entity_access',
     'access arguments' => array('update', 1),
-    'file' => 'includes/media.pages.inc',
-    'type' => MENU_CALLBACK,
-  );
-
-  // Upgrade interface for old file types.
-  $items['admin/structure/file-types/upgrade'] = array(
-    'title' => 'Upgrade types',
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('media_upgrade_file_types'),
-    'access arguments' => array('administer file types'),
-    'file' => 'includes/media.pages.inc',
-    'type' => MENU_CALLBACK,
-  );
-  $items['admin/structure/file-types/upgrade/confirm'] = array(
-    'title' => 'Upgrade types',
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('media_upgrade_file_types_confirm'),
-    'access arguments' => array('administer file types'),
+    'theme callback' => 'ajax_base_page_theme',
     'file' => 'includes/media.pages.inc',
     'type' => MENU_CALLBACK,
   );
@@ -242,10 +167,11 @@ function media_menu_local_tasks_alter(&$data, $router_item, $root_path) {
  */
 function media_admin_paths() {
   $paths['media/*/edit/*'] = TRUE;
+  $paths['media/*/format-form'] = TRUE;
 
   // If the media browser theme is set to the admin theme, ensure it gets set
   // as an admin path as well.
-  $dialog_theme = variable_get('media__dialog_theme', '');
+  $dialog_theme = variable_get('media_dialog_theme', '');
   if (empty($dialog_theme) || $dialog_theme == variable_get('admin_theme')) {
     $paths['media/browser'] = TRUE;
     $paths['media/browser/*'] = TRUE;
@@ -263,9 +189,8 @@ function media_permission() {
       'title' => t('Administer media browser'),
       'description' => t('Access media browser settings.'),
     ),
-    'import media' => array(
-      'title' => t('Import media files from the local filesystem'),
-      'description' => t('Simple file importer'),
+    'access media browser' => array(
+      'title' => t('Use the media browser'),
     ),
   );
 }
@@ -275,38 +200,101 @@ function media_permission() {
  */
 function media_theme() {
   return array(
-    // The default media file list form element.
-    'media_file_list' => array(
-      'variables' => array('element' => NULL),
+    // media.module.
+    'media_element' => array(
+      'render element' => 'element',
     ),
 
-    // A preview of the uploaded file.
-    'media_thumbnail' => array(
+    // media.field.inc.
+    'media_widget' => array(
       'render element' => 'element',
-      'file' => 'includes/media.theme.inc',
     ),
-
-    // Dialog page.
-    'media_dialog_page' => array(
-      'render element' => 'page',
-      'template' => 'templates/media-dialog-page',
-      'file' => 'includes/media.theme.inc',
+    'media_widget_multiple' => array(
+      'render element' => 'element',
+    ),
+    'media_upload_help' => array(
+      'variables' => array('description' => NULL),
     ),
 
-    // Media form API element type.
-    'media_element' => array(
+    // media.theme.inc.
+    'media_thumbnail' => array(
       'render element' => 'element',
       'file' => 'includes/media.theme.inc',
     ),
-
-    // Display a file as a large icon.
     'media_formatter_large_icon' => array(
       'variables' => array('file' => NULL, 'attributes' => array(), 'style_name' => 'media_thumbnail'),
       'file' => 'includes/media.theme.inc',
     ),
+    'media_dialog_page' => array(
+      'render element' => 'page',
+      'template' => 'templates/media-dialog-page',
+      'file' => 'includes/media.theme.inc',
+    ),
   );
 }
 
+/**
+ * Menu callback; Shared Ajax callback for media attachment and deletions.
+ *
+ * This rebuilds the form element for a particular field item. As long as the
+ * form processing is properly encapsulated in the widget element the form
+ * should rebuild correctly using FAPI without the need for additional callbacks
+ * or processing.
+ */
+function media_ajax_upload() {
+  $form_parents = func_get_args();
+  $form_build_id = (string) array_pop($form_parents);
+
+  if (empty($_POST['form_build_id']) || $form_build_id != $_POST['form_build_id']) {
+    // Invalid request.
+    drupal_set_message(t('An unrecoverable error occurred. The uploaded file likely exceeded the maximum file size (@size) that this server supports.', array('@size' => format_size(file_upload_max_size()))), 'error');
+    $commands = array();
+    $commands[] = ajax_command_replace(NULL, theme('status_messages'));
+    return array('#type' => 'ajax', '#commands' => $commands);
+  }
+
+  list($form, $form_state, $form_id, $form_build_id, $commands) = ajax_get_form();
+
+  if (!$form) {
+    // Invalid form_build_id.
+    drupal_set_message(t('An unrecoverable error occurred. Use of this form has expired. Try reloading the page and submitting again.'), 'error');
+    $commands = array();
+    $commands[] = ajax_command_replace(NULL, theme('status_messages'));
+    return array('#type' => 'ajax', '#commands' => $commands);
+  }
+
+  // Get the current element and count the number of files.
+  $current_element = $form;
+  foreach ($form_parents as $parent) {
+    $current_element = $current_element[$parent];
+  }
+  $current_file_count = isset($current_element['#file_upload_delta']) ? $current_element['#file_upload_delta'] : 0;
+
+  // Process user input. $form and $form_state are modified in the process.
+  drupal_process_form($form['#form_id'], $form, $form_state);
+
+  // Retrieve the element to be rendered.
+  foreach ($form_parents as $parent) {
+    $form = $form[$parent];
+  }
+
+  // Add the special Ajax class if a new file was added.
+  if (isset($form['#file_upload_delta']) && $current_file_count < $form['#file_upload_delta']) {
+    $form[$current_file_count]['#attributes']['class'][] = 'ajax-new-content';
+  }
+  // Otherwise just add the new content class on a placeholder.
+  else {
+    $form['#suffix'] .= '<span class="ajax-new-content"></span>';
+  }
+
+  $output = theme('status_messages') . drupal_render($form);
+  $js = drupal_add_js();
+  $settings = call_user_func_array('array_merge_recursive', $js['settings']['data']);
+
+  $commands[] = ajax_command_replace(NULL, $output, $settings);
+  return array('#type' => 'ajax', '#commands' => $commands);
+}
+
 /**
  * Implements hook_image_default_styles().
  */
@@ -345,110 +333,6 @@ function media_page_alter(&$page) {
       }
     }
   }
-
-  // Check if there are file types that need migration and display a message
-  // to user if so.
-  $menu = menu_get_item();
-  if (variable_get('media__display_types_migration_mess', TRUE) && $menu['path'] == 'admin/structure/file-types') {
-    if ($migratable_types = _media_get_migratable_file_types()) {
-      drupal_set_message(t('There are disabled/deleted file types that can be migrated to their new alternatives. Visit <a href="!url">migration page</a> to get more information.', array('!url' => url('admin/structure/file-types/upgrade'))));
-    }
-  }
-}
-
-/**
- * Implements hook_element_info_alter().
- */
-function media_element_info_alter(&$types) {
-  $types['text_format']['#pre_render'][] = 'media_pre_render_text_format';
-}
-
-/**
- * Implements hook_file_operations().
- */
-function media_file_operations() {
-  $operations = array();
-
-  // If the multiform module is not installed, do not show this option.
-  if (module_exists('multiform')) {
-    $operations['edit_multiple'] = array(
-      'label' => t('Edit selected files'),
-      'callback' => 'media_file_operation_edit_multiple',
-    );
-  }
-
-  return $operations;
-}
-
-/**
- * Return a URL for editing an files.
- *
- * Works with an array of fids or a single fid.
- *
- * @param mixed $fids
- *   An array of file IDs or a single file ID.
- */
-function media_file_edit_url($fids) {
-  if (!is_array($fids)) {
-    $fids = array($fids);
-  }
-
-  if (count($fids) > 1) {
-    return 'admin/content/file/edit-multiple/' . implode(' ', $fids);
-  }
-  else {
-    return 'file/' . reset($fids) . '/edit';
-  }
-}
-
-/**
- * Callback for the edit operation.
- *
- * Redirects the user to the edit multiple files page.
- *
- * @param array $fids
- *   An array of file IDs.
- *
- * @see media_file_page_edit_multiple()
- */
-function media_file_operation_edit_multiple($fids) {
-  // The thumbnail browser returns TRUE/FALSE for each item, so use array keys.
-  $fids = array_keys(array_filter($fids));
-  drupal_goto(media_file_edit_url($fids), array('query' => drupal_get_destination()));
-}
-
-/**
- * Implements hook_forms().
- */
-function media_forms($form_id, $args) {
-  $forms = array();
-  // To support the multiedit form, each form has to have a unique ID.
-  // So we name all the forms media_edit_N where the first requested form is
-  // media_edit_0, 2nd is media_edit_1, etc.
-  module_load_include('inc', 'file_entity', 'file_entity.pages');
-  if ($form_id != 'media_edit' && (strpos($form_id, 'media_edit') === 0)) {
-    $forms[$form_id] = array(
-      'callback' => 'file_entity_edit',
-    );
-  }
-  return $forms;
-}
-
-/**
- * Implements hook_form_FIELD_UI_FIELD_SETTINGS_FORM_alter().
- *
- * @todo: Respect field settings in 7.x-2.x and handle them in the media widget
- * UI.
- */
-function media_form_field_ui_field_settings_form_alter(&$form, &$form_state) {
-  // On file fields that use the media widget we need remove specific fields.
-  if ($form['field']['type']['#value'] == 'file') {
-    $fields = field_info_instances($form['#entity_type'], $form['#bundle']);
-    if ($fields[$form['field']['field_name']['#value']]['widget']['type'] == 'media_generic') {
-      $form['field']['settings']['display_field']['#access'] = FALSE;
-      $form['field']['settings']['display_default']['#access'] = FALSE;
-    }
-  }
 }
 
 /**
@@ -460,9 +344,6 @@ function media_form_field_ui_field_settings_form_alter(&$form, &$form_state) {
 function media_form_field_ui_field_edit_form_alter(&$form, &$form_state) {
   // On file fields that use the media widget we need remove specific fields.
   if ($form['#field']['type'] == 'file' && $form['instance']['widget']['type']['#value'] == 'media_generic') {
-    $form['field']['settings']['display_field']['#access'] = FALSE;
-    $form['field']['settings']['display_default']['#access'] = FALSE;
-    $form['instance']['settings']['description_field']['#access'] = FALSE;
     $form['instance']['settings']['file_extensions']['#title'] = t('Allowed file extensions for uploaded files');
     $form['instance']['settings']['file_extensions']['#maxlength'] = 255;
   }
@@ -475,6 +356,13 @@ function media_form_field_ui_field_edit_form_alter(&$form, &$form_state) {
     // Do not increase maxlength of file extensions for image fields, since
     // presumably they will not need a long list of extensions.
   }
+
+  // Add a validation function to any field instance which uses the media widget
+  // to ensure that the upload destination scheme is one of the allowed schemes.
+  if ($form['instance']['widget']['type']['#value'] == 'media_generic') {
+    $form['#validate'][] = 'media_field_instance_validate';
+  }
+
   if ($form['#instance']['entity_type'] == 'file') {
     $form['instance']['settings']['wysiwyg_override'] = array(
       '#type' => 'checkbox',
@@ -486,19 +374,15 @@ function media_form_field_ui_field_edit_form_alter(&$form, &$form_state) {
 }
 
 /**
- * Implements hook_form_FORM_ID_alter().
+ * Validation handler; ensure that the upload destination scheme is one of the
+ * allowed schemes.
  */
-function media_form_file_entity_edit_alter(&$form, &$form_state) {
-  // Make adjustments to the file edit form when used in a CTools modal.
-  if (!empty($form_state['ajax'])) {
-    // Remove the preview and the delete button.
-    $form['preview']['#access'] = FALSE;
-    $form['actions']['delete']['#access'] = FALSE;
+function media_field_instance_validate($form, &$form_state) {
+  $allowed_schemes = $form_state['values']['instance']['widget']['settings']['allowed_schemes'];
+  $upload_destination = $form_state['values']['field']['settings']['uri_scheme'];
 
-    // Convert the cancel link to a button which triggers a modal close.
-    $form['actions']['cancel']['#attributes']['class'][] = 'button';
-    $form['actions']['cancel']['#attributes']['class'][] = 'button-no';
-    $form['actions']['cancel']['#attributes']['class'][] = 'ctools-close-modal';
+  if (!in_array($upload_destination, array_filter($allowed_schemes))) {
+    form_set_error('allowed_schemes', t('The upload destination must be one of the allowed schemes.'));
   }
 }
 
@@ -534,87 +418,12 @@ function media_browser_form_submit($form, &$form_state) {
     $parameters = array('query' => array('render' => 'media-popup', 'fid' => $file->fid));
   }
 
-  // Multi upload.
-  if (!empty($form_state['files'])) {
-    $files = $form_state['files'];
-    $url = 'media/browser';
-    $parameters = array('query' => array('render' => 'media-popup', 'fid' => array_keys($files)));
-  }
-
   // If $url is set, we had some sort of upload, so redirect the form.
   if (!empty($url)) {
     $form_state['redirect'] = array($url, $parameters);
   }
 }
 
-/**
- * Implements hook_form_FORM_ID_alter().
- */
-function media_form_wysiwyg_profile_form_alter(&$form, &$form_state) {
-  // Add warnings if the media filter is disabled for the WYSIWYG's text format.
-  $form['buttons']['drupal']['media']['#element_validate'][] = 'media_wysiwyg_button_element_validate';
-  $form['buttons']['drupal']['media']['#after_build'][] = 'media_wysiwyg_button_element_validate';
-  form_load_include($form_state, 'inc', 'media', 'wysiwyg_plugins/media');
-}
-
-/**
- * Access callback for the media-multi form.
- *
- * @param $files
- *   An array of files being editing on the multiform.
- * @param $op
- *   A string containing the operation requested, such as 'update'.
- * @return
- *   TRUE if the current user has access to edit all of the files, otherwise FALSE.
- */
-function _media_file_entity_access_recursive($files, $op) {
-  // Check that the current user can access each file.
-  if (!empty($files)) {
-    foreach ($files as $file) {
-      if (!file_entity_access($op, $file)) {
-        return FALSE;
-      }
-    }
-    return TRUE;
-  }
-  return FALSE;
-}
-
-/* ***************************************** */
-/* API FUNCTIONS                             */
-/* ***************************************** */
-
-/**
- * Load callback for %media_multi placeholder in menu paths.
- *
- * @param string $fids
- *   Separated by space (e.g., "3 6 12 99"). This often appears as "+" within
- *   URLs (e.g., "3+6+12+99"), but Drupal automatically decodes paths when
- *   intializing $_GET['q'].
- *
- * @return array
- *   An array of corresponding file entities.
- */
-function media_multi_load($fids) {
-  return file_load_multiple(explode(' ', $fids));
-}
-
-/* ***************************************** */
-/* Callbacks                                 */
-/* ***************************************** */
-
-/**
- * Process callback for the media_browser element.
- */
-function media_file_list_element_process($element, $edit, $form_state, $form) {
-  $element['list'] = array(
-    '#type'     => 'select',
-    '#options'  => $element['#options'],
-    '#size'     => variable_get('media__file_list_size', 10),
-  );
-  return $element;
-}
-
 /**
  * Implements hook_library().
  */
@@ -682,7 +491,7 @@ function media_library() {
  * will default to the administration theme, unless set otherwise.
  */
 function media_dialog_get_theme_name() {
-  return variable_get('media__dialog_theme', variable_get('admin_theme'));
+  return variable_get('media_dialog_theme', variable_get('admin_theme'));
 }
 
 /**
@@ -808,16 +617,16 @@ function media_recursive_check_plain(&$value, $key) {
  * Implements hook_element_info().
  */
 function media_element_info() {
-  $types = array();
   $types['media'] = array(
     '#input' => TRUE,
     '#process' => array('media_element_process'),
-    // '#value_callback' => 'media_element_value',
+    '#value_callback' => 'media_file_value',
     '#element_validate' => array('media_element_validate'),
-    '#theme_wrappers' => array('container'),
-    '#progress_indicator' => 'throbber',
+    '#pre_render' => array('media_element_pre_render'),
+    '#theme' => 'media_element',
+    '#theme_wrappers' => array('form_element'),
+    '#size' => 22,
     '#extended' => FALSE,
-    '#required' => FALSE,
     '#media_options' => array(
       'global' => array(
         // Example: array('image', 'audio');
@@ -826,64 +635,97 @@ function media_element_info() {
         'schemes' => array(),
       ),
     ),
-    '#attributes' => array(
-      'class' => array('media-widget', 'form-item'),
-    ),
     '#attached' => array(
       'library' => array(
         array('media', 'media_browser'),
       ),
     ),
   );
+
+  $setting = array();
+  $setting['media']['global'] = $types['media']['#media_options'];
+
+  $types['media']['#attached']['js'][] = array(
+    'type' => 'setting',
+    'data' => $setting,
+  );
+
   return $types;
 }
 
 /**
  * Process callback for the media form element.
  */
-function media_element_process(&$element, &$form_state, $form) {
-  $fid = isset($element['#value']['fid']) ? $element['#value']['fid'] : 0;
-  $file = $fid ? file_load($fid) : FALSE;
-
-  // Add the CTools modal JavaScript for the edit button if necessary.
+function media_element_process($element, &$form_state, $form) {
   ctools_include('modal');
   ctools_include('ajax');
   ctools_modal_add_js();
+  $fid = isset($element['#value']['fid']) ? $element['#value']['fid'] : 0;
 
   // Set some default element properties.
-  $element['#file'] = $file;
-
-  $element['title'] = array(
-    '#type' => 'item',
-    '#title' => $element['#title'],
-    '#description' => $element['#description'],
-    '#required' => $element['#required'],
-    '#weight' => -100,
+  $element['#file'] = $fid ? file_load($fid) : FALSE;
+  $element['#tree'] = TRUE;
+
+  $ajax_settings = array(
+    'path' => 'media/ajax/' . implode('/', $element['#array_parents']) . '/' . $form['form_build_id']['#value'],
+    'wrapper' => $element['#id'] . '-ajax-wrapper',
+    'effect' => 'fade',
+  );
+
+  // Set up the buttons first since we need to check if they were clicked.
+  $element['attach_button'] = array(
+    '#name' => implode('_', $element['#parents']) . '_attach_button',
+    '#type' => 'submit',
+    '#value' => t('Attach'),
+    '#validate' => array(),
+    '#submit' => array('media_file_submit'),
+    '#limit_validation_errors' => array($element['#parents']),
+    '#ajax' => $ajax_settings,
+    '#attributes' => array('class' => array('attach')),
+    '#weight' => -1,
   );
-  if (isset($element['#title_display'])) {
-    $element['title']['#title_display'] = $element['#title_display'];
-  }
 
-  // @todo This should load from the JS in case of a failed form submission.
   $element['preview'] = array(
-    '#prefix' => '<div class="preview launcher">',
+    'content' => array(),
+    '#prefix' => '<div class="preview">',
     '#suffix' => '</div>',
-    '#weight' => 0,
-    'content' => $file ? media_get_thumbnail_preview($file) : array(),
+    '#ajax' => $ajax_settings,
+    '#weight' => -10,
   );
 
-  // @todo: Perhaps this language logic should be handled by JS since the state
-  // changes on client side after choosing an item.
-  $element['select'] = array(
+  // Substitute the JS preview for a true file thumbnail once the file is
+  // attached.
+  if ($fid && $element['#file']) {
+    $element['preview']['content'] = media_get_thumbnail_preview($element['#file']);
+  }
+
+  // The file ID field itself.
+  $element['upload'] = array(
+    '#name' => 'media[' . implode('_', $element['#parents']) . ']',
+    '#type' => 'textfield',
+    '#title' => t('Enter the ID of an existing file'),
+    '#title_display' => 'invisible',
+    '#field_prefix' => t('File ID'),
+    '#size' => $element['#size'],
+    '#theme_wrappers' => array(),
+    '#attributes' => array('class' => array('upload')),
+    '#weight' => -9,
+  );
+
+  $element['browse_button'] = array(
     '#type' => 'link',
     '#href' => '',
-    '#title' => t('Select'),
-    '#attributes' => array('class' => array('button', 'launcher')),
+    '#title' => t('Browse'),
+    '#attributes' => array('class' => array('button', 'browse', 'element-hidden')),
     '#options' => array('fragment' => FALSE, 'external' => TRUE),
-    '#weight' => 10,
+    '#weight' => -8,
   );
-  // @todo Figure out how to update the preview image after the Edit modal is
-  // closed.
+
+  // Force the progress indicator for the remove button to be either 'none' or
+  // 'throbber', even if the upload button is using something else.
+  $ajax_settings['progress']['type'] = 'throbber';
+  $ajax_settings['progress']['message'] = NULL;
+  $ajax_settings['effect'] = 'none';
   $element['edit'] = array(
     '#type' => 'link',
     '#href' => 'media/' . $fid . '/edit/nojs',
@@ -896,42 +738,128 @@ function media_element_process(&$element, &$form_state, $form) {
       ),
     ),
     '#weight' => 20,
-    '#access' => $file ? file_entity_access('update', $file) : TRUE, // only do perm check for existing files
+    '#access' => $element['#file'] ? file_entity_access('update', $element['#file']) : FALSE,
   );
-  $element['remove'] = array(
-    '#type' => 'link',
-    '#href' => '',
-    '#title' => t('Remove'),
-    '#attributes' => array('class' => array('button', 'remove')),
-    '#options' => array('fragment' => FALSE, 'external' => TRUE),
-    '#weight' => 30,
+  $element['remove_button'] = array(
+    '#name' => implode('_', $element['#parents']) . '_remove_button',
+    '#type' => 'submit',
+    '#value' => t('Remove'),
+    '#validate' => array(),
+    '#submit' => array('media_file_submit'),
+    '#limit_validation_errors' => array($element['#parents']),
+    '#ajax' => $ajax_settings,
+    '#attributes' => array('class' => array('remove')),
+    '#weight' => 0,
   );
 
   $element['fid'] = array(
     '#type' => 'hidden',
     '#value' => $fid,
     '#attributes' => array('class' => array('fid')),
-    '#weight' => 100,
   );
 
   // Media browser attach code.
   $element['#attached']['js'][] = drupal_get_path('module', 'media') . '/js/media.js';
 
-  $setting = array();
-  $setting['media']['elements'][$element['#id']] = $element['#media_options'];
-
-  $element['#attached']['js'][] = array(
-    'type' => 'setting',
-    'data' => $setting,
+  // Add the media options to the page as JavaScript settings.
+  $element['browse_button']['#attached']['js'] = array(
+    array(
+      'type' => 'setting',
+      'data' => array('media' => array('elements' => array('#' . $element['#id'] => $element['#media_options'])))
+    )
   );
 
-  // @todo: Might need to think about this. All settings would likely apply to
-  // all media in a multi-value, but what about passing the existing fid?
   module_load_include('inc', 'media', 'includes/media.browser');
   media_attach_browser_js($element);
 
+  // Prefix and suffix used for Ajax replacement.
+  $element['#prefix'] = '<div id="' . $element['#id'] . '-ajax-wrapper">';
+  $element['#suffix'] = '</div>';
+
   return $element;
-  // @todo: make this work for file and image fields.
+}
+
+/**
+ * Implements hook_form_FORM_ID_alter().
+ */
+function media_form_file_entity_edit_alter(&$form, &$form_state) {
+  // Make adjustments to the file edit form when used in a CTools modal.
+  if (!empty($form_state['ajax'])) {
+    // Remove the preview and the delete button.
+    $form['preview']['#access'] = FALSE;
+    $form['actions']['delete']['#access'] = FALSE;
+
+    // Convert the cancel link to a button which triggers a modal close.
+    $form['actions']['cancel']['#attributes']['class'][] = 'button';
+    $form['actions']['cancel']['#attributes']['class'][] = 'button-no';
+    $form['actions']['cancel']['#attributes']['class'][] = 'ctools-close-modal';
+  }
+}
+
+/**
+ * The #value_callback for a media type element.
+ */
+function media_file_value(&$element, $input = FALSE, $form_state = NULL) {
+  $fid = 0;
+
+  // Find the current value of this field from the form state.
+  $form_state_fid = $form_state['values'];
+  foreach ($element['#parents'] as $parent) {
+    $form_state_fid = isset($form_state_fid[$parent]) ? $form_state_fid[$parent] : 0;
+  }
+
+  if ($element['#extended'] && isset($form_state_fid['fid'])) {
+    $fid = $form_state_fid['fid'];
+  }
+  elseif (is_numeric($form_state_fid)) {
+    $fid = $form_state_fid;
+  }
+
+  // Process any input and attach files.
+  if ($input !== FALSE) {
+    $return = $input;
+
+    // Attachments take priority over all other values.
+    if ($file = media_attach_file($element)) {
+      $fid = $file->fid;
+    }
+    else {
+      // Check for #filefield_value_callback values.
+      // Because FAPI does not allow multiple #value_callback values like it
+      // does for #element_validate and #process, this fills the missing
+      // functionality to allow File fields to be extended through FAPI.
+      if (isset($element['#file_value_callbacks'])) {
+        foreach ($element['#file_value_callbacks'] as $callback) {
+          $callback($element, $input, $form_state);
+        }
+      }
+      // Load file if the FID has changed to confirm it exists.
+      if (isset($input['fid']) && $file = file_load($input['fid'])) {
+        $fid = $file->fid;
+      }
+    }
+  }
+
+  // If there is no input, set the default value.
+  else {
+    if ($element['#extended']) {
+      $default_fid = isset($element['#default_value']['fid']) ? $element['#default_value']['fid'] : 0;
+      $return = isset($element['#default_value']) ? $element['#default_value'] : array('fid' => 0);
+    }
+    else {
+      $default_fid = isset($element['#default_value']) ? $element['#default_value'] : 0;
+      $return = array('fid' => 0);
+    }
+
+    // Confirm that the file exists when used as a default value.
+    if ($default_fid && $file = file_load($default_fid)) {
+      $fid = $file->fid;
+    }
+  }
+
+  $return['fid'] = $fid;
+
+  return $return;
 }
 
 /**
@@ -941,41 +869,149 @@ function media_element_process(&$element, &$form_state, $form) {
  * necessary in order to respect the #required property.
  */
 function media_element_validate(&$element, &$form_state) {
-  if ($element['#required']) {
-    $has_value = FALSE;
-    $widget_parents = $element['#array_parents'];
-    array_pop($widget_parents);
-    $items = drupal_array_get_nested_value($form_state['values'], $widget_parents);
-    foreach ($items as $value) {
-      if (is_array($value) && !empty($value['fid'])) {
-        $has_value = TRUE;
-      }
-    }
-    if (!$has_value) {
-      form_error($element, t('%element_title is required.', array('%element_title' => $element['#title'])));
+  $clicked_button = end($form_state['triggering_element']['#parents']);
+
+  // Check required property based on the FID.
+  if ($element['#required'] && empty($element['fid']['#value']) && !in_array($clicked_button, array('attach_button', 'remove_button'))) {
+    form_error($element['browse_button'], t('!name field is required.', array('!name' => $element['#title'])));
+  }
+
+  // Consolidate the array value of this field to a single FID.
+  if (!$element['#extended']) {
+    form_set_value($element, $element['fid']['#value'], $form_state);
+  }
+}
+
+/**
+ * Form submission handler for attach / remove buttons of media elements.
+ *
+ * @see media_element_process()
+ */
+function media_file_submit($form, &$form_state) {
+  // Determine whether it was the attach or remove button that was clicked, and
+  // set $element to the managed_file element that contains that button.
+  $parents = $form_state['triggering_element']['#array_parents'];
+  $button_key = array_pop($parents);
+  $element = drupal_array_get_nested_value($form, $parents);
+
+  // No action is needed here for the attach button, because all media
+  // attachments on the form are processed by media_file_value() regardless of
+  // which button was clicked. Action is needed here for the remove button,
+  // because we only remove a file in response to its remove button being
+  // clicked.
+  if ($button_key == 'remove_button') {
+    // If it's a temporary file we can safely remove it immediately, otherwise
+    // it's up to the implementing module to clean up files that are in use.
+    if ($element['#file'] && $element['#file']->status == 0) {
+      file_delete($element['#file']);
     }
+    // Update both $form_state['values'] and $form_state['input'] to reflect
+    // that the file has been removed, so that the form is rebuilt correctly.
+    // $form_state['values'] must be updated in case additional submit handlers
+    // run, and for form building functions that run during the rebuild, such as
+    // when the media element is part of a field widget.
+    // $form_state['input'] must be updated so that media_file_value() has
+    // correct information during the rebuild.
+    $values_element = $element['#extended'] ? $element['fid'] : $element;
+    form_set_value($values_element, NULL, $form_state);
+    drupal_array_set_nested_value($form_state['input'], $values_element['#parents'], NULL);
   }
+
+  // Set the form to rebuild so that $form is correctly updated in response to
+  // processing the file removal. Since this function did not change $form_state
+  // if the upload button was clicked, a rebuild isn't necessary in that
+  // situation and setting $form_state['redirect'] to FALSE would suffice.
+  // However, we choose to always rebuild, to keep the form processing workflow
+  // consistent between the two buttons.
+  $form_state['rebuild'] = TRUE;
 }
 
 /**
- * Implements hook_filter_info().
+ * Attaches any files that have been referenced by a media element.
+ *
+ * @param $element
+ *   The FAPI element whose files are being attached.
+ *
+ * @return
+ *   The file object representing the file that was attached, or FALSE if no
+ *   file was attached.
  */
-function media_filter_info() {
-  $filters['media_filter'] = array(
-    'title' => t('Convert Media tags to markup'),
-    'description' => t('This filter will convert [[{type:media... ]] tags into markup.'),
-    'process callback' => 'media_filter',
-    'weight' => 2,
-    // @TODO not implemented
-    'tips callback' => 'media_filter_tips',
-  );
+function media_attach_file($element) {
+  $upload_name = implode('_', $element['#parents']);
+  if (empty($_POST['media'][$upload_name])) {
+    return FALSE;
+  }
 
-  // If the WYSIWYG module is enabled, add additional help.
-  if (module_exists('wysiwyg')) {
-    $filters['media_filter']['description'] .= ' ' . t('This must be enabled for the Media WYSIWYG integration to work with this input format.');
+  if (!$file = file_load($_POST['media'][$upload_name])) {
+    watchdog('file', 'The file upload failed. %upload', array('%upload' => $upload_name));
+    form_set_error($upload_name, t('The file in the !name field was unable to be uploaded.', array('!name' => $element['#title'])));
+    return FALSE;
   }
 
-  return $filters;
+  return $file;
+}
+
+/**
+ * Returns HTML for a managed file element.
+ *
+ * @param $variables
+ *   An associative array containing:
+ *   - element: A render element representing the file.
+ *
+ * @ingroup themeable
+ */
+function theme_media_element($variables) {
+  $element = $variables['element'];
+
+  $attributes = array();
+  if (isset($element['#id'])) {
+    $attributes['id'] = $element['#id'];
+  }
+  if (!empty($element['#attributes']['class'])) {
+    $attributes['class'] = (array) $element['#attributes']['class'];
+  }
+  $attributes['class'][] = 'form-media';
+
+  // This wrapper is required to apply JS behaviors and CSS styling.
+  $output = '';
+  $output .= '<div' . drupal_attributes($attributes) . '>';
+  $output .= drupal_render_children($element);
+  $output .= '</div>';
+  return $output;
+}
+
+/**
+ * #pre_render callback to hide display of the browse/attach or remove controls.
+ *
+ * Browse/attach controls are hidden when a file is already attached.
+ * Remove controls are hidden when there is no file attached. Controls are
+ * hidden here instead of in media_element_process(), because #access for these
+ * buttons depends on the media element's #value. See the documentation of
+ * form_builder() for more detailed information about the relationship between
+ * #process, #value, and #access.
+ *
+ * Because #access is set here, it affects display only and does not prevent
+ * JavaScript or other untrusted code from submitting the form as though access
+ * were enabled. The form processing functions for these elements should not
+ * assume that the buttons can't be "clicked" just because they are not
+ * displayed.
+ *
+ * @see media_element_process()
+ * @see form_builder()
+ */
+function media_element_pre_render($element) {
+  // If we already have a file, we don't want to show the browse and attach
+  // controls.
+  if (!empty($element['#value']['fid'])) {
+    $element['upload']['#access'] = FALSE;
+    $element['browse_button']['#access'] = FALSE;
+    $element['attach_button']['#access'] = FALSE;
+  }
+  // If we don't already have a file, there is nothing to remove.
+  else {
+    $element['remove_button']['#access'] = FALSE;
+  }
+  return $element;
 }
 
 /**
@@ -995,13 +1031,12 @@ function media_get_thumbnail_preview($file, $link = NULL) {
   if (!file_type_is_enabled($file->type)) {
     $file->type = file_get_type($file);
   }
-  // @todo should CSS be attached to the form element here?
-  // $element['#attached']['css'][] = drupal_get_path('module', 'media') . '/css/media.css';
-  drupal_add_css(drupal_get_path('module', 'media') . '/css/media.css');
+
   $preview = file_view_file($file, 'preview');
   $preview['#show_names'] = TRUE;
   $preview['#add_link'] = $link;
   $preview['#theme_wrappers'][] = 'media_thumbnail';
+  $preview['#attached']['css'][] = drupal_get_path('module', 'media') . '/css/media.css';
   return $preview;
 }
 
@@ -1018,7 +1053,7 @@ function media_get_thumbnail_preview($file, $link = NULL) {
  *
  * @see hook_file_validate()
  */
-function media_file_validate_types(stdClass $file, $types) {
+function media_file_validate_types($file, $types) {
   $errors = array();
   if (!in_array(file_get_type($file), $types)) {
     $errors[] = t('Only the following types of files are allowed to be uploaded: %types-allowed', array('%types-allowed' => implode(', ', $types)));
@@ -1050,55 +1085,76 @@ function media_file_displays_alter(&$displays, $file, $view_mode) {
         $file->{$field_name} = $value;}
     }
   }
+
+  // Alt and title are special.
+  // @see file_entity_file_load
+  $alt = variable_get('file_entity_alt', '[file:field_file_image_alt_text]');
+  $title = variable_get('file_entity_title', '[file:field_file_image_title_text]');
+
+  $replace_options = array(
+    'clear' => TRUE,
+    'sanitize' => FALSE,
+  );
+
+  // Load alt and title text from fields.
+  if (!empty($alt)) {
+    $file->alt = token_replace($alt, array('file' => $file), $replace_options);
+  }
+  if (!empty($title)) {
+    $file->title = token_replace($title, array('file' => $file), $replace_options);
+  }
 }
 
 /**
- * Implements hook_file_default_displays_alter().
+ * For sanity in grammar.
+ *
+ * @see media_set_browser_params()
  */
-function media_file_default_displays_alter(&$file_displays) {
-  // Image previews should be displayed using the media image style.
-  if (isset($file_displays['image__preview__file_field_image'])) {
-    $file_displays['image__preview__file_field_image']->settings['image_style'] = 'media_thumbnail';
-  }
+function media_get_browser_params() {
+  return media_set_browser_params();
+}
 
-  // Video previews should be displayed using a large filetype icon.
-  if (isset($file_displays['video__preview__file_field_file_default'])) {
-    $file_displays['video__preview__file_field_file_default']->status = FALSE;
-  }
+/**
+ * Provides a singleton of the params passed to the media browser.
+ *
+ * This is useful in situations like form alters because callers can pass
+ * id="wysiywg_form" or whatever they want, and a form alter could pick this up.
+ * We may want to change the hook_media_browser_plugin_view() implementations to
+ * use this function instead of being passed params for consistency.
+ *
+ * It also offers a chance for some meddler to meddle with them.
+ *
+ * @see media_browser()
+ */
+function media_set_browser_params() {
+  $params = &drupal_static(__FUNCTION__, array());
+
+  if (empty($params)) {
+    // Build out browser settings. Permissions- and security-related behaviors
+    // should not rely on these parameters, since they come from the HTTP query.
+    // @TODO make sure we treat parameters as user input.
+    $params = drupal_get_query_parameters() + array(
+        'types' => array(),
+        'multiselect' => FALSE,
+      );
 
-  $file_display = new stdClass();
-  $file_display->api_version = 1;
-  $file_display->name = 'video__preview__file_field_media_large_icon';
-  $file_display->weight = 50;
-  $file_display->status = TRUE;
-  $file_display->settings = '';
-  $file_displays['video__preview__file_field_media_large_icon'] = $file_display;
-
-  // Audio previews should be displayed using a large filetype icon.
-  if (isset($file_displays['audio__preview__file_field_file_default'])) {
-    $file_displays['audio__preview__file_field_file_default']->status = FALSE;
-  }
+    // Transform text 'true' and 'false' to actual booleans.
+    foreach ($params as $k => $v) {
+      if ($v === 'true') {
+        $params[$k] = TRUE;
+      }
+      elseif ($v === 'false') {
+        $params[$k] = FALSE;
+      }
+    }
 
-  $file_display = new stdClass();
-  $file_display->api_version = 1;
-  $file_display->name = 'audio__preview__file_field_media_large_icon';
-  $file_display->weight = 50;
-  $file_display->status = TRUE;
-  $file_display->settings = '';
-  $file_displays['audio__preview__file_field_media_large_icon'] = $file_display;
-
-  // Document previews should be displayed using a large filetype icon.
-  if (isset($file_displays['document__preview__file_field_file_default'])) {
-    $file_displays['document__preview__file_field_file_default']->status = FALSE;
+    array_walk_recursive($params, 'media_recursive_check_plain');
+
+    // Allow modules to alter the parameters.
+    drupal_alter('media_browser_params', $params);
   }
 
-  $file_display = new stdClass();
-  $file_display->api_version = 1;
-  $file_display->name = 'document__preview__file_field_media_large_icon';
-  $file_display->weight = 50;
-  $file_display->status = TRUE;
-  $file_display->settings = '';
-  $file_displays['document__preview__file_field_media_large_icon'] = $file_display;
+  return $params;
 }
 
 /**
@@ -1132,20 +1188,18 @@ function media_form_file_entity_admin_file_alter(&$form, $form_state) {
   // selected and they try to switch between the "Thumbnail" and "List" local
   // tasks.
   $path = drupal_get_path('module', 'media');
-  require_once $path . '/includes/media.browser.inc';
   $form['#attributes']['class'][] = 'file-entity-admin-file-form';
   $form['#attached']['js'][] = $path . '/js/media.admin.js';
   $form['#attached']['css'][] = $path . '/css/media.css';
-  media_attach_browser_js($form);
 
   // By default, this form contains a table select element called "files". For
   // the 'thumbnails' tab, Media generates a thumbnail for each file and
   // replaces the tableselect with a grid of thumbnails.
   if (arg(3) == 'thumbnails') {
-    if (empty($form['admin']['files'])) {
+    if (empty($form['admin']['files']['#options'])) {
       // Display empty text if there are no files.
       $form['admin']['files'] = array(
-        '#markup' => '<p>' . $form['files']['#empty'] . '</p>',
+        '#markup' => '<p>' . $form['admin']['files']['#empty'] . '</p>',
       );
     }
     else {
@@ -1245,6 +1299,31 @@ function media_get_browser_plugin_info() {
   return $info;
 }
 
+/**
+ * Gets the MIME type mapped to a given extension.
+ *
+ * @param string $extension
+ *   A file extension.
+ *
+ * @return string
+ *   The MIME type associated with the extension or FALSE if the extension does
+ *   not have an associated MIME type.
+ *
+ * @see file_mimetype_mapping()
+ */
+function media_get_extension_mimetype($extension) {
+  include_once DRUPAL_ROOT . '/includes/file.mimetypes.inc';
+  $mimetype_mappings = file_mimetype_mapping();
+
+  if (isset($mimetype_mappings['extensions'][$extension])) {
+    $id = $mimetype_mappings['extensions'][$extension];
+    return $mimetype_mappings['mimetypes'][$id];
+  }
+  else {
+    return FALSE;
+  }
+}
+
 /**
  * Helper function to get a list of local stream wrappers.
  */
@@ -1261,24 +1340,3 @@ function media_get_remote_stream_wrappers() {
   $wrappers = array_diff_key($wrappers, file_get_stream_wrappers(STREAM_WRAPPERS_LOCAL_HIDDEN));
   return $wrappers;
 }
-
-
-/**
- * Checks if there are any files that belong to disabled or deleted file
- * types.
- *
- * @return Array of file types (machine names) that are candidates for
- *   migration.
- */
-function _media_get_migratable_file_types() {
-  $query = db_select('file_managed', 'f')
-    ->fields('f', array('type'))
-    ->distinct();
-  $types = $query->execute()->fetchCol();
-  $enabled_types = array();
-  foreach (file_type_get_enabled_types() as $type) {
-    $enabled_types[] = $type->type;
-  }
-
-  return array_diff($types, $enabled_types);
-}
diff --git a/drupal7/sites/all/modules/media/modules/media_bulk_upload/includes/MediaBrowserBulkUpload.inc b/drupal7/sites/all/modules/media/modules/media_bulk_upload/includes/MediaBrowserBulkUpload.inc
new file mode 100644
index 00000000..9dbc9833
--- /dev/null
+++ b/drupal7/sites/all/modules/media/modules/media_bulk_upload/includes/MediaBrowserBulkUpload.inc
@@ -0,0 +1,30 @@
+<?php
+
+/**
+ * @file
+ * Definition of MediaBrowserBulkUpload.
+ */
+
+/**
+ * Media browser plugin for showing the bulk upload form.
+ *
+ * @deprecated
+ */
+class MediaBrowserBulkUpload extends MediaBrowserUpload {
+  /**
+   * Overrides MediaBrowserPlugin::view().
+   */
+  public function view() {
+    module_load_include('inc', 'file_entity', 'file_entity.pages');
+
+    $build = array();
+    if ($this->params['multiselect']) {
+      $build['form'] = drupal_get_form('file_entity_add_upload_multiple', $this->params);
+    }
+    else {
+      $build['form'] = drupal_get_form('file_entity_add_upload', $this->params);
+    }
+
+    return $build;
+  }
+}
diff --git a/drupal7/sites/all/modules/media/modules/media_bulk_upload/includes/media_bulk_upload.admin.inc b/drupal7/sites/all/modules/media/modules/media_bulk_upload/includes/media_bulk_upload.admin.inc
new file mode 100644
index 00000000..bc0b77f6
--- /dev/null
+++ b/drupal7/sites/all/modules/media/modules/media_bulk_upload/includes/media_bulk_upload.admin.inc
@@ -0,0 +1,155 @@
+<?php
+
+/**
+ * @file
+ * This file contains the admin functions for the Media Bulk Upload module.
+ */
+
+/**
+ * Form callback for mass import.
+ */
+function media_bulk_upload_import($form, &$form_state) {
+  if (!isset($form_state['storage']['files'])) {
+    $form_state['storage']['step'] = 'choose';
+    $form_state['storage']['next_step'] = 'preview';
+    $form['directory'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Directory'),
+      '#description' => t('Enter the absolute directory on the web server to look for files. Subdirectories inside this directory will not be scanned.'),
+      '#required' => TRUE,
+    );
+
+    $form['pattern'] = array(
+      '#type' => 'textarea',
+      '#title' => t('Pattern'),
+      '#description' => t("Only files matching these patterns will be imported. Enter one pattern per line. The '*' character is a wildcard. Example patterns are %png_example to import all PNG files.", array('%png_example' => '*.png')),
+      '#default_value' => '*',
+      '#required' => TRUE,
+    );
+
+    $form['actions'] = array('#type' => 'actions');
+    $form['actions']['submit'] = array(
+      '#type' => 'submit',
+      '#value' => t('Preview'),
+    );
+    $form['actions']['cancel'] = array(
+      '#type' => 'link',
+      '#title' => t('Cancel'),
+      '#href' => isset($_GET['destination']) ? $_GET['destination'] : 'admin/content/file',
+    );
+  }
+  else {
+    $form['preview'] = array(
+      '#markup' => theme('item_list', array('items' => $form_state['storage']['files'])),
+    );
+
+    $form = confirm_form($form, t('Import these files?'), 'admin/content/file/import');
+  }
+  return $form;
+
+}
+
+/**
+ * Validate handler for media_import().
+ */
+function media_bulk_upload_import_validate($form, &$form_state) {
+  if ($form_state['values']['op'] != t('Confirm')) {
+    $directory = $form_state['values']['directory'];
+    $pattern = $form_state['values']['pattern'];
+    if (!is_dir($directory)) {
+      form_set_error('directory', t('The provided directory does not exist.'));
+    }
+    if (!is_readable($directory)) {
+      form_set_error('directory', t('The provided directory is not readable.'));
+    }
+
+    $pattern_quoted = preg_quote($pattern, '/');
+    $pattern_quoted = preg_replace('/(\r\n?|\n)/', '|', $pattern_quoted);
+    $pattern_quoted = strtr($pattern_quoted, array(
+      '\\|' => '|',
+      '\\*' => '.*',
+      '\\?' => '.?',
+    ));
+    $files = file_scan_directory($directory, '/^(' . $pattern_quoted . ')$/', array('recurse' => FALSE));
+    $files = array_keys($files);
+    if (empty($files)) {
+      form_set_error('pattern', t('No files were found in %directory matching the regular expression %pattern', array('%directory' => $directory, '%pattern' => $pattern_quoted)));
+    }
+    $form_state['storage']['files'] = $files;
+  }
+}
+
+/**
+ * Submit handler for media_import().
+ */
+function media_bulk_upload_import_submit($form, &$form_state) {
+  if ($form_state['values']['op'] == t('Confirm')) {
+    $files = $form_state['storage']['files'];
+    $batch = array(
+      'title' => t('Importing'),
+      'operations' => array(
+        array('media_bulk_upload_import_batch_import_files', array($files)),
+      ),
+      'finished' => 'media_bulk_upload_import_batch_import_complete',
+      'file' => drupal_get_path('module', 'media_bulk_upload') . '/includes/media_bulk_upload.admin.inc',
+    );
+    batch_set($batch);
+    return;
+
+  }
+  $form_state['rebuild'] = TRUE;
+}
+
+/**
+ * BatchAPI callback op for media import.
+ */
+function media_bulk_upload_import_batch_import_files($files, &$context) {
+  if (!isset($context['sandbox']['files'])) {
+    // This runs the first time the batch runs.
+    // This is stupid, but otherwise, I don't think it will work...
+    $context['results'] = array('success' => array(), 'errors' => array());
+    $context['sandbox']['max'] = count($files);
+    $context['sandbox']['files'] = $files;
+  }
+  $files =& $context['sandbox']['files'];
+
+  // Take a cut of files.  Let's do 10 at a time.
+  $import_batch_size = variable_get('media_bulk_upload_import_batch_size', 20);
+  $length = (count($files) > $import_batch_size) ? $import_batch_size : count($files);
+  $to_process = array_splice($files, 0, $length);
+  $image_in_message = '';
+
+  foreach ($to_process as $file) {
+    try {
+      $file_obj = media_parse_to_file($file);
+      $context['results']['success'][] = $file;
+      if (!$image_in_message) {
+        // @todo Is this load step really necessary? When there's time, test
+        //   this, and either remove it, or comment why it's needed.
+        $loaded_file = file_load($file_obj->fid);
+        $image_in_message = file_view_file($loaded_file, 'preview');
+      }
+    }
+    catch (Exception $e) {
+      $context['results']['errors'][] = $file . " Reason: " . $e->getMessage();
+    }
+  }
+
+  $context['message'] = "Importing " . theme('item_list', array('items' => $to_process));
+  // Show the image that is being imported.
+  $context['message'] .= drupal_render($image_in_message);
+
+  $context['finished'] = ($context['sandbox']['max'] - count($files)) / $context['sandbox']['max'];
+}
+
+/**
+ * BatchAPI complete callback for media import.
+ */
+function media_bulk_upload_import_batch_import_complete($success, $results, $operations) {
+  if ($results['errors']) {
+    drupal_set_message(theme('item_list', array('items' => $results['errors'])), 'error');
+  }
+  if ($results['success']) {
+    drupal_set_message(theme('item_list', array('items' => $results['success'])));
+  }
+}
diff --git a/drupal7/sites/all/modules/media/modules/media_bulk_upload/includes/media_bulk_upload.pages.inc b/drupal7/sites/all/modules/media/modules/media_bulk_upload/includes/media_bulk_upload.pages.inc
new file mode 100644
index 00000000..50d0b560
--- /dev/null
+++ b/drupal7/sites/all/modules/media/modules/media_bulk_upload/includes/media_bulk_upload.pages.inc
@@ -0,0 +1,66 @@
+<?php
+
+/**
+ * @file
+ * Common pages for the Media Bulk Upload module.
+ */
+
+/**
+ * Menu callback; Edit multiple files on the same page using multiform module.
+ *
+ * @todo When http://drupal.org/node/1227706 is fixed, filter the $files
+ * array using file_access($file, 'edit').
+ *
+ * @see media_bulk_upload_file_operation_edit_multiple()
+ */
+function media_bulk_upload_file_page_edit_multiple($files) {
+  if (empty($files)) {
+    return MENU_ACCESS_DENIED;
+  }
+
+  $forms = array();
+  foreach ($files as $file) {
+    // To maintain unique form_ids, append the file id.
+    $forms[] = array('media_edit_' . $file->fid, $file);
+  }
+
+  $form = call_user_func_array('multiform_get_form', $forms);
+  $form['#attributes']['class'][] = 'media-bulk-upload-multiedit-form';
+
+  // Add the title to each 'subform'.
+  foreach (element_children($form['multiform']) as $key) {
+    $fid = $form['multiform'][$key]['fid']['#value'];
+    $file = $files[$fid];
+    $title = t('<em>Edit @type</em> @title', array('@type' => $file->type, '@title' => $file->filename));
+    $form['multiform'][$key]['#prefix'] = '<h2>' . $title . '</h2>';
+    $form['multiform'][$key]['actions']['#access'] = FALSE;
+  }
+
+  if (isset($form['buttons']['Delete'])) {
+    $form['buttons']['Delete']['#access'] = FALSE;
+  }
+
+  // Add a cancel button at the bottom of the form.
+  $form['buttons']['cancel'] = array(
+    '#type' => 'link',
+    '#title' => t('Cancel'),
+    '#weight' => 50,
+  );
+  if (isset($_GET['destination'])) {
+    $form['buttons']['cancel']['#href'] = $_GET['destination'];
+  }
+  else if (user_access('administer files')) {
+    $form['buttons']['cancel']['#href'] = 'admin/content/file';
+  }
+  else {
+    $form['buttons']['cancel']['#href'] = '<front>';
+  }
+
+  // Override the page title since each file form sets a title.
+  drupal_set_title(t('Edit multiple files'));
+
+  // Allow other modules to alter the form.
+  drupal_alter('media_bulk_upload_edit_multiple_form', $form);
+
+  return $form;
+}
diff --git a/drupal7/sites/all/modules/media/modules/media_bulk_upload/media_bulk_upload.info b/drupal7/sites/all/modules/media/modules/media_bulk_upload/media_bulk_upload.info
new file mode 100644
index 00000000..a4414f9f
--- /dev/null
+++ b/drupal7/sites/all/modules/media/modules/media_bulk_upload/media_bulk_upload.info
@@ -0,0 +1,17 @@
+name = Media Bulk Upload
+description = Adds support for uploading multiple files at a time.
+package = Media
+core = 7.x
+
+dependencies[] = media
+dependencies[] = multiform
+dependencies[] = plupload
+
+files[] = includes/MediaBrowserBulkUpload.inc
+
+; Information added by Drupal.org packaging script on 2014-10-04
+version = "7.x-2.0-alpha4"
+core = "7.x"
+project = "media"
+datestamp = "1412422430"
+
diff --git a/drupal7/sites/all/modules/media/modules/media_bulk_upload/media_bulk_upload.install b/drupal7/sites/all/modules/media/modules/media_bulk_upload/media_bulk_upload.install
new file mode 100644
index 00000000..a7b0741c
--- /dev/null
+++ b/drupal7/sites/all/modules/media/modules/media_bulk_upload/media_bulk_upload.install
@@ -0,0 +1,14 @@
+<?php
+
+/**
+ * @file
+ * Install, update and uninstall functions for the Media Bulk Upload module.
+ */
+
+/**
+ * Implements hook_uninstall().
+ */
+function media_bulk_upload_uninstall() {
+  // Remove variables.
+  variable_del('media_bulk_upload_import_batch_size');
+}
diff --git a/drupal7/sites/all/modules/media/modules/media_bulk_upload/media_bulk_upload.module b/drupal7/sites/all/modules/media/modules/media_bulk_upload/media_bulk_upload.module
new file mode 100644
index 00000000..aba72f86
--- /dev/null
+++ b/drupal7/sites/all/modules/media/modules/media_bulk_upload/media_bulk_upload.module
@@ -0,0 +1,198 @@
+<?php
+
+/**
+ * @file
+ * Primarily Drupal hooks.
+ */
+
+/**
+ * Implements hook_menu().
+ */
+function media_bulk_upload_menu() {
+  $items['admin/content/file/import'] = array(
+    'title' => 'Import files',
+    'description' => 'Import files into your media library.',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('media_bulk_upload_import'),
+    'access arguments' => array('import media'),
+    'type' => MENU_LOCAL_ACTION,
+    'file' => 'includes/media_bulk_upload.admin.inc',
+    'weight' => 10,
+  );
+  $items['admin/content/file/thumbnails/import'] = $items['admin/content/file/import'];
+
+  // @todo Investigate passing file IDs in query string rather than a menu
+  // argument and then deprecate media_multi_load().
+  $items['admin/content/file/edit-multiple/%media_bulk_upload_multi'] = array(
+    'title' => 'Edit multiple files',
+    'page callback' => 'media_bulk_upload_file_page_edit_multiple',
+    'page arguments' => array(4),
+    'access callback' =>  '_media_bulk_upload_file_entity_access_recursive',
+    'access arguments' => array(4, 'update'),
+    'file' => 'includes/media_bulk_upload.pages.inc',
+  );
+
+  return $items;
+}
+
+/**
+ * Implements hook_permission().
+ */
+function media_bulk_upload_permission() {
+  return array(
+    'import media' => array(
+      'title' => t('Import media files from the local filesystem'),
+      'description' => t('Simple file importer'),
+      'restrict access' => TRUE,
+    ),
+  );
+}
+
+/**
+ * Implements hook_media_browser_plugin_info_alter().
+ */
+function media_bulk_upload_media_browser_plugin_info_alter(&$info) {
+  $info['upload']['class'] = 'MediaBrowserBulkUpload';
+}
+
+/**
+ * Implements hook_file_operations().
+ */
+function media_bulk_upload_file_operations() {
+  return array(
+    'edit_multiple' => array(
+      'label' => t('Edit selected files'),
+      'callback' => 'media_bulk_upload_file_operation_edit_multiple',
+    ),
+  );
+}
+
+/**
+ * Implements hook_form_alter().
+ */
+function media_bulk_upload_form_alter(&$form, &$form_state, $form_id) {
+  // If we're in the media browser, set the #media_browser key to true
+  // so that if an ajax request gets sent to a different path, the form
+  // still uses the media_browser_form_submit callback.
+  if (current_path() == 'media/browser' && $form_id != 'views_exposed_form') {
+    $form_state['#media_browser'] = TRUE;
+  }
+
+  // If the #media_browser key isset and is true we are using the browser
+  // popup, so add the media_browser submit handler.
+  if (!empty($form_state['#media_browser'])) {
+    $form['#submit'][] = 'media_bulk_upload_browser_form_submit';
+  }
+}
+
+/**
+ * Submit handler; direction form submissions in the media browser.
+ */
+function media_bulk_upload_browser_form_submit($form, &$form_state) {
+  $url = NULL;
+  $parameters = array();
+
+  // Multi upload.
+  if (!empty($form_state['files'])) {
+    $files = $form_state['files'];
+    $url = 'media/browser';
+    $parameters = array('query' => array('render' => 'media-popup', 'fid' => array_keys($files)));
+  }
+
+  // If $url is set, we had some sort of upload, so redirect the form.
+  if (!empty($url)) {
+    $form_state['redirect'] = array($url, $parameters);
+  }
+}
+
+/**
+ * Return a URL for editing an files.
+ *
+ * Works with an array of fids or a single fid.
+ *
+ * @param mixed $fids
+ *   An array of file IDs or a single file ID.
+ */
+function media_bulk_upload_file_edit_url($fids) {
+  if (!is_array($fids)) {
+    $fids = array($fids);
+  }
+
+  if (count($fids) > 1) {
+    return 'admin/content/file/edit-multiple/' . implode(' ', $fids);
+  }
+  else {
+    return 'file/' . reset($fids) . '/edit';
+  }
+}
+
+/**
+ * Callback for the edit operation.
+ *
+ * Redirects the user to the edit multiple files page.
+ *
+ * @param array $fids
+ *   An array of file IDs.
+ *
+ * @see media_file_page_edit_multiple()
+ */
+function media_bulk_upload_file_operation_edit_multiple($fids) {
+  // The thumbnail browser returns TRUE/FALSE for each item, so use array keys.
+  $fids = array_keys(array_filter($fids));
+  drupal_goto(media_bulk_upload_file_edit_url($fids), array('query' => drupal_get_destination()));
+}
+
+/**
+ * Implements hook_forms().
+ */
+function media_bulk_upload_forms($form_id, $args) {
+  $forms = array();
+  // To support the multiedit form, each form has to have a unique ID.
+  // So we name all the forms media_edit_N where the first requested form is
+  // media_edit_0, 2nd is media_edit_1, etc.
+  module_load_include('inc', 'file_entity', 'file_entity.pages');
+  if ($form_id != 'media_edit' && (strpos($form_id, 'media_edit') === 0)) {
+    $forms[$form_id] = array(
+      'callback' => 'file_entity_edit',
+    );
+  }
+  return $forms;
+}
+
+/**
+ * Access callback for the media-multi form.
+ *
+ * @param $files
+ *   An array of files being editing on the multiform.
+ * @param $op
+ *   A string containing the operation requested, such as 'update'.
+ * @return
+ *   TRUE if the current user has access to edit all of the files, otherwise FALSE.
+ */
+function _media_bulk_upload_file_entity_access_recursive($files, $op) {
+  // Check that the current user can access each file.
+  if (!empty($files)) {
+    foreach ($files as $file) {
+      if (!file_entity_access($op, $file)) {
+        return FALSE;
+      }
+    }
+    return TRUE;
+  }
+  return FALSE;
+}
+
+/**
+ * Load callback for %media_multi placeholder in menu paths.
+ *
+ * @param string $fids
+ *   Separated by space (e.g., "3 6 12 99"). This often appears as "+" within
+ *   URLs (e.g., "3+6+12+99"), but Drupal automatically decodes paths when
+ *   intializing $_GET['q'].
+ *
+ * @return array
+ *   An array of corresponding file entities.
+ */
+function media_bulk_upload_multi_load($fids) {
+  return file_load_multiple(explode(' ', $fids));
+}
diff --git a/drupal7/sites/all/modules/media/modules/media_internet/includes/MediaBrowserInternet.inc b/drupal7/sites/all/modules/media/modules/media_internet/includes/MediaBrowserInternet.inc
index 919108f1..b719dc9a 100644
--- a/drupal7/sites/all/modules/media/modules/media_internet/includes/MediaBrowserInternet.inc
+++ b/drupal7/sites/all/modules/media/modules/media_internet/includes/MediaBrowserInternet.inc
@@ -20,8 +20,13 @@ class MediaBrowserInternet extends MediaBrowserPlugin {
    * Implements MediaBrowserPlugin::view().
    */
   public function view() {
-    module_load_include('inc', 'media_internet', 'media_internet.pages');
-    $build['form'] = drupal_get_form('media_internet_add', $this->params['types'], $this->params['multiselect']);
+    module_load_include('inc', 'file_entity', 'file_entity.pages');
+
+    $build = array();
+    $params = $this->params;
+    $params['internet_media'] = TRUE;
+    $build['form'] = drupal_get_form('media_internet_add_upload', $params);
+
     return $build;
   }
 }
diff --git a/drupal7/sites/all/modules/media/modules/media_internet/includes/MediaInternetBaseHandler.inc b/drupal7/sites/all/modules/media/modules/media_internet/includes/MediaInternetBaseHandler.inc
new file mode 100644
index 00000000..abd71d51
--- /dev/null
+++ b/drupal7/sites/all/modules/media/modules/media_internet/includes/MediaInternetBaseHandler.inc
@@ -0,0 +1,77 @@
+<?php
+
+/**
+ * @file
+ * Definition of MediaInternetBaseHandler.
+ */
+
+/**
+ * A base class for managing the addition of Internet media.
+ *
+ * Classes extending this class manage the addition of Internet media. To
+ * achieve this, the class should parse user-submitted embed code, claim it
+ * when appropriate and save it as a managed file.
+ */
+abstract class MediaInternetBaseHandler {
+
+  /**
+   * The constructor for the MediaInternetBaseHandler class. This method is also called
+   * from the classes that extend this class and override this method.
+   */
+  public function __construct($embedCode) {
+    $this->embedCode = $embedCode;
+  }
+
+  /**
+   * Determines if this handler should claim the item.
+   *
+   * @param string $embed_code
+   *   A string of user-submitted embed code.
+   *
+   * @return boolean
+   *   Pass TRUE to claim the item.
+   */
+  abstract public function claim($embed_code);
+
+  /**
+   * Returns a file object which can be used for validation.
+   *
+   * @return StdClass
+   */
+  abstract public function getFileObject();
+
+  /**
+   * If required, implementors can validate the embedCode.
+   */
+  public function validate() {
+  }
+
+  /**
+   * Before the file has been saved, implementors may do additional operations.
+   *
+   * @param object $file_obj
+   */
+  public function preSave(&$file_obj) {
+  }
+
+  /**
+   * Saves a file to the file_managed table (with file_save).
+   *
+   * @return StdClass
+   */
+  public function save() {
+    $file_obj = $this->getFileObject();
+    $this->preSave($file_obj);
+    file_save($file_obj);
+    $this->postSave($file_obj);
+    return $file_obj;
+  }
+
+  /**
+   * After the file has been saved, implementors may do additional operations.
+   *
+   * @param object $file_obj
+   */
+  public function postSave(&$file_obj) {
+  }
+}
diff --git a/drupal7/sites/all/modules/media/modules/media_internet/includes/MediaInternetFileHandler.inc b/drupal7/sites/all/modules/media/modules/media_internet/includes/MediaInternetFileHandler.inc
new file mode 100644
index 00000000..c5b65cf5
--- /dev/null
+++ b/drupal7/sites/all/modules/media/modules/media_internet/includes/MediaInternetFileHandler.inc
@@ -0,0 +1,67 @@
+<?php
+
+/**
+ * @file
+ * Definition of MediaInternetFileHandler.
+ */
+
+/**
+ * A class for managing the addition of Internet files.
+ */
+class MediaInternetFileHandler extends MediaInternetBaseHandler {
+
+  public $fileObject;
+
+  public function preSave(&$file_obj) {
+    // Coppies the remote file locally.
+    $remote_uri = $file_obj->uri;
+    //@TODO: we should follow redirection here an save the final filename, not just the basename.
+    $local_filename = basename($remote_uri);
+    $local_filename = file_munge_filename($local_filename, variable_get('file_entity_default_allowed_extensions', 'jpg jpeg gif png txt doc docx xls xlsx pdf ppt pptx pps ppsx odt ods odp mp3 mov mp4 m4a m4v mpeg avi ogg oga ogv weba webp webm'), FALSE);
+    $local_uri = file_stream_wrapper_uri_normalize('temporary://' . $local_filename);
+    if (!@copy($remote_uri, $local_uri)) {
+      throw new Exception('Unable to add file ' . $remote_uri);
+      return;
+    }
+    // Make the current fileObject point to the local_uri, not the remote one.
+    $file_obj = file_uri_to_object($local_uri);
+  }
+
+  public function postSave(&$file_obj) {
+    $scheme = variable_get('file_default_scheme', 'public') . '://';
+    module_load_include('inc', 'file_entity', 'file_entity.pages');
+    $destination_uri = file_entity_upload_destination_uri(array());
+    $uri = file_stream_wrapper_uri_normalize($destination_uri . '/' . $file_obj->filename);
+    // Now to its new home.
+    $file_obj = file_move($file_obj, $uri, FILE_EXISTS_RENAME);
+  }
+
+  public function getFileObject() {
+    if (!$this->fileObject) {
+      $this->fileObject = file_uri_to_object($this->embedCode);
+    }
+    return $this->fileObject;
+  }
+
+  public function claim($embedCode) {
+    // Claim only valid URLs using a supported scheme.
+    if (!valid_url($embedCode, TRUE) || !in_array(file_uri_scheme($embedCode), variable_get('media_fromurl_supported_schemes', array('http', 'https', 'ftp', 'smb', 'ftps')))) {
+      return FALSE;
+    }
+
+    // This handler is intended for regular files, so don't claim URLs
+    // containing query strings or fragments.
+    if (preg_match('/[\?\#]/', $embedCode)) {
+      return FALSE;
+    }
+
+    // Since this handler copies the remote file to the local web server, do not
+    // claim a URL with an extension disallowed for media uploads.
+    $regex = '/\.(' . preg_replace('/ +/', '|', preg_quote(variable_get('file_entity_default_allowed_extensions', 'jpg jpeg gif png txt doc docx xls xlsx pdf ppt pptx pps ppsx odt ods odp mp3 mov mp4 m4a m4v mpeg avi ogg oga ogv weba webp webm'))) . ')$/i';
+    if (!preg_match($regex, basename($embedCode))) {
+      return FALSE;
+    }
+
+    return TRUE;
+  }
+}
diff --git a/drupal7/sites/all/modules/media/modules/media_internet/includes/MediaInternetNoHandlerException.inc b/drupal7/sites/all/modules/media/modules/media_internet/includes/MediaInternetNoHandlerException.inc
new file mode 100644
index 00000000..5a199cc3
--- /dev/null
+++ b/drupal7/sites/all/modules/media/modules/media_internet/includes/MediaInternetNoHandlerException.inc
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * @file
+ * Definition of MediaInternetNoHandlerException.
+ */
+
+/**
+ * A custom exception class for handling embed code with no handler.
+ */
+class MediaInternetNoHandlerException extends Exception {
+
+}
diff --git a/drupal7/sites/all/modules/media/modules/media_internet/includes/MediaInternetValidationException.inc b/drupal7/sites/all/modules/media/modules/media_internet/includes/MediaInternetValidationException.inc
new file mode 100644
index 00000000..36322b3e
--- /dev/null
+++ b/drupal7/sites/all/modules/media/modules/media_internet/includes/MediaInternetValidationException.inc
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * @file
+ * Definition of MediaInternetValidationException.
+ */
+
+/**
+ * A custom exception class for handling file validation errors.
+ */
+class MediaInternetValidationException extends Exception {
+
+}
diff --git a/drupal7/sites/all/modules/media/modules/media_internet/media_internet.info b/drupal7/sites/all/modules/media/modules/media_internet/media_internet.info
index 71d2b65b..a01f8a2d 100644
--- a/drupal7/sites/all/modules/media/modules/media_internet/media_internet.info
+++ b/drupal7/sites/all/modules/media/modules/media_internet/media_internet.info
@@ -2,12 +2,19 @@ name = Media Internet Sources
 description = Provides an API for accessing media on various internet services
 package = Media
 core = 7.x
+
 dependencies[] = media
+
 files[] = includes/MediaBrowserInternet.inc
+files[] = includes/MediaInternetBaseHandler.inc
+files[] = includes/MediaInternetFileHandler.inc
+files[] = includes/MediaInternetNoHandlerException.inc
+files[] = includes/MediaInternetValidationException.inc
+files[] = tests/media_internet.test
 
-; Information added by drupal.org packaging script on 2013-10-25
-version = "7.x-2.0-alpha3"
+; Information added by Drupal.org packaging script on 2014-10-04
+version = "7.x-2.0-alpha4"
 core = "7.x"
 project = "media"
-datestamp = "1382744872"
+datestamp = "1412422430"
 
diff --git a/drupal7/sites/all/modules/media/modules/media_internet/media_internet.install b/drupal7/sites/all/modules/media/modules/media_internet/media_internet.install
new file mode 100644
index 00000000..03264d41
--- /dev/null
+++ b/drupal7/sites/all/modules/media/modules/media_internet/media_internet.install
@@ -0,0 +1,21 @@
+<?php
+
+/**
+ * @file
+ * Install, update and uninstall functions for the Media Internet module.
+ */
+
+/**
+ * Implements hook_uninstall().
+ */
+function media_internet_uninstall() {
+  // Remove variables.
+  variable_del('media_internet_fromurl_supported_schemes');
+}
+
+/**
+ * Rebuild the registry in order to accommodate moved classes.
+ */
+function media_internet_update_7000() {
+  registry_rebuild();
+}
diff --git a/drupal7/sites/all/modules/media/modules/media_internet/media_internet.module b/drupal7/sites/all/modules/media/modules/media_internet/media_internet.module
index 15418e6d..c60fbd80 100644
--- a/drupal7/sites/all/modules/media/modules/media_internet/media_internet.module
+++ b/drupal7/sites/all/modules/media/modules/media_internet/media_internet.module
@@ -19,10 +19,11 @@ function media_internet_menu() {
     'title' => 'Web',
     'description' => 'Add internet files to your media library.',
     'page callback' => 'drupal_get_form',
-    'page arguments' => array('media_internet_add'),
+    'page arguments' => array('media_internet_add_upload'),
     'access callback' => 'media_internet_access',
     'type' => MENU_LOCAL_TASK,
-    'file' => 'media_internet.pages.inc',
+    'file' => 'file_entity.pages.inc',
+    'file path' => drupal_get_path('module', 'file_entity'),
   );
 
   return $items;
@@ -47,6 +48,18 @@ function media_internet_permission() {
   );
 }
 
+/**
+ * Implements hook_theme().
+ */
+function media_internet_theme() {
+  return array(
+    // media_internet.pages.inc.
+    'media_internet_embed_help' => array(
+      'variables' => array('description' => NULL, 'supported_providers' => NULL),
+    ),
+  );
+}
+
 /**
  * Gets the list of providers.
  *
@@ -102,139 +115,204 @@ function media_internet_get_provider($embed_string) {
   throw new MediaInternetNoHandlerException(t('Unable to handle the provided embed string or URL.'));
 }
 
-class MediaInternetFileHandler extends MediaInternetBaseHandler {
+/**
+ * Returns HTML for help text based on supported internet media providers.
+ *
+ * @param $variables
+ *   An associative array containing:
+ *   - description: The normal description for this field, specified by the
+ *     user.
+ *   - supported_providers: A string of supported providers.
+ *
+ * @ingroup themeable
+ */
+function theme_media_internet_embed_help($variables) {
+  $description = $variables['description'];
+  $supported_providers = $variables['supported_providers'];
 
-  public $fileObject;
+  $descriptions = array();
 
-  public function preSave(&$file_obj) {
-    // Coppies the remote file locally.
-    $remote_uri = $file_obj->uri;
-    //@TODO: we should follow redirection here an save the final filename, not just the basename.
-    $local_filename = basename($remote_uri);
-    $local_filename = file_munge_filename($local_filename, variable_get('file_entity_default_allowed_extensions', 'jpg jpeg gif png txt doc docx xls xlsx pdf ppt pptx pps ppsx odt ods odp mp3 mov mp4 m4a m4v mpeg avi ogg oga ogv weba webp webm'), FALSE);
-    $local_uri = file_stream_wrapper_uri_normalize('temporary://' . $local_filename);
-    if (!@copy($remote_uri, $local_uri)) {
-      throw new Exception('Unable to add file ' . $remote_uri);
-      return;
-    }
-    // Make the current fileObject point to the local_uri, not the remote one.
-    $file_obj = file_uri_to_object($local_uri);
+  if (strlen($description)) {
+    $descriptions[] = $description;
   }
-
-  public function postSave(&$file_obj) {
-    $scheme = variable_get('file_default_scheme', 'public') . '://';
-    module_load_include('inc', 'file_entity', 'file_entity.pages');
-    $destination_uri = file_entity_upload_destination_uri(array());
-    $uri = file_stream_wrapper_uri_normalize($destination_uri . '/' . $file_obj->filename);
-    // Now to its new home.
-    $file_obj = file_move($file_obj, $uri, FILE_EXISTS_RENAME);
+  if (!empty($supported_providers)) {
+    $descriptions[] = t('Supported internet media providers: !providers.', array('!providers' => '<strong>' . $supported_providers . '</strong>'));
   }
 
-  public function getFileObject() {
-    if (!$this->fileObject) {
-      $this->fileObject = file_uri_to_object($this->embedCode);
-    }
-    return $this->fileObject;
+  return implode('<br />', $descriptions);
+}
+
+/**
+ * Implements hook_forms().
+ */
+function media_internet_forms($form_id, $args) {
+  $forms = array();
+
+  // Create a copy of the upload wizard form for internet media.
+  if ($form_id == 'media_internet_add_upload') {
+    $forms[$form_id] = array(
+      'callback' => 'file_entity_add_upload',
+    );
   }
 
-  public function claim($embedCode) {
-    // Claim only valid URLs using a supported scheme.
-    if (!valid_url($embedCode, TRUE) || !in_array(file_uri_scheme($embedCode), variable_get('media__fromurl_supported_schemes', array('http', 'https', 'ftp', 'smb', 'ftps')))) {
-      return FALSE;
+  return $forms;
+}
+
+/**
+ * Implements hook_form_FORM_ID_alter().
+ */
+function media_internet_form_file_entity_add_upload_alter(&$form, &$form_state, $form_id) {
+  $step = $form['#step'];
+  $options = $form['#options'];
+
+  // Swap the upload field for an embed field when on the first step of the web
+  // tab.
+  if ($form_id == 'media_internet_add_upload' && $step == 1) {
+    unset($form['upload']);
+
+    $form['embed_code'] = array(
+      '#type' => 'textfield',
+      '#title' => t('File URL'),
+      '#description' => t('Enter a URL to a file.'),
+      '#attributes' => array('class' => array('media-add-from-url')),
+      // There is no standard specifying a maximum length for a URL. Internet
+      // Explorer supports up to 2083 (http://support.microsoft.com/kb/208427)
+      // so we assume publicly available media URLs are within this limit.
+      '#maxlength' => 2083,
+      '#required' => TRUE,
+      '#default_value' => isset($form_state['storage']['embed_code']) ? $form_state['storage']['embed_code'] : NULL,
+    );
+
+    // Create an array to hold potential Internet media providers.
+    $providers = array();
+
+    // Determine if there are any visible providers.
+    foreach (media_internet_get_providers() as $key => $provider) {
+      if (empty($provider['hidden']) || $provider['hidden'] != TRUE) {
+        $providers[] = check_plain($provider['title']);
+      }
     }
 
-    // This handler is intended for regular files, so don't claim URLs
-    // containing query strings or fragments.
-    if (preg_match('/[\?\#]/', $embedCode)) {
-      return FALSE;
+    $form['#providers'] = $providers;
+
+    // Notify the user of any available providers.
+    if ($providers) {
+      // If any providers are enabled it is assumed that some kind of embed is supported.
+      $form['embed_code']['#title'] = t('File URL or media resource');
+      $form['embed_code']['#description'] = t('Enter a URL to a file or media resource. Many media providers also support identifying media via the embed code used to embed the media into external websites.');
+
+      $form['embed_code']['#description'] = theme('media_internet_embed_help', array('description' => $form['embed_code']['#description'], 'supported_providers' => implode(' ', $providers)));
     }
 
-    // Since this handler copies the remote file to the local web server, do not
-    // claim a URL with an extension disallowed for media uploads.
-    $regex = '/\.(' . preg_replace('/ +/', '|', preg_quote(variable_get('file_entity_default_allowed_extensions', 'jpg jpeg gif png txt doc docx xls xlsx pdf ppt pptx pps ppsx odt ods odp mp3 mov mp4 m4a m4v mpeg avi ogg oga ogv weba webp webm'))) . ')$/i';
-    if (!preg_match($regex, basename($embedCode))) {
-      return FALSE;
+    $form['#validators'] = array();
+
+    if (!empty($options['types'])) {
+      $form['#validators']['media_file_validate_types'] = array($options['types']);
     }
 
-    return TRUE;
+    // Add validation and submission handlers to the form and ensure that they
+    // run first.
+    array_unshift($form['#validate'], 'media_internet_add_validate');
+    array_unshift($form['#submit'], 'media_internet_add_submit');
   }
 }
 
-/*
- * Base MediaInternetBaseHandler class.
+/**
+ * Allow stream wrappers to have their chance at validation.
+ *
+ * Any module that implements hook_media_parse will have an
+ * opportunity to validate this.
  *
- * Classes extending this class manage the addition of Internet media. To
- * achieve this, the class should parse user-submitted embed code, claim it
- * when appropriate and save it as a managed file.
+ * @see media_parse_to_uri()
  */
-abstract class MediaInternetBaseHandler {
-
-  /**
-   * The constructor for the MediaInternetBaseHandler class. This method is also called
-   * from the classes that extend this class and override this method.
-   */
-  public function __construct($embedCode) {
-    $this->embedCode = $embedCode;
-  }
+function media_internet_add_validate($form, &$form_state) {
+  // Supporting providers can now claim this input. It might be a URL, but it
+  // might be an embed code as well.
+  $embed_code = $form_state['values']['embed_code'];
 
-  /**
-   * Determines if this handler should claim the item.
-   *
-   * @param string $embed_code
-   *   A string of user-submitted embed code.
-   *
-   * @return boolean
-   *   Pass TRUE to claim the item.
-   */
-  abstract public function claim($embed_code);
-
-  /**
-   * Returns a file object which can be used for validation.
-   *
-   * @return StdClass
-   */
-  abstract public function getFileObject();
-
-  /**
-   * If required, implementors can validate the embedCode.
-   */
-  public function validate() {
+  try {
+    $provider = media_internet_get_provider($embed_code);
+    $provider->validate();
   }
-
-  /**
-   * Before the file has been saved, implementors may do additional operations.
-   *
-   * @param object $file_obj
-   */
-  public function preSave(&$file_obj) {
+  catch (MediaInternetNoHandlerException $e) {
+    form_set_error('embed_code', $e->getMessage());
+    return;
   }
-
-  /**
-   * Saves a file to the file_managed table (with file_save).
-   *
-   * @return StdClass
-   */
-  public function save() {
-    $file_obj = $this->getFileObject();
-    $this->preSave($file_obj);
-    file_save($file_obj);
-    $this->postSave($file_obj);
-    return $file_obj;
+  catch (MediaInternetValidationException $e) {
+    form_set_error('embed_code', $e->getMessage());
+    return;
   }
 
-  /**
-   * After the file has been saved, implementors may do additional operations.
-   *
-   * @param object $file_obj
-   */
-  public function postSave(&$file_obj) {
+  $validators = $form['#validators'];
+  $file = $provider->getFileObject();
+
+  if ($validators) {
+    try {
+      $file = $provider->getFileObject();
+    }
+    catch (Exception $e) {
+      form_set_error('embed_code', $e->getMessage());
+      return;
+    }
+
+    // Check for errors. @see media_add_upload_validate calls file_save_upload().
+    // this code is ripped from file_save_upload because we just want the validation part.
+    // Call the validation functions specified by this function's caller.
+    $errors = file_validate($file, $validators);
+
+    if (!empty($errors)) {
+      $message = t('%url could not be added.', array('%url' => $embed_code));
+      if (count($errors) > 1) {
+        $message .= theme('item_list', array('items' => $errors));
+      }
+      else {
+        $message .= ' ' . array_pop($errors);
+      }
+      form_set_error('embed_code', $message);
+      return FALSE;
+    }
   }
-}
 
-class MediaInternetValidationException extends Exception {
+  // @TODO: Validate that if we have no $uri that this is a valid file to
+  // save. For instance, we may only be interested in images, and it would
+  // be helpful to let the user know they passed the HTML page containing
+  // the image accidentally. That would also save us from saving the file
+  // in the submit step.
+
+  // This is kinda a hack of the same.
 
+  // This should use the file_validate routines that the upload form users.
+  // We need to fix the media_parse_to_file routine to allow for a validation.
 }
 
-class MediaInternetNoHandlerException extends Exception {
+/**
+ * Upload a file from a URL.
+ *
+ * This will copy a file from a remote location and store it locally.
+ *
+ * @see media_parse_to_uri()
+ * @see media_parse_to_file()
+ */
+function media_internet_add_submit($form, &$form_state) {
+  $embed_code = $form_state['values']['embed_code'];
 
+  try {
+    // Save the remote file
+    $provider = media_internet_get_provider($embed_code);
+    // Providers decide if they need to save locally or somewhere else.
+    // This method returns a file object
+    $file = $provider->save();
+  }
+  catch (Exception $e) {
+    form_set_error('embed_code', $e->getMessage());
+    return;
+  }
+
+  if (!$file->fid) {
+    form_set_error('embed_code', t('The file %file could not be saved. An unknown error has occurred.', array('%file' => $embed_code)));
+    return;
+  }
+  else {
+    $form_state['storage']['upload'] = $file->fid;
+  }
 }
diff --git a/drupal7/sites/all/modules/media/modules/media_internet/media_internet.pages.inc b/drupal7/sites/all/modules/media/modules/media_internet/media_internet.pages.inc
deleted file mode 100644
index 736e2cfd..00000000
--- a/drupal7/sites/all/modules/media/modules/media_internet/media_internet.pages.inc
+++ /dev/null
@@ -1,185 +0,0 @@
-<?php
-
-/**
- * @file
- * Supports the addition of Internet media.
- */
-
-/**
- * Provides a form for adding media items from 3rd party sources.
- *
- * @todo Convert the form arguments to just one array of options/parameters.
- */
-function media_internet_add($form, &$form_state = array(), $types = NULL) {
-  $form['embed_code'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Enter a URL to an image'),
-    '#description' => t('Enter a URL to an image on the web.'),
-    '#attributes' => array('class' => array('media-add-from-url')),
-    // There is no standard specifying a maximum length for a URL. Internet
-    // Explorer supports up to 2083 (http://support.microsoft.com/kb/208427)
-    // so we assume publicly available media URLs are within this limit.
-    '#maxlength' => 2083,
-    '#required' => TRUE,
-  );
-
-  // Create an array to hold potential Internet media providers.
-  $providers = array();
-
-  // Determine if there are any visible providers.
-  foreach (media_internet_get_providers() as $key => $provider) {
-    if (empty($provider['hidden']) || $provider['hidden'] != TRUE) {
-      $providers[] = array(
-        'data' => check_plain($provider['title']),
-        'class' => array(drupal_html_class($provider['title'])),
-      );
-    }
-  }
-
-  // Notify the user of any available providers.
-  if ($providers) {
-    // If any providers are enabled it is assumed that some kind of embed is supported.
-    $form['embed_code']['#title'] = t('Enter an image URL or an embed code');
-    $form['embed_code']['#description'] = t('Enter a URL or the embed code from a media provider.');
-
-    // Providers are displayed in an unordered list below the embed input.
-    // Providers can easily style their own listing by targeting the unique
-    // class assigned to each list item.
-    $form['providers'] = array(
-      '#theme' => 'item_list',
-      '#title' => t('Supported providers'),
-      '#items' => $providers,
-      '#attributes' => array(
-        'class' => array('media-internet-providers'),
-      ),
-    );
-  }
-
-  $form['#validators'] = array();
-  if ($types) {
-    $form['#validators']['media_file_validate_types'] = array($types);
-  }
-
-  $form['actions'] = array(
-    '#type' => 'actions',
-  );
-  $form['actions']['submit'] = array(
-    '#type' => 'submit',
-    '#value' => t('Submit'),
-  );
-
-  return $form;
-}
-
-/**
- * Allow stream wrappers to have their chance at validation.
- *
- * Any module that implements hook_media_parse will have an
- * opportunity to validate this.
- *
- * @see media_parse_to_uri()
- */
-function media_internet_add_validate($form, &$form_state) {
-  // Supporting providers can now claim this input. It might be a URL, but it
-  // might be an embed code as well.
-  $embed_code = $form_state['values']['embed_code'];
-
-  try {
-    $provider = media_internet_get_provider($embed_code);
-    $provider->validate();
-  }
-  catch (MediaInternetNoHandlerException $e) {
-    form_set_error('embed_code', $e->getMessage());
-    return;
-  }
-  catch (MediaInternetValidationException $e) {
-    form_set_error('embed_code', $e->getMessage());
-    return;
-  }
-
-  $validators = $form['#validators'];
-  $file = $provider->getFileObject();
-
-  if ($validators) {
-    try {
-      $file = $provider->getFileObject();
-    }
-    catch (Exception $e) {
-      form_set_error('embed_code', $e->getMessage());
-      return;
-    }
-
-    // Check for errors. @see media_add_upload_validate calls file_save_upload().
-    // this code is ripped from file_save_upload because we just want the validation part.
-    // Call the validation functions specified by this function's caller.
-    $errors = file_validate($file, $validators);
-
-    if (!empty($errors)) {
-      $message = t('%url could not be added.', array('%url' => $embed_code));
-      if (count($errors) > 1) {
-        $message .= theme('item_list', array('items' => $errors));
-      }
-      else {
-        $message .= ' ' . array_pop($errors);
-      }
-      form_set_error('embed_code', $message);
-      return FALSE;
-    }
-  }
-
-  // @TODO: Validate that if we have no $uri that this is a valid file to
-  // save. For instance, we may only be interested in images, and it would
-  // be helpful to let the user know they passed the HTML page containing
-  // the image accidentally. That would also save us from saving the file
-  // in the submit step.
-
-  // This is kinda a hack of the same.
-
-  // This should use the file_validate routines that the upload form users.
-  // We need to fix the media_parse_to_file routine to allow for a validation.
-}
-
-/**
- * Upload a file from a URL.
- *
- * This will copy a file from a remote location and store it locally.
- *
- * @see media_parse_to_uri()
- * @see media_parse_to_file()
- */
-function media_internet_add_submit($form, &$form_state) {
-  $embed_code = $form_state['values']['embed_code'];
-
-  try {
-    // Save the remote file
-    $provider = media_internet_get_provider($embed_code);
-    // Providers decide if they need to save locally or somewhere else.
-    // This method returns a file object
-    $file = $provider->save();
-  }
-  catch (Exception $e) {
-    form_set_error('embed_code', $e->getMessage());
-    return;
-  }
-
-  if (!$file->fid) {
-    form_set_error('embed_code', t('The file %file could not be saved. An unknown error has occurred.', array('%file' => $embed_code)));
-    return;
-  }
-  else {
-    $form_state['file'] = $file;
-  }
-
-  // Redirect to the file edit page after submission.
-  if (file_entity_access('update', $file)) {
-    $destination = array('destination' => 'admin/content/file');
-    if (isset($_GET['destination'])) {
-      $destination = drupal_get_destination();
-      unset($_GET['destination']);
-    }
-    $form_state['redirect'] = array('file/' . $file->fid . '/edit', array('query' => $destination));
-  }
-  else {
-    $form_state['redirect'] = 'admin/content/file';
-  }
-}
diff --git a/drupal7/sites/all/modules/media/modules/media_internet/tests/includes/MediaInternetTestHandler.inc b/drupal7/sites/all/modules/media/modules/media_internet/tests/includes/MediaInternetTestHandler.inc
new file mode 100644
index 00000000..764279ca
--- /dev/null
+++ b/drupal7/sites/all/modules/media/modules/media_internet/tests/includes/MediaInternetTestHandler.inc
@@ -0,0 +1,45 @@
+<?php
+
+/**
+ * @file
+ * Extends the MediaInternetBaseHandler class to handle videos from an imaginary example.com.
+ */
+
+/**
+ * Implementation of MediaInternetBaseHandler.
+ *
+ * @see hook_media_internet_providers().
+ */
+class MediaInternetTestHandler extends MediaInternetBaseHandler {
+  public function parse($embedCode) {
+    // http://example.com/video/*
+    $patterns = array(
+      '@example\.com/video/(\d+)@i',
+    );
+
+    foreach ($patterns as $pattern) {
+      preg_match($pattern, $embedCode, $matches);
+      if (isset($matches[1])) {
+        return file_stream_wrapper_uri_normalize('mediainternettest://video/' . $matches[1]);
+      }
+    }
+  }
+
+  public function claim($embedCode) {
+    if ($this->parse($embedCode)) {
+      return TRUE;
+    }
+  }
+
+  public function getFileObject() {
+    $uri = $this->parse($this->embedCode);
+    $file = file_uri_to_object($uri, TRUE);
+
+    // Override the default filename for testing purposes.
+    if (empty($file->fid)) {
+      $file->filename = 'Drupal';
+    }
+
+    return $file;
+  }
+}
diff --git a/drupal7/sites/all/modules/media/modules/media_internet/tests/includes/MediaInternetTestStreamWrapper.inc b/drupal7/sites/all/modules/media/modules/media_internet/tests/includes/MediaInternetTestStreamWrapper.inc
new file mode 100644
index 00000000..20253838
--- /dev/null
+++ b/drupal7/sites/all/modules/media/modules/media_internet/tests/includes/MediaInternetTestStreamWrapper.inc
@@ -0,0 +1,24 @@
+<?php
+
+/**
+ *  @file
+ *  Extends the MediaReadOnlyStreamWrapper class to handle videos from an imaginary example.com.
+ */
+
+/**
+ *  Create an instance like this:
+ *  $media_internet_test = new MediaInternetTestStreamWrapper('mediainternettest://video/[video-code]');
+ */
+class MediaInternetTestStreamWrapper extends MediaReadOnlyStreamWrapper {
+  protected $base_url = 'http://example.com';
+
+  static function getMimeType($uri, $mapping = NULL) {
+    return 'video/mediainternettest';
+  }
+
+  function interpolateUrl() {
+    if ($parameters = $this->get_parameters()) {
+      return $this->base_url . '/' . $parameters['video'];
+    }
+  }
+}
diff --git a/drupal7/sites/all/modules/media/modules/media_internet/tests/media_internet.test b/drupal7/sites/all/modules/media/modules/media_internet/tests/media_internet.test
new file mode 100644
index 00000000..9d67ac16
--- /dev/null
+++ b/drupal7/sites/all/modules/media/modules/media_internet/tests/media_internet.test
@@ -0,0 +1,176 @@
+<?php
+
+/**
+ * @file
+ * Tests for media_internet.module.
+ */
+
+/**
+ * Provides methods specifically for testing Media Internet module's remote media handling.
+ */
+class MediaInternetTestHelper extends DrupalWebTestCase {
+  function setUp() {
+    // Since this is a base class for many test cases, support the same
+    // flexibility that DrupalWebTestCase::setUp() has for the modules to be
+    // passed in as either an array or a variable number of string arguments.
+    $modules = func_get_args();
+    if (isset($modules[0]) && is_array($modules[0])) {
+      $modules = $modules[0];
+    }
+    $modules[] = 'media_internet';
+    parent::setUp($modules);
+  }
+
+  /**
+   * Get a file from the database based on its filename.
+   *
+   * @param $filename
+   *   A file filename, usually generated by $this->randomName().
+   * @param $reset
+   *   (optional) Whether to reset the internal file_load() cache.
+   *
+   * @return
+   *   A file object matching $filename.
+   */
+  function getFileByFilename($filename, $reset = FALSE) {
+    $files = file_load_multiple(array(), array('filename' => $filename), $reset);
+    // Load the first file returned from the database.
+    $returned_file = reset($files);
+    return $returned_file;
+  }
+}
+
+/**
+ * Tests the media browser 'Web' tab.
+ */
+class MediaInternetBrowserWebTabTestCase extends MediaInternetTestHelper {
+  public static function getInfo() {
+    return array(
+      'name' => 'Media browser web tab test',
+      'description' => 'Tests the media browser web tab.',
+      'group' => 'Media Internet',
+      'dependencies' => array('fake'), // @todo remove when File Entity > alpha3 is released. This test currently fails on drupal.org due to testbot dependency issues.
+    );
+  }
+
+  function setUp() {
+    parent::setUp();
+
+    $web_user = $this->drupalCreateUser(array('access media browser', 'add media from remote sources'));
+    $this->drupalLogin($web_user);
+  }
+
+  /**
+   * Tests that the views sorting works on the media browser 'Library' tab.
+   */
+  function testMediaBrowserWebTab() {
+    // Load only the 'Library' tab of the media browser.
+    $options = array(
+      'query' => array(
+        'enabledPlugins' => array(
+          'media_internet' => 'media_internet',
+        ),
+      ),
+    );
+
+    $this->drupalGet('media/browser', $options);
+    $this->assertResponse(200);
+
+    // Check that the web tab is available and has an 'embed code' field.
+    $this->assertRaw(t('Web'), t('The web tab was found.'));
+    $this->assertFieldByName('embed_code', '', t('Embed code form field found.'));
+  }
+}
+
+/**
+ * Test file creation through the file upload wizard with remote media.
+ */
+class MediaInternetCreationTestCase extends MediaInternetTestHelper {
+  public static function getInfo() {
+    return array(
+      'name' => 'Remote media file creation',
+      'description' => 'Test file creation with remote media.',
+      'group' => 'Media Internet',
+      'dependencies' => array('fake'), // @todo remove when File Entity > alpha3 is released. This test currently fails on drupal.org due to testbot dependency issues.
+    );
+  }
+
+  function setUp() {
+    parent::setUp();
+
+    $web_user = $this->drupalCreateUser(array('create files', 'add media from remote sources', 'edit own document files'));
+    $this->drupalLogin($web_user);
+  }
+
+  /**
+   * Tests file creation with remote media.
+   */
+  function testRemoteMediaFileCreation() {
+    // Create a file.
+    $edit = array();
+    $edit['embed_code'] = file_create_url('README.txt');
+    $this->drupalPost('file/add/web', $edit, t('Next'));
+
+    // Step 2: Scheme selection
+    if ($this->xpath('//input[@name="scheme"]')) {
+      $this->drupalPost(NULL, array(), t('Next'));
+    }
+
+    // Check that the document file has been uploaded.
+    $this->assertRaw(t('!type %name was uploaded.', array('!type' => 'Document', '%name' => 'README.txt')), t('Document file uploaded.'));
+
+    // Check that the file exists in the database.
+    $file = $this->getFileByFilename('README.txt');
+    $this->assertTrue($file, t('File found in database.'));
+  }
+}
+
+/**
+ * Tests custom media provider APIs.
+ */
+class MediaInternetProviderTestCase extends MediaInternetTestHelper {
+  public static function getInfo() {
+    return array(
+      'name' => 'Custom media provider test',
+      'description' => 'Tests the custom media provider APIs.',
+      'group' => 'Media Internet',
+      'dependencies' => array('fake'), // @todo remove when File Entity > alpha3 is released. This test currently fails on drupal.org due to testbot dependency issues.
+    );
+  }
+
+  function setUp() {
+    parent::setUp('media_internet_test');
+
+    $web_user = $this->drupalCreateUser(array('access media browser', 'create files', 'add media from remote sources', 'edit own video files'));
+    $this->drupalLogin($web_user);
+  }
+
+  /**
+   * Tests file creation with a custom media provider.
+   */
+  function testFilesBrowserSort() {
+    $this->drupalGet('file/add/web');
+    $this->assertResponse(200);
+
+    // Check that the provider is listed as supported.
+    $supported_providers = 'Media Internet Test';
+    $this->assertRaw(t('Supported internet media providers: !providers.', array('!providers' => '<strong>' . $supported_providers . '</strong>')), t('The example media provider is enabled.'));
+
+    // Create a file.
+    $edit = array();
+    $edit['embed_code'] = 'http://www.example.com/video/123';
+    $this->drupalPost('file/add/web', $edit, t('Next'));
+
+    // Step 2: Scheme selection
+    if ($this->xpath('//input[@name="scheme"]')) {
+      $this->drupalPost(NULL, array(), t('Next'));
+    }
+
+    // Check that the video file has been uploaded.
+    $this->assertRaw(t('!type %name was uploaded.', array('!type' => 'Video', '%name' => 'Drupal')), t('Video file uploaded.'));
+
+    // Check that the file exists in the database.
+    $file = $this->getFileByFilename('Drupal');
+    $this->assertTrue($file, t('File found in database.'));
+  }
+}
diff --git a/drupal7/sites/all/modules/media/modules/media_internet/tests/media_internet_test.info b/drupal7/sites/all/modules/media/modules/media_internet/tests/media_internet_test.info
new file mode 100644
index 00000000..193115db
--- /dev/null
+++ b/drupal7/sites/all/modules/media/modules/media_internet/tests/media_internet_test.info
@@ -0,0 +1,15 @@
+name = Media Internet Test
+description = Provides hooks for testing Media Internet module functionality.
+package = Media
+core = 7.x
+hidden = TRUE
+
+files[] = includes/MediaInternetTestStreamWrapper.inc
+files[] = includes/MediaInternetTestHandler.inc
+
+; Information added by Drupal.org packaging script on 2014-10-04
+version = "7.x-2.0-alpha4"
+core = "7.x"
+project = "media"
+datestamp = "1412422430"
+
diff --git a/drupal7/sites/all/modules/media/modules/media_internet/tests/media_internet_test.module b/drupal7/sites/all/modules/media/modules/media_internet/tests/media_internet_test.module
new file mode 100644
index 00000000..ee1279aa
--- /dev/null
+++ b/drupal7/sites/all/modules/media/modules/media_internet/tests/media_internet_test.module
@@ -0,0 +1,50 @@
+<?php
+
+/**
+ * @file
+ * Provides Media Internet module hook implementations for testing purposes.
+ */
+
+/**
+ * Implements hook_media_internet_providers().
+ */
+function media_internet_test_media_internet_providers() {
+  return array(
+    'MediaInternetTestHandler' => array(
+      'title' => t('Media Internet Test'),
+    ),
+  );
+}
+
+/**
+ * Implements hook_stream_wrappers().
+ */
+function media_internet_test_stream_wrappers() {
+  return array(
+    'mediainternettest' => array(
+      'name' => t('Media Internet Test'),
+      'class' => 'MediaInternetTestStreamWrapper',
+      'description' => t('Media Internet Test.'),
+      'type' => STREAM_WRAPPERS_READ_VISIBLE,
+    ),
+  );
+}
+
+/**
+ * Implements hook_media_parse().
+ *
+ * @todo This hook should be deprecated. Refactor Media module to not call it
+ *   any more, since media_internet should be able to automatically route to the
+ *   appropriate handler.
+ */
+function media_internet_test_media_parse($embed_code) {
+  $handler = new MediaInternetTestHandler($embed_code);
+  return $handler->parse($embed_code);
+}
+
+ /**
+ * Implements hook_file_mimetype_mapping_alter().
+ */
+function media_internet_test_file_mimetype_mapping_alter(&$mapping) {
+  $mapping['mimetypes'][] = 'video/mediainternettest';
+}
diff --git a/drupal7/sites/all/modules/media/modules/media_migrate_file_types/includes/media_migrate_file_types.pages.inc b/drupal7/sites/all/modules/media/modules/media_migrate_file_types/includes/media_migrate_file_types.pages.inc
new file mode 100644
index 00000000..e88bda13
--- /dev/null
+++ b/drupal7/sites/all/modules/media/modules/media_migrate_file_types/includes/media_migrate_file_types.pages.inc
@@ -0,0 +1,199 @@
+<?php
+
+/**
+ * @file
+ * Common pages for the Media Migrate File Types module.
+ */
+
+/**
+ * File type migration page.
+ *
+ * Allows site administrator to execute migration of old/disabled/deleted
+ * file types to new ones.
+ */
+function media_migrate_file_types_upgrade_file_types($form, &$form_state) {
+  $migratable_types = _media_migrate_file_types_get_migratable_file_types();
+
+  // Silently return if there are no file types that need migration.
+  if (empty($migratable_types)) {
+    return array(
+      'message' => array(
+        '#markup' => t('There are no file types that need migration. The Media Medigrate File Types module can now be safely <a href="@modules">disabled</a>.', array('@modules' => url('admin/modules'))),
+      ),
+    );
+  }
+
+  $form['message'] = array(
+    'message' => array(
+      '#markup' => t('This page allows you to migrate deprecated and/or disabled file types to new ones. It will migrate files from old type to new one and optionally migrate fields and delete old type.'),
+    ),
+  );
+
+  $form['migrate_fields'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Migrate fields'),
+    '#default_value' => TRUE,
+    '#description' => t('Migrate fields and their values from old file types to new ones.'),
+  );
+  $form['delete_old_type'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Delete old type'),
+    '#default_value' => FALSE,
+    '#description' => t('Delete old file type if migration was successful and delete operation is possible (type is not exported in code).'),
+  );
+  $form['migrate_mimes'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Migrate type mime-type'),
+    '#default_value' => TRUE,
+    '#description' => t('Move mime-type from old type to new one.'),
+  );
+
+  $form['upgradable_types'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Upgradable file types'),
+  );
+
+  $options = array('- ' . t('Do not upgrade') . ' -');
+  foreach (file_type_get_enabled_types() as $type) {
+    $options[$type->type] = $type->label;
+  }
+
+  foreach ($migratable_types as $machine_name) {
+    $type = file_type_load($machine_name);
+    if (!$type) {
+      $type = new stdClass;
+      $type->label = $type->type = $machine_name;
+    }
+    $form['upgradable_types'][$machine_name] = array(
+      '#type' => 'select',
+      '#title' => $type->label,
+      '#options' => $options,
+      '#description' => t(
+        'Select file type which you want to migrate @type to. Select %no_upgrade if type should stay as it is.',
+        array('@type' => $type->label, '%no_upgrade' => '- ' . t('Do not upgrade') . ' -')),
+    );
+  }
+
+  $form['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Start migration'),
+  );
+
+  return $form;
+}
+
+/**
+ * File type migration page submit handler.
+ */
+function media_migrate_file_types_upgrade_file_types_submit($form, &$form_state) {
+  $migratable_types = _media_migrate_file_types_get_migratable_file_types();
+  $migrate = FALSE;
+  foreach ($migratable_types as $type) {
+    if ($form_state['values'][$type]) {
+      $migrate = TRUE;
+      break;
+    }
+  }
+
+  // Return silently if no types were selected for migration.
+  if (!$migrate) {
+    return;
+  }
+
+  // Use confirmation page/form.
+  $query = $form_state['values'];
+  unset($query['op']);
+  unset($query['submit']);
+  unset($query['form_id']);
+  unset($query['form_token']);
+  unset($query['form_build_id']);
+
+  $form_state['redirect'] = array(
+    'admin/structure/file-types/upgrade/confirm',
+    array('query' => $query),
+  );
+}
+
+/**
+ * File types migration confirmation page.
+ */
+function media_migrate_file_types_upgrade_file_types_confirm($form, &$form_state) {
+  return confirm_form(
+    $form,
+    t('Do you really want to migrate selected file types?'),
+    'admin/structure/file-types/upgrade',
+    NULL,
+    t('Migrate')
+  );
+}
+
+/**
+ * File types migration confirmation page submit. Executes actual migration.
+ */
+function media_migrate_file_types_upgrade_file_types_confirm_submit($form, &$form_state) {
+  $migratable_types = _media_migrate_file_types_get_migratable_file_types();
+  foreach ($migratable_types as $type) {
+    if ($_GET[$type] && $bundle_new = file_type_load($_GET[$type])) {
+      // Old bundle might be deleted so let's fake some values.
+      $bundle_old = file_type_load($type);
+      if (empty($bundle_old)) {
+        $bundle_old = new stdClass;
+        $bundle_old->type = $type;
+        $bundle_old->mimetypes = array();
+        $bundle_old->export_type = 2;
+      }
+
+      // Migrate fields to new bundle.
+      if ($_GET['migrate_fields']) {
+        $old_fields = db_select('field_config_instance', 'fc')->fields('fc', array('field_name'))->condition('entity_type',  'file')->condition('bundle', $bundle_old->type)->execute()->fetchCol();
+        $new_fields = db_select('field_config_instance', 'fc')->fields('fc', array('field_name'))->condition('entity_type',  'file')->condition('bundle', $bundle_new->type)->execute()->fetchCol();
+        $fields_to_move = array_diff($old_fields, $new_fields);
+        $fields_to_drop = array_diff($old_fields, $fields_to_move);
+
+        db_update('field_config_instance')
+          ->fields(array('bundle' => $bundle_new->type))
+          ->condition('entity_type',  'file')
+          ->condition('bundle', $bundle_old->type)
+          ->condition('field_name', $fields_to_move, 'IN')
+          ->execute();
+
+        db_delete('field_config_instance')
+          ->condition('entity_type',  'file')
+          ->condition('bundle', $bundle_old->type)
+          ->condition('field_name', $fields_to_drop, 'IN')
+          ->execute();
+
+        field_cache_clear();
+        module_invoke_all('field_attach_rename_bundle', 'file', $bundle_old->type, $bundle_new->type);
+      }
+
+      // Migrate mimetypes to new bundle.
+      if ($_GET['migrate_mimes']) {
+        $changed = FALSE;
+        foreach ($bundle_old->mimetypes as $mime) {
+          if (!file_entity_match_mimetypes($bundle_new->mimetypes, $mime)) {
+            $bundle_new->mimetypes[] = $mime;
+            $changed = TRUE;
+          }
+        }
+
+        if ($changed) {
+          file_type_save($bundle_new);
+        }
+      }
+
+      // Delete old bundle.
+      if ($_GET['delete_old_type'] && $bundle_old->export_type == 1) {
+        file_type_delete($bundle_old);
+      }
+
+      // Migrate files.
+      db_update('file_managed')
+        ->fields(array('type' => $bundle_new->type))
+        ->condition('type', $bundle_old->type)
+        ->execute();
+    }
+  }
+
+  $form_state['redirect'] = 'admin/structure/file-types';
+}
diff --git a/drupal7/sites/all/modules/media/modules/media_migrate_file_types/media_migrate_file_types.info b/drupal7/sites/all/modules/media/modules/media_migrate_file_types/media_migrate_file_types.info
new file mode 100644
index 00000000..0031d93f
--- /dev/null
+++ b/drupal7/sites/all/modules/media/modules/media_migrate_file_types/media_migrate_file_types.info
@@ -0,0 +1,16 @@
+name = Media Migrate File Types
+description = Provides a UI for updating legacy media types with the new file types provided by File Entity.
+package = Media
+core = 7.x
+hidden = TRUE
+
+dependencies[] = media
+
+configure = admin/structure/file-types/upgrade
+
+; Information added by Drupal.org packaging script on 2014-10-04
+version = "7.x-2.0-alpha4"
+core = "7.x"
+project = "media"
+datestamp = "1412422430"
+
diff --git a/drupal7/sites/all/modules/media/modules/media_migrate_file_types/media_migrate_file_types.module b/drupal7/sites/all/modules/media/modules/media_migrate_file_types/media_migrate_file_types.module
new file mode 100644
index 00000000..c9c6d46c
--- /dev/null
+++ b/drupal7/sites/all/modules/media/modules/media_migrate_file_types/media_migrate_file_types.module
@@ -0,0 +1,73 @@
+<?php
+
+/**
+ * @file
+ * Primarily Drupal hooks.
+ */
+
+/*
+ * Implements hook_system_info_alter()
+ */
+function media_migrate_file_types_system_info_alter(&$info, $file, $type) {
+  if ($type == 'module' && $file->name == 'media_migrate_file_types') {
+    $info['hidden'] = FALSE;
+  }
+}
+
+/**
+ * Implements hook_menu().
+ */
+function media_migrate_file_types_menu() {
+  $items['admin/structure/file-types/upgrade'] = array(
+    'title' => 'Upgrade types',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('media_migrate_file_types_upgrade_file_types'),
+    'access arguments' => array('administer file types'),
+    'file' => 'includes/media_migrate_file_types.pages.inc',
+    'type' => MENU_CALLBACK,
+  );
+  $items['admin/structure/file-types/upgrade/confirm'] = array(
+    'title' => 'Upgrade types',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('media_migrate_file_types_upgrade_file_types_confirm'),
+    'access arguments' => array('administer file types'),
+    'file' => 'includes/media_migrate_file_types.pages.inc',
+    'type' => MENU_CALLBACK,
+  );
+
+  return $items;
+}
+
+/**
+ * Implements hook_help().
+ */
+function media_migrate_file_types_help($path, $arg) {
+  switch ($path) {
+    case 'admin/structure/file-types':
+      if (_media_migrate_file_types_get_migratable_file_types()) {
+        drupal_set_message(t('There are disabled/deleted file types that can be migrated to their new alternatives. Visit <a href="!url">migration page</a> to get more information.', array('!url' => url('admin/structure/file-types/upgrade'))));
+      }
+      break;
+  }
+}
+
+/**
+ * Checks if there are any files that belong to disabled or deleted file
+ * types.
+ *
+ * @return Array of file types (machine names) that are candidates for
+ *   migration.
+ */
+function _media_migrate_file_types_get_migratable_file_types() {
+  $query = db_select('file_managed', 'f')
+    ->fields('f', array('type'))
+    ->distinct();
+  $types = $query->execute()->fetchCol();
+
+  $enabled_types = array();
+  foreach (file_type_get_enabled_types() as $type) {
+    $enabled_types[] = $type->type;
+  }
+
+  return array_diff($types, $enabled_types);
+}
diff --git a/drupal7/sites/all/modules/media/modules/media_wysiwyg/css/media_wysiwyg.css b/drupal7/sites/all/modules/media/modules/media_wysiwyg/css/media_wysiwyg.css
new file mode 100644
index 00000000..7b6f0190
--- /dev/null
+++ b/drupal7/sites/all/modules/media/modules/media_wysiwyg/css/media_wysiwyg.css
@@ -0,0 +1,20 @@
+/**
+ * @file
+ * Styles for the format form.
+ *
+ * The display and layout of the Media browser assumes Drupal's Seven theme as
+ * the theme active when this is displayed.
+ */
+
+#media-wysiwyg-format-form {
+  margin: 20px;
+}
+
+#media-wysiwyg-format-form .media-item {
+  float: left;
+  margin-right: 10px;
+}
+
+#media-wysiwyg-format-form .form-item-format label {
+  display: inline;
+}
diff --git a/drupal7/sites/all/modules/media/images/wysiwyg-media.gif b/drupal7/sites/all/modules/media/modules/media_wysiwyg/images/wysiwyg-media.gif
similarity index 100%
rename from drupal7/sites/all/modules/media/images/wysiwyg-media.gif
rename to drupal7/sites/all/modules/media/modules/media_wysiwyg/images/wysiwyg-media.gif
diff --git a/drupal7/sites/all/modules/media/modules/media_wysiwyg/includes/media_wysiwyg.file_usage.inc b/drupal7/sites/all/modules/media/modules/media_wysiwyg/includes/media_wysiwyg.file_usage.inc
new file mode 100644
index 00000000..cbc1e841
--- /dev/null
+++ b/drupal7/sites/all/modules/media/modules/media_wysiwyg/includes/media_wysiwyg.file_usage.inc
@@ -0,0 +1,179 @@
+<?php
+
+/**
+ * @file
+ * Functions related to the tracking the file usage of embedded media.
+ */
+
+/**
+ * Implements hook_field_attach_insert().
+ *
+ * Track file usage for media files included in formatted text. Note that this
+ * is heavy-handed, and should be replaced when Drupal's filter system is
+ * context-aware.
+ */
+function media_wysiwyg_field_attach_insert($entity_type, $entity) {
+  _media_wysiwyg_filter_add_file_usage_from_fields($entity_type, $entity);
+}
+
+/**
+ * Implements hook_field_attach_update().
+ *
+ * @see media_field_attach_insert().
+ */
+function media_wysiwyg_field_attach_update($entity_type, $entity) {
+  _media_wysiwyg_filter_add_file_usage_from_fields($entity_type, $entity);
+}
+
+/**
+ * Add file usage from file references in an entity's text fields.
+ */
+function _media_wysiwyg_filter_add_file_usage_from_fields($entity_type, $entity) {
+  // Track the total usage for files from all fields combined.
+  $entity_files = media_wysiwyg_entity_field_count_files($entity_type, $entity);
+
+  list($entity_id, $entity_vid, $entity_bundle) = entity_extract_ids($entity_type, $entity);
+
+  // When an entity has revisions and then is saved again NOT as new version the
+  // previous revision of the entity has be loaded to get the last known good
+  // count of files. The saved data is compared against the last version
+  // so that a correct file count can be created for that (the current) version
+  // id. This code may assume some things about entities that are only true for
+  // node objects. This should be reviewed.
+  // @TODO this conditional can probably be condensed
+  if (empty($entity->revision) && empty($entity->old_vid) && empty($entity->is_new) && ! empty($entity->original)) {
+    $old_files = media_wysiwyg_entity_field_count_files($entity_type, $entity->original);
+    foreach ($old_files as $fid => $old_file_count) {
+      // Were there more files on the node just prior to saving?
+      if (empty($entity_files[$fid])) {
+        $entity_files[$fid] = 0;
+      }
+      if ($old_file_count > $entity_files[$fid]) {
+        $deprecate = $old_file_count - $entity_files[$fid];
+        // Now deprecate this usage
+        $file = file_load($fid);
+        if ($file) {
+          file_usage_delete($file, 'media', $entity_type, $entity_id, $deprecate);
+        }
+        // Usage is deleted, nothing more to do with this file
+        unset($entity_files[$fid]);
+      }
+      // There are the same number of files, nothing to do
+      elseif ($entity_files[$fid] ==  $old_file_count) {
+        unset($entity_files[$fid]);
+      }
+      // There are more files now, adjust the difference for the greater number.
+      // file_usage incrementing will happen below.
+      else {
+        // We just need to adjust what the file count will account for the new
+        // images that have been added since the increment process below will
+        // just add these additional ones in
+        $entity_files[$fid] = $entity_files[$fid] - $old_file_count;
+      }
+    }
+  }
+
+  // Each entity revision counts for file usage. If versions are not enabled
+  // the file_usage table will have no entries for this because of the delete
+  // query above.
+  foreach ($entity_files as $fid => $entity_count) {
+    if ($file = file_load($fid)) {
+      file_usage_add($file, 'media', $entity_type, $entity_id, $entity_count);
+    }
+  }
+}
+
+/**
+ * Parse file references from an entity's text fields and return them as an array.
+ */
+function media_wysiwyg_filter_parse_from_fields($entity_type, $entity) {
+  $file_references = array();
+
+  foreach (media_wysiwyg_filter_fields_with_text_filtering($entity_type, $entity) as $field_name) {
+    if ($field_items = field_get_items($entity_type, $entity, $field_name)) {
+      foreach ($field_items as $field_item) {
+        preg_match_all(MEDIA_WYSIWYG_TOKEN_REGEX, $field_item['value'], $matches);
+        foreach ($matches[0] as $tag) {
+          $tag = str_replace(array('[[', ']]'), '', $tag);
+          $tag_info = drupal_json_decode($tag);
+          if (isset($tag_info['fid']) && $tag_info['type'] == 'media') {
+            $file_references[] = $tag_info;
+          }
+        }
+
+        preg_match_all(MEDIA_WYSIWYG_TOKEN_REGEX, $field_item['value'], $matches_alt);
+        foreach ($matches_alt[0] as $tag) {
+          $tag = urldecode($tag);
+          $tag_info = drupal_json_decode($tag);
+          if (isset($tag_info['fid']) && $tag_info['type'] == 'media') {
+            $file_references[] = $tag_info;
+          }
+        }
+      }
+    }
+  }
+
+  return $file_references;
+}
+
+/**
+ * Utility function to get the file count in this entity
+ *
+ * @param type $entity
+ * @param type $entity_type
+ * @return int
+ */
+function media_wysiwyg_entity_field_count_files($entity_type, $entity) {
+  $entity_files = array();
+  foreach (media_wysiwyg_filter_parse_from_fields($entity_type, $entity) as $file_reference) {
+    if (empty($entity_files[$file_reference['fid']])) {
+      $entity_files[$file_reference['fid']] = 1;
+    }
+    else {
+      $entity_files[$file_reference['fid']]++;
+    }
+  }
+  return $entity_files;
+}
+
+/**
+ * Implements hook_entity_delete().
+ */
+function media_wysiwyg_entity_delete($entity, $type) {
+  list($entity_id) = entity_extract_ids($type, $entity);
+
+  db_delete('file_usage')
+    ->condition('module', 'media')
+    ->condition('type', $type)
+    ->condition('id', $entity_id)
+    ->execute();
+}
+
+/**
+ * Implements hook_field_attach_delete_revision().
+ *
+ * @param type $entity_type
+ * @param type $entity
+ */
+function media_wysiwyg_field_attach_delete_revision($entity_type, $entity) {
+  list($entity_id) = entity_extract_ids($entity_type, $entity);
+  $files = media_wysiwyg_entity_field_count_files($entity_type, $entity);
+  foreach ($files as $fid => $count) {
+    if ($file = file_load($fid)) {
+      file_usage_delete($file, 'media', $entity_type , $entity_id, $count);
+    }
+  }
+}
+
+/**
+ * Implements hook_entity_dependencies().
+ */
+function media_wysiwyg_entity_dependencies($entity, $entity_type) {
+  // Go through all the entity's text fields and add a dependency on any files
+  // that are referenced there.
+  $dependencies = array();
+  foreach (media_wysiwyg_filter_parse_from_fields($entity_type, $entity) as $file_reference) {
+    $dependencies[] = array('type' => 'file', 'id' => $file_reference['fid']);
+  }
+  return $dependencies;
+}
diff --git a/drupal7/sites/all/modules/media/modules/media_wysiwyg/includes/media_wysiwyg.filter.inc b/drupal7/sites/all/modules/media/modules/media_wysiwyg/includes/media_wysiwyg.filter.inc
new file mode 100644
index 00000000..44360b3d
--- /dev/null
+++ b/drupal7/sites/all/modules/media/modules/media_wysiwyg/includes/media_wysiwyg.filter.inc
@@ -0,0 +1,359 @@
+<?php
+
+/**
+ * @file
+ * Functions related to the WYSIWYG editor and the media input filter.
+ */
+
+define('MEDIA_WYSIWYG_TOKEN_REGEX', '/\[\[.*?\]\]/s');
+
+/**
+ * Filter callback for media markup filter.
+ *
+ * @TODO check for security probably pass text through filter_xss
+ */
+function media_wysiwyg_filter($text) {
+  $text = preg_replace_callback(MEDIA_WYSIWYG_TOKEN_REGEX, 'media_wysiwyg_token_to_markup', $text);
+  return $text;
+}
+
+/**
+ * Parses the contents of a CSS declaration block.
+ *
+ * @param string $declarations
+ *   One or more CSS declarations delimited by a semicolon. The same as a CSS
+ *   declaration block (see http://www.w3.org/TR/CSS21/syndata.html#rule-sets),
+ *   but without the opening and closing curly braces. Also the same as the
+ *   value of an inline HTML style attribute.
+ *
+ * @return array
+ *   A keyed array. The keys are CSS property names, and the values are CSS
+ *   property values.
+ */
+function media_wysiwyg_parse_css_declarations($declarations) {
+  $properties = array();
+  foreach (array_map('trim', explode(";", $declarations)) as $declaration) {
+    if ($declaration != '') {
+      list($name, $value) = array_map('trim', explode(':', $declaration, 2));
+      $properties[strtolower($name)] = $value;
+    }
+  }
+  return $properties;
+}
+
+/**
+ * Replace callback to convert a media file tag into HTML markup.
+ *
+ * @param string $match
+ *   Takes a match of tag code
+ * @param bool $wysiwyg
+ *   Set to TRUE if called from within the WYSIWYG text area editor.
+ *
+ * @return string
+ *   The HTML markup representation of the tag, or an empty string on failure.
+ *
+ * @see media_wysiwyg_get_file_without_label()
+ * @see hook_media_wysiwyg_token_to_markup_alter()
+ */
+function media_wysiwyg_token_to_markup($match, $wysiwyg = FALSE) {
+  $settings = array();
+  $match = str_replace("[[", "", $match);
+  $match = str_replace("]]", "", $match);
+  $tag = $match[0];
+
+  try {
+    if (!is_string($tag)) {
+      throw new Exception('Unable to find matching tag');
+    }
+
+    $tag_info = drupal_json_decode($tag);
+
+    if (!isset($tag_info['fid'])) {
+      throw new Exception('No file Id');
+    }
+
+    // Ensure the 'link_text' key is always defined.
+    if (!isset($tag_info['link_text'])) {
+      $tag_info['link_text'] = NULL;
+    }
+
+    // Ensure a valid view mode is being requested.
+    if (!isset($tag_info['view_mode'])) {
+      $tag_info['view_mode'] = variable_get('media_wysiwyg_wysiwyg_default_view_mode', 'full');
+    }
+    elseif ($tag_info['view_mode'] != 'default') {
+      $file_entity_info = entity_get_info('file');
+      if (!in_array($tag_info['view_mode'], array_keys($file_entity_info['view modes']))) {
+        // Media 1.x defined some old view modes that have been superseded by
+        // more semantically named ones in File Entity. The media_update_7203()
+        // function updates field settings that reference the old view modes,
+        // but it's impractical to update all text content, so adjust
+        // accordingly here.
+        static $view_mode_updates = array(
+          'media_preview' => 'preview',
+          'media_small' => 'teaser',
+          'media_large' => 'full',
+        );
+        if (isset($view_mode_updates[$tag_info['view_mode']])) {
+          $tag_info['view_mode'] = $view_mode_updates[$tag_info['view_mode']];
+        }
+        else {
+          throw new Exception('Invalid view mode');
+        }
+      }
+    }
+
+    $file = file_load($tag_info['fid']);
+    if (!$file) {
+      throw new Exception('Could not load media object');
+    }
+    $tag_info['file'] = $file;
+
+    // The class attributes is a string, but drupal requires it to be
+    // an array, so we fix it here.
+    if (!empty($tag_info['attributes']['class'])) {
+      $tag_info['attributes']['class'] = explode(" ", $tag_info['attributes']['class']);
+    }
+
+    // Grab the potentially overrided fields from the file.
+    $fields = media_wysiwyg_filter_field_parser($tag_info);
+
+    $attributes = is_array($tag_info['attributes']) ? $tag_info['attributes'] : array();
+    $attribute_whitelist = variable_get('media_wysiwyg_wysiwyg_allowed_attributes', _media_wysiwyg_wysiwyg_allowed_attributes_default());
+    $settings['attributes'] = array_intersect_key($attributes, array_flip($attribute_whitelist));
+    $settings['fields'] = $fields;
+
+    if (!empty($tag_info['attributes']) && is_array($tag_info['attributes'])) {
+      $settings['attributes'] = array_intersect_key($tag_info['attributes'], array_flip($attribute_whitelist));
+      $settings['fields'] = $fields;
+
+      // Many media formatters will want to apply width and height independently
+      // of the style attribute or the corresponding HTML attributes, so pull
+      // these two out into top-level settings. Different WYSIWYG editors have
+      // different behavior with respect to whether they store user-specified
+      // dimensions in the HTML attributes or the style attribute - check both.
+      // Per http://www.w3.org/TR/html5/the-map-element.html#attr-dim-width, the
+      // HTML attributes are merely hints: CSS takes precedence.
+      if (isset($settings['attributes']['style'])) {
+        $css_properties = media_wysiwyg_parse_css_declarations($settings['attributes']['style']);
+        foreach (array('width', 'height') as $dimension) {
+          if (isset($css_properties[$dimension]) && substr($css_properties[$dimension], -2) == 'px') {
+            $settings[$dimension] = substr($css_properties[$dimension], 0, -2);
+          }
+          elseif (isset($settings['attributes'][$dimension])) {
+            $settings[$dimension] = $settings['attributes'][$dimension];
+          }
+        }
+      }
+    }
+  }
+  catch (Exception $e) {
+    watchdog('media', 'Unable to render media from %tag. Error: %error', array('%tag' => $tag, '%error' => $e->getMessage()));
+    return '';
+  }
+
+  // If the tag has link text stored with it, override the filename with it for
+  // the rest of this function, so that if the file is themed as a link, the
+  // desired text will be used (see, for example, theme_file_link()).
+  // @todo: Try to find a less hacky way to do this.
+  if (isset($tag_info['link_text'])) {
+    // The link text will have characters such as "&" encoded for HTML, but the
+    // filename itself needs the raw value when it is used to build the link,
+    // in order to avoid double encoding.
+    $file->filename = decode_entities($tag_info['link_text']);
+  }
+
+  if ($wysiwyg) {
+    $settings['wysiwyg'] = $wysiwyg;
+    // If sending markup to a WYSIWYG, we need to pass the file infomation so
+    // that an inline macro can be generated when the WYSIWYG is detached.
+    // The WYSIWYG plugin is expecting this information in the
+    // Drupal.settings.mediaDataMap variable.
+    $element = media_wysiwyg_get_file_without_label($file, $tag_info['view_mode'], $settings);
+    $data = array(
+      'type' => 'media',
+      'fid'  => $file->fid,
+      'view_mode' => $tag_info['view_mode'],
+      'link_text' => $tag_info['link_text'],
+    );
+    drupal_add_js(array('mediaDataMap' => array($file->fid => $data)), 'setting');
+    $element['#attributes']['data-fid'] = $file->fid;
+    $element['#attributes']['class'][] = 'media-element';
+  }
+  else {
+    // Display the field elements.
+    $element = array();
+    $element['content']['file'] = media_wysiwyg_get_file_without_label($file, $tag_info['view_mode'], $settings);
+    // Overwrite or set the file #alt attribute if it has been set in this
+    // instance.
+    if (!empty($element['content']['file']['#attributes']['alt'])) {
+      $element['content']['file']['#alt'] = $element['content']['file']['#attributes']['alt'];
+    }
+    // Overwrite or set the file #title attribute if it has been set in this
+    // instance.
+    if (!empty($element['content']['file']['#attributes']['title'])) {
+      $element['content']['file']['#title'] = $element['content']['file']['#attributes']['title'];
+    }
+    field_attach_prepare_view('file', array($file->fid => $file), $tag_info['view_mode']);
+    entity_prepare_view('file', array($file->fid => $file));
+    $element['content'] += field_attach_view('file', $file, $tag_info['view_mode']);
+    if (count(element_children($element['content'])) > 1) {
+      // Add surrounding divs to group them together.
+      // We dont want divs when there are no additional fields to allow files
+      // to display inline with text, without breaking p tags.
+      $element['content']['#type'] = 'container';
+      $element['content']['#attributes']['class'] = array(
+        'media',
+        'media-element-container',
+        'media-' . $element['content']['file']['#view_mode']
+      );
+    }
+  }
+  drupal_alter('media_wysiwyg_token_to_markup', $element, $tag_info, $settings);
+  return drupal_render($element);
+}
+
+/**
+ * Parse the field array from the collapsed AJAX string.
+ */
+function media_wysiwyg_filter_field_parser($tag_info) {
+  $fields = array();
+  if (isset($tag_info['fields'])) {
+    foreach($tag_info['fields'] as $field_name => $field_value) {
+      if (strpos($field_name, 'field_') === 0) {
+        $parsed_field = explode('[', str_replace(']', '', $field_name));
+        $ref = &$fields;
+
+        // Each key of the field needs to be the child of the previous key.
+        foreach ($parsed_field as $key) {
+          if (!isset($ref[$key])) {
+            $ref[$key] = array();
+          }
+          $ref = &$ref[$key];
+        }
+
+        // The value should be set at the deepest level.
+        // Fields that use rich-text markup will be urlencoded.
+        $ref = urldecode($field_value);
+      }
+    }
+  }
+  return $fields;
+}
+
+/**
+ * Builds a map of media tags in the element.
+ *
+ * Builds a map of the media tags in an element that are being rendered to their
+ * rendered HTML. The map is stored in JS, so we can transform them when the
+ * editor is being displayed.
+ */
+function media_wysiwyg_pre_render_text_format($element) {
+  // filter_process_format() copies properties to the expanded 'value' child
+  // element.
+  if (!isset($element['format'])) {
+    return $element;
+  }
+
+  $field = &$element['value'];
+  $settings = array(
+    'field' => $field['#id'],
+  );
+
+  $tagmap = _media_wysiwyg_generate_tagMap($field['#value']);
+
+  if (isset($tagmap)) {
+    drupal_add_js(array('tagmap' => $tagmap), 'setting');
+  }
+  return $element;
+}
+
+/**
+ * Creates map of inline media tags.
+ *
+ * Generates an array of [inline tags] => <html> to be used in filter
+ * replacement and to add the mapping to JS.
+ *
+ * @param string $text
+ *   The String containing text and html markup of textarea
+ *
+ * @return array
+ *   An associative array with tag code as key and html markup as the value.
+ *
+ * @see media_process_form()
+ * @see media_token_to_markup()
+ */
+function _media_wysiwyg_generate_tagMap($text) {
+  // Making $tagmap static as this function is called many times and
+  // adds duplicate markup for each tag code in Drupal.settings JS,
+  // so in media_process_form it adds something like tagCode:<markup>,
+  // <markup> and when we replace in attach see two duplicate images
+  // for one tagCode. Making static would make function remember value
+  // between function calls. Since media_process_form is multiple times
+  // with same form, this function is also called multiple times.
+  static $tagmap = array();
+  preg_match_all("/\[\[.*?\]\]/s", $text, $matches, PREG_SET_ORDER);
+  foreach ($matches as $match) {
+    // We see if tagContent is already in $tagMap, if not we add it
+    // to $tagmap.  If we return an empty array, we break embeddings of the same
+    // media multiple times.
+    if (empty($tagmap[$match[0]])) {
+      // @TODO: Total HACK, but better than nothing.
+      // We should find a better way of cleaning this up.
+      if ($markup_for_media = media_wysiwyg_token_to_markup($match, TRUE)) {
+        $tagmap[$match[0]] = $markup_for_media;
+      }
+      else {
+        $missing = file_create_url(drupal_get_path('module', 'media') . '/images/icons/default/image-x-generic.png');
+        $tagmap[$match[0]] = '<div><img src="' . $missing . '" width="100px" height="100px"/></div>';
+      }
+    }
+  }
+  return $tagmap;
+}
+
+/**
+ * Return a list of view modes allowed for a file embedded in the WYSIWYG.
+ *
+ * @param object $file
+ *   A file entity.
+ *
+ * @return array
+ *   An array of view modes that can be used on the file when embedded in the
+ *   WYSIWYG.
+ */
+function media_wysiwyg_get_wysiwyg_allowed_view_modes($file) {
+  $enabled_view_modes = &drupal_static(__FUNCTION__, array());
+
+  // @todo Add more caching for this.
+  if (!isset($enabled_view_modes[$file->type])) {
+    $enabled_view_modes[$file->type] = array();
+
+    // Add the default view mode by default.
+    $enabled_view_modes[$file->type]['default'] = array('label' => t('Default'), 'custom settings' => TRUE);
+
+    $entity_info = entity_get_info('file');
+    $view_mode_settings = field_view_mode_settings('file', $file->type);
+    foreach ($entity_info['view modes'] as $view_mode => $view_mode_info) {
+      // Do not show view modes that don't have their own settings and will
+      // only fall back to the default view mode.
+      if (empty($view_mode_settings[$view_mode]['custom_settings'])) {
+        continue;
+      }
+
+      // Don't present the user with an option to choose a view mode in which
+      // the file is hidden.
+      $extra_fields = field_extra_fields_get_display('file', $file->type, $view_mode);
+      if (empty($extra_fields['file']['visible'])) {
+        continue;
+      }
+
+      // Add the view mode to the list of enabled view modes.
+      $enabled_view_modes[$file->type][$view_mode] = $view_mode_info;
+    }
+  }
+
+  $view_modes = $enabled_view_modes[$file->type];
+  drupal_alter('media_wysiwyg_wysiwyg_allowed_view_modes', $view_modes, $file);
+  return $view_modes;
+}
diff --git a/drupal7/sites/all/modules/media/modules/media_wysiwyg/includes/media_wysiwyg.pages.inc b/drupal7/sites/all/modules/media/modules/media_wysiwyg/includes/media_wysiwyg.pages.inc
new file mode 100644
index 00000000..ab1a845d
--- /dev/null
+++ b/drupal7/sites/all/modules/media/modules/media_wysiwyg/includes/media_wysiwyg.pages.inc
@@ -0,0 +1,111 @@
+<?php
+
+/**
+ * @file
+ * Common pages for the Media WYSIWYG module.
+ */
+
+/**
+ * Form callback used when embedding media.
+ *
+ * Allows the user to pick a format for their media file.
+ * Can also have additional params depending on the media type.
+ */
+function media_wysiwyg_format_form($form, &$form_state, $file) {
+  $form_state['file'] = $file;
+
+  // Allow for overrides to the fields.
+  $query_fields = isset($_GET['fields']) ? drupal_json_decode($_GET['fields']) : array();
+  $fields = media_wysiwyg_filter_field_parser(array('fields' => $query_fields), $file);
+
+  $view_modes = media_wysiwyg_get_wysiwyg_allowed_view_modes($file);
+  $formats = $options = array();
+  foreach ($view_modes as $view_mode => $view_mode_info) {
+    // @TODO: Display more verbose information about which formatter and what it
+    // does.
+    $options[$view_mode] = $view_mode_info['label'];
+    $element = media_wysiwyg_get_file_without_label($file, $view_mode, array('wysiwyg' => TRUE));
+
+    // Make a pretty name out of this.
+    $formats[$view_mode] = drupal_render($element);
+  }
+
+  // Add the previews back into the form array so they can be altered.
+  $form['#formats'] = &$formats;
+
+  if (!count($formats)) {
+    throw new Exception('Unable to continue, no available formats for displaying media.');
+    return;
+  }
+
+  // Allow for overrides to the display format.
+  $default_view_mode = is_array($query_fields) && isset($query_fields['format']) ? $query_fields['format'] : variable_get('media_wysiwyg_wysiwyg_default_view_mode', 'full');
+  if (!isset($formats[$default_view_mode])) {
+    $default_view_mode = key($formats);
+  }
+
+  // Add the previews by reference so that they can easily be altered by
+  // changing $form['#formats'].
+  $settings['media']['formatFormFormats'] = &$formats;
+  $form['#attached']['js'][] = array('data' => $settings, 'type' => 'setting');
+
+  // Add the required libraries, JavaScript and CSS for the form.
+  $form['#attached']['library'][] = array('media', 'media_base');
+  $form['#attached']['library'][] = array('system', 'form');
+  $form['#attached']['css'][] = drupal_get_path('module', 'media_wysiwyg') . '/css/media_wysiwyg.css';
+  $form['#attached']['js'][] = drupal_get_path('module', 'media_wysiwyg') . '/js/media_wysiwyg.format_form.js';
+
+  $form['title'] = array(
+    '#markup' => t('Embedding %filename', array('%filename' => $file->filename)),
+  );
+
+  $preview = media_get_thumbnail_preview($file);
+
+  $form['preview'] = array(
+    '#type' => 'markup',
+    '#title' => check_plain(basename($file->uri)),
+    '#markup' => drupal_render($preview),
+  );
+
+  // These will get passed on to WYSIWYG.
+  $form['options'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('options'),
+  );
+
+  $form['options']['format'] = array(
+    '#type' => 'select',
+    '#title' => t('Display as'),
+    '#options' => $options,
+    '#default_value' => $default_view_mode,
+    '#description' => t('Choose the type of display you would like for this
+      file. Please be aware that files may display differently than they do when
+      they are inserted into an editor.')
+  );
+
+  // Add fields from the file, so that we can override them if neccesary.
+  $form['options']['fields'] = array();
+  foreach ($fields as $field_name => $field_value) {
+    $file->{$field_name} = $field_value;
+  }
+  field_attach_form('file', $file, $form['options']['fields'], $form_state);
+  $instance = field_info_instances('file', $file->type);
+  foreach ($instance as $field_name => $field_value) {
+    if (isset($instance[$field_name]['settings']) && isset($instance[$field_name]['settings']['wysiwyg_override']) && !$instance[$field_name]['settings']['wysiwyg_override']) {
+      unset($form['options']['fields'][$field_name]);
+    }
+  }
+
+  // Similar to a form_alter, but we want this to run first so that
+  // media.types.inc can add the fields specific to a given type (like alt tags
+  // on media). If implemented as an alter, this might not happen, making other
+  // alters not be able to work on those fields.
+  // @todo: We need to pass in existing values for those attributes.
+  drupal_alter('media_wysiwyg_format_form_prepare', $form, $form_state, $file);
+
+  if (!element_children($form['options'])) {
+    $form['options']['#attributes'] = array('style' => 'display:none');
+  }
+
+  return $form;
+}
diff --git a/drupal7/sites/all/modules/media/modules/media_wysiwyg/includes/media_wysiwyg.uuid.inc b/drupal7/sites/all/modules/media/modules/media_wysiwyg/includes/media_wysiwyg.uuid.inc
new file mode 100644
index 00000000..3d228e3d
--- /dev/null
+++ b/drupal7/sites/all/modules/media/modules/media_wysiwyg/includes/media_wysiwyg.uuid.inc
@@ -0,0 +1,88 @@
+<?php
+
+/**
+ * @file
+ * Functions related to adding UUID support to embedded media.
+ */
+
+/**
+ * Implements hook_entity_uuid_load().
+ */
+function media_wysiwyg_entity_uuid_load(&$entities, $entity_type) {
+  // Go through all the entity's text fields and replace file IDs in media
+  // tokens with the corresponding UUID.
+  foreach ($entities as $entity) {
+    media_wysiwyg_filter_replace_tokens_in_all_text_fields($entity_type, $entity, 'media_wysiwyg_token_fid_to_uuid');
+  }
+}
+
+/**
+ * Implements hook_entity_uuid_presave().
+ */
+function media_wysiwyg_entity_uuid_presave(&$entity, $entity_type) {
+  // Go through all the entity's text fields and replace UUIDs in media tokens
+  // with the corresponding file ID.
+  media_wysiwyg_filter_replace_tokens_in_all_text_fields($entity_type, $entity, 'media_wysiwyg_token_uuid_to_fid');
+}
+
+/**
+ * Replaces media tokens in an entity's text fields, using the specified callback function.
+ */
+function media_wysiwyg_filter_replace_tokens_in_all_text_fields($entity_type, $entity, $callback) {
+  $text_field_names = media_wysiwyg_filter_fields_with_text_filtering($entity_type, $entity);
+  foreach ($text_field_names as $field_name) {
+    if (!empty($entity->{$field_name})) {
+      $field = field_info_field($field_name);
+      $all_languages = field_available_languages($entity_type, $field);
+      $field_languages = array_intersect($all_languages, array_keys($entity->{$field_name}));
+      foreach ($field_languages as $language) {
+        if (!empty($entity->{$field_name}[$language])) {
+          foreach ($entity->{$field_name}[$language] as &$item) {
+            $item['value'] = preg_replace_callback(MEDIA_WYSIWYG_TOKEN_REGEX, $callback, $item['value']);
+          }
+        }
+      }
+    }
+  }
+}
+
+/**
+ * Callback to replace file IDs with UUIDs in a media token.
+ */
+function media_wysiwyg_token_fid_to_uuid($matches) {
+  return _media_wysiwyg_token_uuid_replace($matches, 'entity_get_uuid_by_id');
+}
+
+/**
+ * Callback to replace UUIDs with file IDs in a media token.
+ */
+function media_wysiwyg_token_uuid_to_fid($matches) {
+  return _media_wysiwyg_token_uuid_replace($matches, 'entity_get_id_by_uuid');
+}
+
+/**
+ * Helper function to replace UUIDs with file IDs or vice versa.
+ *
+ * @param array $matches
+ *   An array of matches for media tokens, from a preg_replace_callback()
+ *   callback function.
+ * @param string $entity_uuid_function
+ *   Either 'entity_get_uuid_by_id' (to replace file IDs with UUIDs in the
+ *   token) or 'entity_get_id_by_uuid' (to replace UUIDs with file IDs).
+ *
+ * @return string
+ *   A string representing the JSON-encoded token, with the appropriate
+ *   replacement between file IDs and UUIDs.
+ */
+function _media_wysiwyg_token_uuid_replace($matches, $entity_uuid_function) {
+  $tag = $matches[0];
+  $tag = str_replace(array('[[', ']]'), '', $tag);
+  $tag_info = drupal_json_decode($tag);
+  if (isset($tag_info['fid'])) {
+    if ($new_ids = $entity_uuid_function('file', array($tag_info['fid']))) {
+      $new_id = reset($new_ids);
+      $tag_info['fid'] = $new_id;
+    }
+  }
+  return '[[' . drupal_json_encode($tag_info) . ']]';
+}
diff --git a/drupal7/sites/all/modules/media/modules/media_wysiwyg/js/media_wysiwyg.filter.js b/drupal7/sites/all/modules/media/modules/media_wysiwyg/js/media_wysiwyg.filter.js
new file mode 100644
index 00000000..5ac10ec4
--- /dev/null
+++ b/drupal7/sites/all/modules/media/modules/media_wysiwyg/js/media_wysiwyg.filter.js
@@ -0,0 +1,261 @@
+/**
+ *  @file
+ *  File with utilities to handle media in html editing.
+ */
+(function ($) {
+
+  Drupal.media = Drupal.media || {};
+  /**
+   * Utility to deal with media tokens / placeholders.
+   */
+  Drupal.media.filter = {
+    /**
+     * Replaces media tokens with the placeholders for html editing.
+     * @param content
+     */
+    replaceTokenWithPlaceholder: function(content) {
+      Drupal.media.filter.ensure_tagmap();
+      var matches = content.match(/\[\[.*?\]\]/g);
+
+      if (matches) {
+        for (var i = 0; i < matches.length; i++) {
+          var match = matches[i];
+          if (match.indexOf('"type":"media"') == -1) {
+            continue;
+          }
+
+          // Check if the macro exists in the tagmap. This ensures backwards
+          // compatibility with existing media and is moderately more efficient
+          // than re-building the element.
+          var media = Drupal.settings.tagmap[match];
+          var media_json = match.replace('[[', '').replace(']]', '');
+
+          // Ensure that the media JSON is valid.
+          try {
+            var media_definition = JSON.parse(media_json);
+          }
+          catch (err) {
+            // @todo: error logging.
+            // Content should be returned to prevent an empty editor.
+            return content;
+          }
+
+          // Re-build the media if the macro has changed from the tagmap.
+          if (!media && media_definition.fid) {
+            Drupal.media.filter.ensureSourceMap();
+            var source = Drupal.settings.mediaSourceMap[media_definition.fid];
+            media = document.createElement(source.tagName);
+            media.src = source.src;
+          }
+
+          // Apply attributes.
+          var element = Drupal.media.filter.create_element(media, media_definition);
+          var markup  = Drupal.media.filter.outerHTML(element);
+
+          // Use split and join to replace all instances of macro with markup.
+          content = content.split(match).join(markup);
+        }
+      }
+
+      return content;
+    },
+
+    /**
+     * Replaces media elements with tokens.
+     *
+     * @param content (string)
+     *   The markup within the wysiwyg instance.
+     */
+    replacePlaceholderWithToken: function(content) {
+      Drupal.media.filter.ensure_tagmap();
+
+      // Rewrite the tagmap in case any of the macros have changed.
+      Drupal.settings.tagmap = {};
+
+      // Wrap the content to be able to use replaceWith() and html().
+      content = $('<div>').append(content);
+      var media = $('.media-element', content);
+
+      if (media.length) {
+        // Replace all media elements with their respective macros.
+        media.replaceWith(function() {
+          var el = $(this),
+            macro = Drupal.media.filter.create_macro(el);
+
+          // Store the markup for more efficient rendering later.
+          // @see replaceTokenWidthPlaceholder()
+          Drupal.settings.tagmap[macro] = Drupal.media.filter.outerHTML(el);
+
+          return macro;
+        });
+      }
+
+      return content.html();
+    },
+
+    /**
+     * Serializes file information as a url-encoded JSON object and stores it
+     * as a data attribute on the html element.
+     *
+     * @param html (string)
+     *    A html element to be used to represent the inserted media element.
+     * @param info (object)
+     *    A object containing the media file information (fid, view_mode, etc).
+     */
+    create_element: function (html, info) {
+      if ($('<div>').append(html).text().length === html.length) {
+        // Element is not an html tag. Surround it in a span element so we can
+        // pass the file attributes.
+        html = '<span>' + html + '</span>';
+      }
+      var element = $(html);
+
+      // Parse out link wrappers. They will be re-applied when the image is
+      // rendered on the front-end.
+      if (element.is('a')) {
+        element = element.children();
+      }
+
+      // Move attributes from the file info array to the placeholder element.
+      if (info.attributes) {
+        $.each(Drupal.settings.media.wysiwyg_allowed_attributes, function(i, a) {
+          if (info.attributes[a]) {
+            element.attr(a, info.attributes[a]);
+          }
+        });
+        delete(info.attributes);
+
+        // Store information to rebuild the element later, if necessary.
+        Drupal.media.filter.ensureSourceMap();
+        Drupal.settings.mediaSourceMap[info.fid] = {
+          tagName: element[0].tagName,
+          src: element[0].src
+        }
+      }
+
+      info.type = info.type || "media";
+
+      // Store the data in the data map.
+      Drupal.media.filter.ensureDataMap();
+      Drupal.settings.mediaDataMap[info.fid] = info;
+
+      // Store the fid in the DOM to retrieve the data from the info map.
+      element.attr('data-fid', info.fid);
+
+      // Add media-element class so we can find markup element later.
+      var classes = ['media-element'];
+
+      if (info.view_mode) {
+        classes.push('file-' + info.view_mode.replace(/_/g, '-'));
+      }
+      element.addClass(classes.join(' '));
+
+      return element;
+    },
+
+    /**
+     * Create a macro representation of the inserted media element.
+     *
+     * @param element (jQuery object)
+     *    A media element with attached serialized file info.
+     */
+    create_macro: function (element) {
+      var file_info = Drupal.media.filter.extract_file_info(element);
+      if (file_info) {
+        return '[[' + JSON.stringify(file_info) + ']]';
+      }
+      return false;
+    },
+
+    /**
+     * Extract the file info from a WYSIWYG placeholder element as JSON.
+     *
+     * @param element (jQuery object)
+     *    A media element with associated file info via a file id (fid).
+     */
+    extract_file_info: function (element) {
+      var fid, file_info, value;
+
+      if (fid = element.data('fid')) {
+        Drupal.media.filter.ensureDataMap();
+
+        if (file_info = Drupal.settings.mediaDataMap[fid]) {
+          file_info.attributes = {};
+
+          $.each(Drupal.settings.media.wysiwyg_allowed_attributes, function(i, a) {
+            if (value = element.attr(a)) {
+              // Replace &quot; by \" to avoid error with JSON format.
+              if (typeof value == 'string') {
+                value = value.replace('&quot;', '\\"');
+              }
+              file_info.attributes[a] = value;
+            }
+          });
+
+          // Extract the link text, if there is any.
+          file_info.link_text = element.find('a').html();
+        }
+      }
+
+      return file_info;
+    },
+
+    /**
+     * Gets the HTML content of an element.
+     *
+     * @param element (jQuery object)
+     */
+    outerHTML: function (element) {
+      return element[0].outerHTML || $('<div>').append(element.eq(0).clone()).html();
+    },
+
+    /**
+     * Gets the wrapped HTML content of an element to insert into the wysiwyg.
+     *
+     * It also registers the element in the tag map so that the token
+     * replacement works.
+     *
+     * @param element (jQuery object) The element to insert.
+     *
+     * @see Drupal.media.filter.replacePlaceholderWithToken()
+     */
+    getWysiwygHTML: function (element) {
+      // Create the markup and the macro.
+      var markup = Drupal.media.filter.outerHTML(element),
+        macro = Drupal.media.filter.create_macro(element);
+
+      // Store macro/markup in the tagmap.
+      Drupal.media.filter.ensure_tagmap();
+      Drupal.settings.tagmap[macro] = markup;
+
+      // Return the html code to insert in an editor and use it with
+      // replacePlaceholderWithToken()
+      return markup;
+    },
+
+    /**
+     * Ensures the src tracking has been initialized and returns it.
+     */
+    ensureSourceMap: function() {
+      Drupal.settings.mediaSourceMap = Drupal.settings.mediaSourceMap || {};
+      return Drupal.settings.mediaSourceMap;
+    },
+
+    /**
+     * Ensures the data tracking has been initialized and returns it.
+     */
+    ensureDataMap: function() {
+      Drupal.settings.mediaDataMap = Drupal.settings.mediaDataMap || {};
+      return Drupal.settings.mediaDataMap;
+    },
+
+    /**
+     * Ensures the tag map has been initialized and returns it.
+     */
+    ensure_tagmap: function () {
+      Drupal.settings.tagmap = Drupal.settings.tagmap || {};
+      return Drupal.settings.tagmap;
+    }
+  }
+
+})(jQuery);
diff --git a/drupal7/sites/all/modules/media/modules/media_wysiwyg/js/media_wysiwyg.format_form.js b/drupal7/sites/all/modules/media/modules/media_wysiwyg/js/media_wysiwyg.format_form.js
new file mode 100644
index 00000000..f9b16f43
--- /dev/null
+++ b/drupal7/sites/all/modules/media/modules/media_wysiwyg/js/media_wysiwyg.format_form.js
@@ -0,0 +1,69 @@
+
+/**
+ *  @file
+ *  Attach behaviors to formatter radio select when selecting a media's display
+ *  formatter.
+ */
+
+(function ($) {
+namespace('Drupal.media.formatForm');
+
+Drupal.media.mediaFormatSelected = {};
+
+Drupal.behaviors.mediaFormatForm = {
+  attach: function (context, settings) {
+    // Add the "Submit" button inside the IFRAME that trigger the behavior of
+    // the hidden "OK" button that is outside the IFRAME.
+    // @see Drupal.media.browser.validateButtons() for more details.
+
+    // @note I think this should be handled in media.browser.js in
+    // Drupal.media.browser.validateButtons but I'm not sure how crufty this
+    // particular functionality is. We should evaluate if it is still needed.
+
+    // @TODO can these be added to the content being displayed via form_alter?
+
+    // Adding the buttons should only be done once in order to prevent multiple
+    // buttons from being added if part of the form is updated via AJAX
+    $('#media-wysiwyg-format-form').once('format', function() {
+      $('<a class="button fake-ok">' + Drupal.t('Submit') + '</a>').appendTo($('#media-wysiwyg-format-form')).bind('click', Drupal.media.formatForm.submit);
+    });
+  }
+};
+
+Drupal.media.formatForm.getOptions = function () {
+  // Get all the values
+  var ret = {};
+
+  $.each($('#media-wysiwyg-format-form .fieldset-wrapper *').serializeArray(), function (i, field) {
+    ret[field.name] = field.value;
+
+    // When a field uses a WYSIWYG format, the value needs to be extracted.
+    if (field.name.match(/\[format\]/i)) {
+      field.name = field.name.replace(/\[format\]/i, '[value]');
+      field.key  = 'edit-' + field.name.replace(/[_\[]/g, '-').replace(/[\]]/g, '');
+
+      if (Drupal.wysiwyg.instances[field.key]) {
+        // Retrieve the content from the WYSIWYG instance.
+        ret[field.name] = Drupal.wysiwyg.instances[field.key].getContent();
+
+        // Escape the double-quotes and encode it to play nicely within JSON.
+        ret[field.name] = encodeURIComponent(ret[field.name].replace(/"/g, '\\"'));
+      }
+    }
+  });
+
+  return ret;
+};
+
+Drupal.media.formatForm.getFormattedMedia = function () {
+  var formatType = $("#edit-format").val();
+  return { type: formatType, options: Drupal.media.formatForm.getOptions(), html: Drupal.settings.media.formatFormFormats[formatType] };
+};
+
+Drupal.media.formatForm.submit = function () {
+  // @see Drupal.behaviors.mediaFormatForm.attach().
+  var buttons = $(parent.window.document.body).find('#mediaStyleSelector').parent('.ui-dialog').find('.ui-dialog-buttonpane button');
+  buttons[0].click();
+}
+
+})(jQuery);
diff --git a/drupal7/sites/all/modules/media/js/wysiwyg-media.js b/drupal7/sites/all/modules/media/modules/media_wysiwyg/js/wysiwyg-media.js
similarity index 99%
rename from drupal7/sites/all/modules/media/js/wysiwyg-media.js
rename to drupal7/sites/all/modules/media/modules/media_wysiwyg/js/wysiwyg-media.js
index ac5bf4d6..af99097b 100644
--- a/drupal7/sites/all/modules/media/js/wysiwyg-media.js
+++ b/drupal7/sites/all/modules/media/modules/media_wysiwyg/js/wysiwyg-media.js
@@ -22,6 +22,7 @@ Drupal.wysiwyg.plugins.media = {
   isNode: function(node) {
     return $(node).is('img.media-element');
   },
+
   /**
    * Execute the button.
    *
diff --git a/drupal7/sites/all/modules/media/modules/media_wysiwyg/media_wysiwyg.api.php b/drupal7/sites/all/modules/media/modules/media_wysiwyg/media_wysiwyg.api.php
new file mode 100644
index 00000000..894e89be
--- /dev/null
+++ b/drupal7/sites/all/modules/media/modules/media_wysiwyg/media_wysiwyg.api.php
@@ -0,0 +1,71 @@
+<?php
+
+/**
+ * @file
+ * Hooks provided by the Media WYSIWYG module.
+ */
+
+/**
+ * Alter a list of view modes allowed for a file embedded in the WYSIWYG.
+ *
+ * @param array $view_modes
+ *   An array of view modes that can be used on the file when embedded in the
+ *   WYSIWYG.
+ * @param object $file
+ *   A file entity.
+ *
+ * @see media_get_wysiwyg_allowed_view_modes()
+ */
+function hook_media_wysiwyg_wysiwyg_allowed_view_modes_alter(&$view_modes, $file) {
+  $view_modes['default']['label'] = t('Display an unmodified version of the file');
+  unset($view_modes['preview']);
+}
+
+/**
+ * Alter the WYSIWYG view mode selection form.
+ *
+ * Similar to a form_alter, but runs first so that modules can add
+ * fields specific to a given file type (like alt tags on images) before alters
+ * begin to work on the fields.
+ *
+ * @param array $form
+ *   An associative array containing the structure of the form.
+ * @param array $form_state
+ *   An associative array containing the current state of the form.
+ * @param object $file
+ *   A file entity.
+ *
+ * @see media_format_form()
+ */
+function hook_media_wysiwyg_format_form_prepare_alter(&$form, &$form_state, $file) {
+  $form['preview']['#access'] = FALSE;
+
+  $file = $form_state['file'];
+  $form['heading']['#markup'] = t('Embedding %filename of type %filetype', array('%filename' => $file->filename, '%filetype' => $file->type));
+}
+
+/**
+ * Alter the output generated by Media filter tags.
+ *
+ * @param array $element
+ *   The renderable array of output generated for the filter tag.
+ * @param array $tag_info
+ *   The filter tag converted into an associative array by
+ *   media_token_to_markup() with the following elements:
+ *   - 'fid': The ID of the media file being rendered.
+ *   - 'file': The object from file_load() of the media file being rendered.
+ *   - 'view_mode': The view mode being used to render the file.
+ *   - 'attributes': An additional array of attributes that could be output
+ *     with media_get_file_without_label().
+ * @param array $settings
+ *   An additional array of settings.
+ *   - 'wysiwyg': A boolean if the output is for the WYSIWYG preview or FALSE
+ *     if for normal rendering.
+ *
+ * @see media_token_to_markup()
+ */
+function hook_media_wysiwyg_token_to_markup_alter(&$element, $tag_info, $settings) {
+  if (empty($settings['wysiwyg'])) {
+    $element['#attributes']['alt'] = t('This media has been output using the @mode view mode.', array('@mode' => $tag_info['view_mode']));
+  }
+}
diff --git a/drupal7/sites/all/modules/media/modules/media_wysiwyg/media_wysiwyg.ckeditor.inc b/drupal7/sites/all/modules/media/modules/media_wysiwyg/media_wysiwyg.ckeditor.inc
new file mode 100644
index 00000000..236ef4bf
--- /dev/null
+++ b/drupal7/sites/all/modules/media/modules/media_wysiwyg/media_wysiwyg.ckeditor.inc
@@ -0,0 +1,37 @@
+<?php
+
+/**
+ * @file
+ * Provides WYSIWYG integration for CKEditor.
+ */
+
+/**
+ * Implements hook_ckeditor_plugin().
+ */
+function media_wysiwyg_ckeditor_plugin() {
+  return array(
+    'media' => array(
+      'name' => 'media',
+      'desc' => t('Plugin for inserting images from Drupal media module'),
+      'path' => base_path() . drupal_get_path('module', 'media_wysiwyg') . '/wysiwyg_plugins/media_ckeditor/',
+      'buttons' => array(
+        'Media' => array(
+          'icon' => 'images/icon.gif',
+          'label' => 'Add media',
+        ),
+      ),
+      'default' => 'f',
+    ),
+  );
+}
+
+/**
+ * Implements hook_ckeditor_plugin_alter().
+ */
+function media_wysiwyg_ckeditor_plugin_alter(&$plugins) {
+  // To ensure the ckeditor media integration is done by this module all other
+  // integrations are overwritten here. However additionally added keys will be
+  // left intact.
+  $default_plugin = media_wysiwyg_ckeditor_plugin();
+  $plugins['media'] = $default_plugin['media'] + $plugins['media'];
+}
diff --git a/drupal7/sites/all/modules/media/modules/media_wysiwyg/media_wysiwyg.info b/drupal7/sites/all/modules/media/modules/media_wysiwyg/media_wysiwyg.info
new file mode 100644
index 00000000..a88618bd
--- /dev/null
+++ b/drupal7/sites/all/modules/media/modules/media_wysiwyg/media_wysiwyg.info
@@ -0,0 +1,23 @@
+name = Media WYSIWYG
+description = Adds support for embedding media using client-side WYSIWYG editors.
+package = Media
+core = 7.x
+
+dependencies[] = media
+
+test_dependencies[] = ckeditor
+test_dependencies[] = token
+test_dependencies[] = wysiwyg
+
+files[] = media_wysiwyg.test
+files[] = tests/media_wysiwyg.file_usage.test
+files[] = tests/media_wysiwyg.macro.test
+
+configure = admin/config/media/browser
+
+; Information added by Drupal.org packaging script on 2014-10-04
+version = "7.x-2.0-alpha4"
+core = "7.x"
+project = "media"
+datestamp = "1412422430"
+
diff --git a/drupal7/sites/all/modules/media/modules/media_wysiwyg/media_wysiwyg.install b/drupal7/sites/all/modules/media/modules/media_wysiwyg/media_wysiwyg.install
new file mode 100644
index 00000000..6d2d5e49
--- /dev/null
+++ b/drupal7/sites/all/modules/media/modules/media_wysiwyg/media_wysiwyg.install
@@ -0,0 +1,20 @@
+<?php
+
+/**
+ * @file
+ * Install, update and uninstall functions for the Media WYSIWYG module.
+ */
+
+/**
+ * Implements hook_uninstall().
+ */
+function media_wysiwyg_uninstall() {
+  // Remove variables.
+  variable_del('media_wysiwyg_wysiwyg_title');
+  variable_del('media_wysiwyg_wysiwyg_icon_title');
+  variable_del('media_wysiwyg_wysiwyg_default_view_mode');
+  variable_del('media_wysiwyg_wysiwyg_upload_directory');
+  variable_del('media_wysiwyg_wysiwyg_allowed_types');
+  variable_del('media_wysiwyg_wysiwyg_allowed_attributes');
+  variable_del('media_wysiwyg_wysiwyg_browser_plugins');
+}
diff --git a/drupal7/sites/all/modules/media/modules/media_wysiwyg/media_wysiwyg.module b/drupal7/sites/all/modules/media/modules/media_wysiwyg/media_wysiwyg.module
new file mode 100644
index 00000000..1fb7a834
--- /dev/null
+++ b/drupal7/sites/all/modules/media/modules/media_wysiwyg/media_wysiwyg.module
@@ -0,0 +1,303 @@
+<?php
+
+/**
+ * @file
+ * Primarily Drupal hooks.
+ */
+
+// Functions for tracking the file usage of [[inline tags]].
+require_once dirname(__FILE__) . '/includes/media_wysiwyg.file_usage.inc';
+
+// Functions for working with [[inline tags]] and wysiwyg editors.
+require_once dirname(__FILE__) . '/includes/media_wysiwyg.filter.inc';
+
+// Functions for UUID support to embedded media.
+require_once dirname(__FILE__) . '/includes/media_wysiwyg.uuid.inc';
+
+/**
+ * Implements hook_hook_info().
+ */
+function media_wysiwyg_hook_info() {
+  $hooks = array(
+    'media_wysiwyg_token_to_markup_alter',
+    'media_wysiwyg_allowed_view_modes_alter',
+    'media_wysiwyg_format_form_prepare_alter',
+  );
+
+  return array_fill_keys($hooks, array('group' => 'media_wysiwyg'));
+}
+
+/**
+ * Implements hook_menu().
+ */
+function media_wysiwyg_menu() {
+  $items['media/%file/format-form'] = array(
+    'title' => 'Style selector',
+    'description' => 'Choose a format for a piece of media',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('media_wysiwyg_format_form', 1),
+    'access callback' => 'file_entity_access',
+    'access arguments' => array('view', 1),
+    'file' => 'includes/media_wysiwyg.pages.inc',
+    'theme callback' => 'media_dialog_get_theme_name',
+    'type' => MENU_CALLBACK,
+  );
+
+  return $items;
+}
+
+/**
+ * Implements hook_element_info_alter().
+ */
+function media_wysiwyg_element_info_alter(&$types) {
+  $types['text_format']['#pre_render'][] = 'media_wysiwyg_pre_render_text_format';
+}
+
+/**
+ * Implements hook_form_FORM_ID_alter().
+ */
+function media_wysiwyg_form_wysiwyg_profile_form_alter(&$form, &$form_state) {
+  // Add warnings if the media filter is disabled for the WYSIWYG's text format.
+  $form['buttons']['drupal']['media']['#element_validate'][] = 'media_wysiwyg_wysiwyg_button_element_validate';
+  $form['buttons']['drupal']['media']['#after_build'][] = 'media_wysiwyg_wysiwyg_button_element_validate';
+  form_load_include($form_state, 'inc', 'media_wysiwyg', 'wysiwyg_plugins/media');
+}
+
+/**
+ * Element validate callback for the media WYSIWYG button.
+ */
+function media_wysiwyg_wysiwyg_button_element_validate($element, &$form_state) {
+  if (!empty($element['#value'])) {
+    $format = filter_format_load($form_state['build_info']['args'][0]->format);
+    $filters = filter_list_format($format->format);
+    if (empty($filters['media_filter']->status)) {
+      form_error($element, t('The <em>Convert Media tags to markup</em> filter must be enabled for the <a href="@format-link">@format format</a> in order to use the Media browser WYSIWYG button.', array(
+        '@format-link' => url('admin/config/content/formats/' . $format->format, array('query' => array('destination' => $_GET['q']))),
+        '@format' => $format->name,
+      )));
+    }
+  }
+
+  return $element;
+}
+
+/**
+ * Implements hook_form_FORM_ID_alter().
+ */
+function media_wysiwyg_form_media_admin_config_browser_alter(&$form, &$form_state) {
+  $form['wysiwyg'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('WYSIWYG configuration'),
+    '#collapsible' => TRUE,
+    '#collapsed' => FALSE,
+  );
+  $form['wysiwyg']['media_wysiwyg_wysiwyg_browser_plugins'] = array(
+    '#type' => 'checkboxes',
+    '#title' => t('Enabled browser plugins'),
+    '#options' => array(),
+    '#required' => FALSE,
+    '#default_value' => variable_get('media_wysiwyg_wysiwyg_browser_plugins', array()),
+    '#description' => t('If no plugins are selected, they will all be available.'),
+  );
+
+  $plugins = media_get_browser_plugin_info();
+
+  foreach ($plugins as $key => $plugin) {
+    $form['wysiwyg']['media_wysiwyg_wysiwyg_browser_plugins']['#options'][$key] = !empty($plugin['title']) ? $plugin['title'] : $key;
+  }
+
+  $form['wysiwyg']['media_wysiwyg_wysiwyg_upload_directory'] = array(
+    '#type' => 'textfield',
+    '#title' => t("File directory for uploaded media"),
+    '#default_value' => variable_get('media_wysiwyg_wysiwyg_upload_directory', ''),
+    '#description' => t('Optional subdirectory within the upload destination where files will be stored. Do not include preceding or trailing slashes.'),
+  );
+
+  if (module_exists('token')) {
+    $form['wysiwyg']['media_wysiwyg_wysiwyg_upload_directory']['#description'] .= t('This field supports tokens.');
+    $form['wysiwyg']['tokens'] = array(
+      '#theme' => 'token_tree',
+      '#dialog' => TRUE,
+    );
+  }
+
+  $form['wysiwyg']['media_wysiwyg_wysiwyg_allowed_types'] = array(
+    '#type' => 'checkboxes',
+    '#title' => t('Allowed types in WYSIWYG'),
+    '#options' => file_entity_type_get_names(),
+    '#default_value' => variable_get('media_wysiwyg_wysiwyg_allowed_types', array('audio', 'image', 'video', 'document')),
+  );
+
+  $form['#submit'][] = 'media_wysiwyg_admin_config_browser_pre_submit';
+}
+
+/**
+ * Manipulate values before form is submitted.
+ */
+function media_wysiwyg_admin_config_browser_pre_submit(&$form, &$form_state) {
+  $wysiwyg_browser_plugins = array_unique(array_values($form_state['values']['media_wysiwyg_wysiwyg_browser_plugins']));
+  if (empty($wysiwyg_browser_plugins[0])) {
+    variable_del('media_wysiwyg_wysiwyg_browser_plugins');
+    unset($form_state['values']['media_wysiwyg_wysiwyg_browser_plugins']);
+  }
+}
+
+/**
+ * Implements hook_filter_info().
+ */
+function media_wysiwyg_filter_info() {
+  $filters['media_filter'] = array(
+    'title' => t('Convert Media tags to markup'),
+    'description' => t('This filter will convert [[{type:media... ]] tags into markup. This must be enabled for the Media WYSIWYG integration to work with this input format.'),
+    'process callback' => 'media_wysiwyg_filter',
+    'weight' => 2,
+    // @TODO not implemented
+    'tips callback' => 'media_filter_tips',
+  );
+
+  return $filters;
+}
+
+/**
+ * Prepares the page to be able to launch the media browser.
+ *
+ * Defines default variables.
+ */
+function media_wysiwyg_include_browser_js() {
+  static $included;
+  if ($included) {
+    return;
+  }
+  $included = TRUE;
+  module_load_include('inc', 'media', 'includes/media.browser');
+  $javascript = media_browser_js();
+  foreach ($javascript as $key => $definitions) {
+    foreach ($definitions as $definition) {
+      $function = 'drupal_add_' . $key;
+      // Since the arguments to pass are variable, use call_user_func_array().
+      // This will not handle all potential drupal_add_*() functions directly
+      // but covers the js and library needed here, which are unlikely to be
+      // expanded since this function is only a workaround for a wysiwyg
+      // limitation.
+      call_user_func_array($function, $definition);
+    }
+  }
+  // Add wysiwyg-specific settings.
+  $settings = array('wysiwyg_allowed_attributes' => variable_get('media_wysiwyg_wysiwyg_allowed_attributes', _media_wysiwyg_wysiwyg_allowed_attributes_default()));
+  drupal_add_js(array('media' => $settings), 'setting');
+}
+
+/**
+ * Implements hook_wysiwyg_include_directory().
+ */
+function media_wysiwyg_wysiwyg_include_directory($type) {
+  switch ($type) {
+    case 'plugins':
+      return 'wysiwyg_plugins';
+
+      break;
+  }
+}
+
+/**
+ * Returns the default set of allowed attributes for use with WYSIWYG.
+ *
+ * @return array
+ *   An array of whitelisted attributes.
+ */
+function _media_wysiwyg_wysiwyg_allowed_attributes_default() {
+  return array(
+    'alt',
+    'title',
+    'height',
+    'width',
+    'hspace',
+    'vspace',
+    'border',
+    'align',
+    'style',
+    'class',
+    'id',
+    'usemap',
+    'data-picture-group',
+    'data-picture-align',
+    'data-picture-mapping',
+  );
+}
+
+/**
+ * Returns a drupal_render() array for just the file portion of a file entity.
+ *
+ * Optional custom settings can override how the file is displayed.
+ */
+function media_wysiwyg_get_file_without_label($file, $view_mode, $settings = array()) {
+  $file->override = $settings;
+
+  $element = file_view_file($file, $view_mode);
+
+  // The formatter invoked by file_view_file() can use $file->override to
+  // customize the returned render array to match the requested settings. To
+  // support simple formatters that don't do this, set the element attributes to
+  // what was requested, but not if the formatter applied its own logic for
+  // element attributes.
+  if (isset($settings['attributes'])) {
+    if (empty($element['#attributes'])) {
+      $element['#attributes'] = $settings['attributes'];
+    }
+
+    // While this function may be called for any file type, images are a common
+    // use-case, and image theme functions have their own structure for render
+    // arrays.
+    if (isset($element['#theme'])) {
+      // theme_image() and theme_image_style() require the 'alt' attributes to
+      // be passed separately from the 'attributes' array. (see
+      // http://drupal.org/node/999338). Until that's fixed, implement this
+      // special-case logic. Image formatters using other theme functions are
+      // responsible for their own 'alt' attribute handling. See
+      // theme_media_formatter_large_icon() for an example.
+      if (in_array($element['#theme'], array('image', 'image_style'))) {
+        if (empty($element['#alt']) && isset($settings['attributes']['alt'])) {
+          $element['#alt'] = $settings['attributes']['alt'];
+        }
+      }
+      // theme_image_formatter() and any potential replacements, such as
+      // theme_colorbox_image_formatter(), also require attribute handling.
+      elseif (strpos($element['#theme'], 'image_formatter') !== FALSE) {
+        // theme_image_formatter() requires the attributes to be
+        // set on the item rather than the element itself.
+        if (empty($element['#item']['attributes'])) {
+          $element['#item']['attributes'] = $settings['attributes'];
+        }
+
+        // theme_image_formatter() also requires alt, title, height, and
+        // width attributes to be set on the item rather than within its
+        // attributes array.
+        foreach (array('alt', 'title', 'width', 'height') as $attr) {
+          if (isset($settings['attributes'][$attr])) {
+            $element['#item'][$attr] = $settings['attributes'][$attr];
+          }
+        }
+      }
+    }
+  }
+
+  return $element;
+}
+
+/**
+ * Returns an array containing the names of all fields that perform text filtering.
+ */
+function media_wysiwyg_filter_fields_with_text_filtering($entity_type, $entity) {
+  list($entity_id, $revision_id, $bundle) = entity_extract_ids($entity_type, $entity);
+  $fields = field_info_instances($entity_type, $bundle);
+
+  // Get all of the fields on this entity that allow text filtering.
+  $fields_with_text_filtering = array();
+  foreach ($fields as $field_name => $field) {
+    if (!empty($field['settings']['text_processing'])) {
+      $fields_with_text_filtering[] = $field_name;
+    }
+  }
+
+  return $fields_with_text_filtering;
+}
diff --git a/drupal7/sites/all/modules/media/modules/media_wysiwyg/media_wysiwyg.test b/drupal7/sites/all/modules/media/modules/media_wysiwyg/media_wysiwyg.test
new file mode 100644
index 00000000..cdb672a1
--- /dev/null
+++ b/drupal7/sites/all/modules/media/modules/media_wysiwyg/media_wysiwyg.test
@@ -0,0 +1,101 @@
+<?php
+
+/**
+ * @file
+ * Tests for media.module.
+ */
+
+/**
+ * Defines base class for media test cases.
+ */
+class MediaWYSIWYGTestHelper extends DrupalWebTestCase {
+
+  /**
+   * Enable media and file entity modules for testing.
+   */
+  public function setUp() {
+    $modules = func_get_args();
+    if (isset($modules[0]) && is_array($modules[0])) {
+      $modules = $modules[0];
+    }
+    $modules[] = 'media_wysiwyg';
+    parent::setUp($modules);
+  }
+
+  /**
+    * Generates markup to be inserted for a file.
+    *
+    * This is a PHP version of InsertMedia.insert() from js/wysiwyg-media.js.
+    *
+    * @param int $fid
+    *   Drupal file id
+    * @param int $count
+    *   Quantity of markup to insert
+    * @param array $attributes
+    *   Extra attributes to insert.
+    * @param array $fields
+    *   Extra field values to insert.
+    *
+    * @return string
+    *   Filter markup.
+    */
+  protected function generateJsonTokenMarkup($fid, $count = 1, array $attributes = array(), array $fields = array()) {
+    $markup = '';
+    // Merge default atttributes.
+    $attributes += array(
+      'height' => 100,
+      'width' => 100,
+      'classes' => 'media-element file_preview',
+    );
+
+    // Build the data that is used in a media tag.
+    $data = array(
+      'fid' => $fid,
+      'type' => 'media',
+      'view_mode' => 'preview',
+      'attributes' => $attributes,
+      'fields' => $fields,
+    );
+
+    // Create the file usage markup.
+    for ($i = 1; $i <= $count; $i++) {
+      $markup .= '<p>[[' . drupal_json_encode($data) . ']]</p>';
+    }
+
+    return $markup;
+  }
+
+  /**
+   * Utility function to create a test node.
+   *
+   * @param int $fid
+   *   Create the node with media markup in the body field
+    * @param array $attributes
+    *   Extra attributes to insert to the file.
+    * @param array $fields
+    *   Extra field values to insert.
+   *
+   * @return int
+   *   Returns the node id
+   */
+  protected function createNode($fid = FALSE, array $attributes = array(), array $fields = array()) {
+    $markup = '';
+    if (! empty($fid)) {
+      $markup = $this->generateJsonTokenMarkup($fid, 1, $attributes, $fields);
+    }
+
+    // Create an article node with file markup in the body field.
+    $edit = array(
+      'title' => $this->randomName(8),
+      'body[und][0][value]' => $markup,
+    );
+    // Save the article node. First argument is the URL, then the value array
+    // and the third is the label the button that should be "clicked".
+    $this->drupalPost('node/add/article', $edit, t('Save'));
+
+    // Get the article node that was saved by the unique title.
+    $node = $this->drupalGetNodeByTitle($edit['title']);
+    return $node->nid;
+  }
+
+}
diff --git a/drupal7/sites/all/modules/media/modules/media_wysiwyg/media_wysiwyg.variable.inc b/drupal7/sites/all/modules/media/modules/media_wysiwyg/media_wysiwyg.variable.inc
new file mode 100644
index 00000000..206905a0
--- /dev/null
+++ b/drupal7/sites/all/modules/media/modules/media_wysiwyg/media_wysiwyg.variable.inc
@@ -0,0 +1,42 @@
+<?php
+
+/**
+ * @file
+ * Declare Media WYSIWYG variables.
+ */
+
+/**
+ * Implements hook_variable_group_info().
+ */
+function media_wysiwyg_variable_group_info() {
+  $groups['media_wysiwyg'] = array(
+    'title' => t('Media WYSIWYG'),
+    'description' => t('Settings for Media WYSIWYG integration.'),
+    'access' => 'administer media browser',
+    'path' => 'admin/config/media/browser',
+  );
+
+  return $groups;
+}
+
+/**
+* Implements hook_variable_info().
+*/
+function media_wysiwyg_variable_info($options) {
+  $variables['media_wysiwyg_wysiwyg_title'] = array(
+    'type' => 'string',
+    'title' => t('WYSIWYG Title', array(), $options),
+    'default' => t('Media browser', array(), $options),
+    'description' => t('The WYSIWYG media plugin title.', array(), $options),
+    'group' => 'media_wysiwyg',
+  );
+  $variables['media_wysiwyg_wysiwyg_icon_title'] = array(
+    'type' => 'string',
+    'title' => t('WYSIWYG Icon Title', array(), $options),
+    'default' => t('Add media', array(), $options),
+    'description' => t('The WYSIWYG media button title to display on hover.', array(), $options),
+    'group' => 'media_wysiwyg',
+  );
+
+  return $variables;
+}
diff --git a/drupal7/sites/all/modules/media/tests/media.file.usage.test b/drupal7/sites/all/modules/media/modules/media_wysiwyg/tests/media_wysiwyg.file_usage.test
similarity index 79%
rename from drupal7/sites/all/modules/media/tests/media.file.usage.test
rename to drupal7/sites/all/modules/media/modules/media_wysiwyg/tests/media_wysiwyg.file_usage.test
index db5c614e..bd82ecfa 100644
--- a/drupal7/sites/all/modules/media/tests/media.file.usage.test
+++ b/drupal7/sites/all/modules/media/modules/media_wysiwyg/tests/media_wysiwyg.file_usage.test
@@ -5,7 +5,7 @@
  * Tests for the file usage in entity fields with the Media filter markup.
  */
 
-class MediaFileUsageTest extends MediaTestHelper {
+class MediaWYSIWYGFileUsageTest extends MediaWYSIWYGTestHelper {
 
   /**
    * Provide test information.
@@ -14,7 +14,7 @@ class MediaFileUsageTest extends MediaTestHelper {
     return array(
       'name' => t('File usage tracking'),
       'description' => t('Tests tracking of usage for files in text fields.'),
-      'group' => t('Media'),
+      'group' => t('Media WYSIWYG'),
     );
   }
 
@@ -22,79 +22,13 @@ class MediaFileUsageTest extends MediaTestHelper {
    * Enable media and file entity modules for testing.
    */
   public function setUp() {
-    parent::setUp(array('media', 'file_entity'));
+    parent::setUp();
 
     // Create and log in a user.
     $account = $this->drupalCreateUser(array('administer nodes', 'create article content'));
     $this->drupalLogin($account);
   }
 
-  /**
-    * Generates markup to be inserted for a file.
-    *
-    * This is a PHP version of InsertMedia.insert() from js/wysiwyg-media.js.
-    *
-    * @param int $fid
-    *   Drupal file id
-    * @param int $count
-    *   Quantity of markup to insert
-    *
-    * @return string
-    *   Filter markup.
-    */
-  private function generateFileMarkup($fid, $count = 1) {
-    $file_usage_markup = '';
-
-    // Build the data that is used in a media tag.
-    $data = array(
-      'fid' => $fid,
-      'type' => 'media',
-      'view_mode' => 'preview',
-      'attributes' => array(
-        'height' => 100,
-        'width' => 100,
-        'classes' => 'media-element file_preview',
-      )
-    );
-
-    // Create the file usage markup.
-    for ($i = 1; $i <= $count; $i++) {
-      $file_usage_markup .= '<p>[[' . drupal_json_encode($data) . ']]</p>';
-    }
-
-    return $file_usage_markup;
-  }
-
-
-  /**
-   * Utility function to create a test node.
-   *
-   * @param int $fid
-   *   Create the node with media markup in the body field
-   *
-   * @return int
-   *   Returns the node id
-   */
-  private function createNode($fid = FALSE) {
-    $markup = '';
-    if (! empty($fid)) {
-      $markup = $this->generateFileMarkup($fid);
-    }
-
-    // Create an article node with file markup in the body field.
-    $edit = array(
-      'title' => $this->randomName(8),
-      'body[und][0][value]' => $markup,
-    );
-    // Save the article node. First argument is the URL, then the value array
-    // and the third is the label the button that should be "clicked".
-    $this->drupalPost('node/add/article', $edit, t('Save'));
-
-    // Get the article node that was saved by the unique title.
-    $node = $this->drupalGetNodeByTitle($edit['title']);
-    return $node->nid;
-  }
-
   /**
    * Tests the tracking of file usages for files submitted via the WYSIWYG editor.
    */
@@ -133,7 +67,7 @@ class MediaFileUsageTest extends MediaTestHelper {
     // Create a new revision that has two instances of the file. File usage will
     // be 4.
     $node = node_load($nid);
-    $node->body[LANGUAGE_NONE][0]['value'] = $this->generateFileMarkup($fid, 2);
+    $node->body[LANGUAGE_NONE][0]['value'] = $this->generateJsonTokenMarkup($fid, 2);
     $node->revision = TRUE;
     node_save($node);
 
@@ -163,7 +97,7 @@ class MediaFileUsageTest extends MediaTestHelper {
 
     // Create a new revision that has the file on it. File usage will be 5.
     $node = node_load($nid);
-    $node->body[LANGUAGE_NONE][0]['value'] = $this->generateFileMarkup($fid, 1);
+    $node->body[LANGUAGE_NONE][0]['value'] = $this->generateJsonTokenMarkup($fid, 1);
     $node->revision = TRUE;
     node_save($node);
 
@@ -194,7 +128,7 @@ class MediaFileUsageTest extends MediaTestHelper {
 
     // Create a new revision with the file on it twice. File usage will be 4.
     $node = node_load($nid);
-    $node->body[LANGUAGE_NONE][0]['value'] = $this->generateFileMarkup($fid, 2);
+    $node->body[LANGUAGE_NONE][0]['value'] = $this->generateJsonTokenMarkup($fid, 2);
     $node->revision = TRUE;
     node_save($node);
 
@@ -206,7 +140,7 @@ class MediaFileUsageTest extends MediaTestHelper {
     // Re-save current revision with file on it once instead of twice. File
     // usage will be 3.
     $node = node_load($nid);
-    $node->body[LANGUAGE_NONE][0]['value'] = $this->generateFileMarkup($fid, 1);
+    $node->body[LANGUAGE_NONE][0]['value'] = $this->generateJsonTokenMarkup($fid, 1);
     $saved_vid = $node->vid;
     node_save($node);
 
@@ -227,7 +161,6 @@ class MediaFileUsageTest extends MediaTestHelper {
     $this->assertEqual(empty($file_uses), TRUE, t('Deleting the node removes all file uses.'));
   }
 
-
   /**
    * Tests the behavior of node and file deletion.
    */
@@ -301,5 +234,4 @@ class MediaFileUsageTest extends MediaTestHelper {
     $type = node_type_load($node->type);
     $this->assertRaw(t('@type %title has been updated.', array('@type' => $type->name, '%title' => $node->title)), t('Node without reference to deleted file saved successfully.'));
   }
-
 }
diff --git a/drupal7/sites/all/modules/media/modules/media_wysiwyg/tests/media_wysiwyg.macro.test b/drupal7/sites/all/modules/media/modules/media_wysiwyg/tests/media_wysiwyg.macro.test
new file mode 100644
index 00000000..7ac1bc4c
--- /dev/null
+++ b/drupal7/sites/all/modules/media/modules/media_wysiwyg/tests/media_wysiwyg.macro.test
@@ -0,0 +1,95 @@
+<?php
+
+/**
+ * @file
+ * Tests for ensuring media macros render properly.
+ */
+
+/**
+ * Defines media macro test cases.
+ */
+class MediaWYSIWYGWYSIWYGOverridesTest extends MediaWYSIWYGTestHelper {
+
+  /**
+   * Provide test information.
+   */
+  public static function getInfo() {
+    return array(
+      'name' => t('Media WYSIWYG WYSIWYG overrides'),
+      'description' => t('Tests that overridden attributes display correct.'),
+      'group' => t('Media WYSIWYG'),
+      'dependencies' => array('token'),
+    );
+  }
+
+  public function setUp() {
+    parent::setUp('token');
+
+    // Create and log in a user.
+    $account = $this->drupalCreateUser(array('create article content', 'administer filters', 'use text format filtered_html'));
+    $this->drupalLogin($account);
+
+    // Enable the media filter for full html.
+    $edit = array(
+      'filters[media_filter][status]' => TRUE,
+      'filters[filter_html][status]' => FALSE,
+    );
+    $this->drupalPost('admin/config/content/formats/filtered_html', $edit, t('Save configuration'));
+  }
+
+  /**
+   * Test image media overrides.
+   */
+  public function testAttributeOverrides() {
+    $files = $this->drupalGetTestFiles('image');
+    $file = file_save($files[0]);
+
+    // Create a node to test with.
+    $nid = $this->createNode($file->fid);
+
+    $this->drupalGet('node/' . $nid);
+    $this->assertRaw('width="100"', t('Image displays with default width attribute.'));
+    $this->assertRaw('height="100"', t('Image displays with default height attribute.'));
+
+    // Create a node with a style attribute.
+    $attributes = array(
+      'style' => 'float: left; width: 50px;',
+    );
+    $nid = $this->createNode($file->fid, $attributes);
+    $this->drupalGet('node/' . $nid);
+    $this->assertRaw(drupal_attributes($attributes), t('Image displays with overriden attributes.'));
+
+    // Create a node with overriden alt/title attributes.
+    $attributes = array(
+      'alt' => $this->randomName(),
+      'title' => $this->randomName(),
+    );
+    $nid = $this->createNode($file->fid, $attributes);
+    $this->drupalGet('node/' . $nid);
+    $this->assertRaw(drupal_attributes($attributes), t('Image displays with alt/title set as attributes.'));
+
+    // Create a node with overriden alt/title fields.
+    $fields = $attributes = array();
+    $attributes['alt'] = $fields['field_file_image_alt_text[und][0][value]'] = $this->randomName();
+    $attributes['title'] = $fields['field_file_image_title_text[und][0][value]'] = $this->randomName();
+
+    $nid = $this->createNode($file->fid, array(), $fields);
+    $this->drupalGet('node/' . $nid);
+    // Ensure that the alt/title from attributes display.
+    $this->assertRaw(drupal_attributes($attributes), t('Image displays with alt/title set as fields.'));
+
+    // Create a node with overriden alt/title fields as well as attributes.
+    $attributes = array(
+      'alt' => $this->randomName(),
+      'title' => $this->randomName(),
+    );
+    $fields = array(
+      'field_file_image_alt_text[und][0][value]' => $this->randomName(),
+      'field_file_image_title_text[und][0][value]' => $this->randomName(),
+    );
+    $nid = $this->createNode($file->fid, $attributes, $fields);
+    $this->drupalGet('node/' . $nid);
+    // Ensure that the alt/title from attributes display rather the field ones.
+    $this->assertRaw(drupal_attributes($attributes), t('Image displays with alt/title set as attributes overriding field values.'));
+  }
+}
diff --git a/drupal7/sites/all/modules/media/modules/media_wysiwyg/wysiwyg_plugins/media.inc b/drupal7/sites/all/modules/media/modules/media_wysiwyg/wysiwyg_plugins/media.inc
new file mode 100644
index 00000000..a61c7134
--- /dev/null
+++ b/drupal7/sites/all/modules/media/modules/media_wysiwyg/wysiwyg_plugins/media.inc
@@ -0,0 +1,44 @@
+<?php
+
+/**
+ * @file
+ * Define the WYSIWYG browser plugin.
+ */
+
+/**
+ * Implements WYSIWYG's hook_INCLUDE_plugin().
+ */
+function media_wysiwyg_media_plugin() {
+  // Include the required browser JS.
+  // @todo: wyswiyg should allow libraries and multiple js files
+  // to be defined by this hook.
+  // @see http://drupal.org/node/1039076
+  media_wysiwyg_include_browser_js();
+
+  // Add the filter handling.
+  drupal_add_js(drupal_get_path('module', 'media_wysiwyg') . '/js/media_wysiwyg.filter.js');
+
+  // Plugin definition.
+  $plugins['media'] = array(
+    'title' => variable_get('media_wysiwyg_wysiwyg_title', t('Media browser')),
+    'vendor url' => 'http://drupal.org/project/media',
+    'icon path' => drupal_get_path('module', 'media_wysiwyg') . '/wysiwyg_plugins/media_ckeditor/images',
+    'icon file' => 'icon.gif',
+    'icon title' => variable_get('media_wysiwyg_wysiwyg_icon_title', t('Add media')),
+    // @todo: move this to the plugin directory for the wysiwyg plugin.
+    'js path' => drupal_get_path('module', 'media_wysiwyg') . '/js',
+    'js file' => 'wysiwyg-media.js',
+    'css path' => drupal_get_path('module', 'media_wysiwyg') . '/css',
+    'css file' => 'media_wysiwyg.css',
+    'settings' => array(
+      'global' => array(
+        'enabledPlugins' => variable_get('media_wysiwyg_wysiwyg_browser_plugins', array()),
+        'file_directory' => variable_get('media_wysiwyg_wysiwyg_upload_directory', ''),
+        'types' => variable_get('media_wysiwyg_wysiwyg_allowed_types', array('audio', 'image', 'video', 'document')),
+        'id' => 'media_wysiwyg',
+      ),
+    ),
+  );
+
+  return $plugins;
+}
diff --git a/drupal7/sites/all/modules/media/modules/media_wysiwyg/wysiwyg_plugins/media_ckeditor/images/icon.gif b/drupal7/sites/all/modules/media/modules/media_wysiwyg/wysiwyg_plugins/media_ckeditor/images/icon.gif
new file mode 100644
index 00000000..bf9b501c
Binary files /dev/null and b/drupal7/sites/all/modules/media/modules/media_wysiwyg/wysiwyg_plugins/media_ckeditor/images/icon.gif differ
diff --git a/drupal7/sites/all/modules/media/modules/media_wysiwyg/wysiwyg_plugins/media_ckeditor/lang/en.js b/drupal7/sites/all/modules/media/modules/media_wysiwyg/wysiwyg_plugins/media_ckeditor/lang/en.js
new file mode 100644
index 00000000..efc1d685
--- /dev/null
+++ b/drupal7/sites/all/modules/media/modules/media_wysiwyg/wysiwyg_plugins/media_ckeditor/lang/en.js
@@ -0,0 +1,14 @@
+﻿/*
+ Copyright (c) 2003-2013, CKSource - Frederico Knabben. All rights reserved.
+ For licensing, see LICENSE.md or http://ckeditor.com/license
+ */
+CKEDITOR.plugins.setLang( 'media', 'en', {
+  alt: 'Alternative Text',	// Inherit from image plugin.
+  captioned: 'Captioned image', // NEW property.
+  lockRatio: 'Lock Ratio',	// Inherit from image plugin.
+  menu: 'Image Properties',	// Inherit from image plugin.
+  resetSize: 'Reset Size', // Inherit from image plugin.
+  resizer: 'Click and drag to resize',	// NEW property.
+  title: 'Image Properties',	// Inherit from image plugin.
+  urlMissing: 'Image source URL is missing.' // Inherit from image plugin.
+} );
diff --git a/drupal7/sites/all/modules/media/modules/media_wysiwyg/wysiwyg_plugins/media_ckeditor/library.js b/drupal7/sites/all/modules/media/modules/media_wysiwyg/wysiwyg_plugins/media_ckeditor/library.js
new file mode 100644
index 00000000..a1f33374
--- /dev/null
+++ b/drupal7/sites/all/modules/media/modules/media_wysiwyg/wysiwyg_plugins/media_ckeditor/library.js
@@ -0,0 +1,183 @@
+
+/**
+ *  @file
+ *  Attach Media ckeditor behaviors.
+ */
+
+(function ($) {
+  Drupal.media = Drupal.media || {};
+
+  Drupal.settings.ckeditor.plugins['media'] = {
+    /**
+     * Execute the button.
+     */
+    invoke: function (data, settings, instanceId) {
+      if (data.format == 'html') {
+        if (jQuery(data.node).is('.media-element')) {
+          // Change the view mode for already-inserted media.
+          var mediaFile = Drupal.media.filter.extract_file_info(jQuery(data.node));
+          Drupal.media.popups.mediaStyleSelector(mediaFile, function (mediaFiles) {
+            Drupal.settings.ckeditor.plugins['media'].insertMediaFile(mediaFile, mediaFiles, CKEDITOR.instances[instanceId]);
+          }, settings['global']);
+        }
+        else {
+          Drupal.media.popups.mediaBrowser(function (mediaFiles) {
+            Drupal.settings.ckeditor.plugins['media'].mediaBrowserOnSelect(mediaFiles, instanceId);
+          }, settings['global']);
+        }
+      }
+    },
+
+    /**
+     * Respond to the mediaBrowser's onSelect event.
+     */
+    mediaBrowserOnSelect: function (mediaFiles, instanceId) {
+      var mediaFile = mediaFiles[0];
+      var options = {};
+      Drupal.media.popups.mediaStyleSelector(mediaFile, function (formattedMedia) {
+        Drupal.settings.ckeditor.plugins['media'].insertMediaFile(mediaFile, formattedMedia, CKEDITOR.instances[instanceId]);
+      }, options);
+
+      return;
+    },
+
+    insertMediaFile: function (mediaFile, formattedMedia, ckeditorInstance) {
+      // Customization of Drupal.media.filter.registerNewElement().
+      var element = Drupal.media.filter.create_element(formattedMedia.html, {
+        fid: mediaFile.fid,
+        view_mode: formattedMedia.type,
+        attributes: formattedMedia.options
+      });
+
+      // Use own wrapper element to be able to properly deal with selections.
+      // Check prepareDataForWysiwygMode() in plugin.js for details.
+      var wysiwygHTML = Drupal.media.filter.getWysiwygHTML(element);
+
+      // Insert element. Use CKEDITOR.dom.element.createFromHtml to ensure our
+      // custom wrapper element is preserved.
+      if (wysiwygHTML.indexOf("<!--MEDIA-WRAPPER-START-") !== -1) {
+        ckeditorInstance.plugins.media.mediaLegacyWrappers = true;
+        wysiwygHTML = wysiwygHTML.replace(/<!--MEDIA-WRAPPER-START-(\d+)-->(.*?)<!--MEDIA-WRAPPER-END-\d+-->/gi, '');
+      } else {
+        wysiwygHTML = '<mediawrapper data="">' + wysiwygHTML + '</mediawrapper>';
+      }
+
+      var editorElement = CKEDITOR.dom.element.createFromHtml(wysiwygHTML);
+      ckeditorInstance.insertElement(editorElement);
+
+      // Initialize widget on our html if possible.
+      if (parseFloat(CKEDITOR.version) >= 4.3 && typeof(CKEDITOR.plugins.registered.widget) != 'undefined') {
+        ckeditorInstance.widgets.initOn( editorElement, 'mediabox' );
+      }
+    },
+
+    /**
+     * Forces custom attributes into the class field of the specified image.
+     *
+     * Due to a bug in some versions of Firefox
+     * (http://forums.mozillazine.org/viewtopic.php?f=9&t=1991855), the
+     * custom attributes used to share information about the image are
+     * being stripped as the image markup is set into the rich text
+     * editor.  Here we encode these attributes into the class field so
+     * the data survives.
+     *
+     * @param imgElement
+     *   The image
+     * @fid
+     *   The file id.
+     * @param view_mode
+     *   The view mode.
+     * @param additional
+     *   Additional attributes to add to the image.
+     */
+    forceAttributesIntoClass: function (imgElement, fid, view_mode, additional) {
+      var wysiwyg = imgElement.attr('wysiwyg');
+      if (wysiwyg) {
+        imgElement.addClass('attr__wysiwyg__' + wysiwyg);
+      }
+      var format = imgElement.attr('format');
+      if (format) {
+        imgElement.addClass('attr__format__' + format);
+      }
+      var typeOf = imgElement.attr('typeof');
+      if (typeOf) {
+        imgElement.addClass('attr__typeof__' + typeOf);
+      }
+      if (fid) {
+        imgElement.addClass('img__fid__' + fid);
+      }
+      if (view_mode) {
+        imgElement.addClass('img__view_mode__' + view_mode);
+      }
+      if (additional) {
+        for (var name in additional) {
+          if (additional.hasOwnProperty(name)) {
+            switch (name) {
+              case 'field_file_image_alt_text[und][0][value]':
+                imgElement.attr('alt', additional[name]);
+                break;
+              case 'field_file_image_title_text[und][0][value]':
+                imgElement.attr('title', additional[name]);
+                break;
+              default:
+                imgElement.addClass('attr__' + name + '__' + additional[name]);
+                break;
+            }
+          }
+        }
+      }
+    },
+
+    /**
+     * Retrieves encoded attributes from the specified class string.
+     *
+     * @param classString
+     *   A string containing the value of the class attribute.
+     * @return
+     *   An array containing the attribute names as keys, and an object
+     *   with the name, value, and attribute type (either 'attr' or
+     *   'img', depending on whether it is an image attribute or should
+     *   be it the attributes section)
+     */
+    getAttributesFromClass: function (classString) {
+      var actualClasses = [];
+      var otherAttributes = [];
+      var classes = classString.split(' ');
+      var regexp = new RegExp('^(attr|img)__([^\S]*)__([^\S]*)$');
+      for (var index = 0; index < classes.length; index++) {
+        var matches = classes[index].match(regexp);
+        if (matches && matches.length === 4) {
+          otherAttributes[matches[2]] = {
+            name: matches[2],
+            value: matches[3],
+            type: matches[1]
+          };
+        }
+        else {
+          actualClasses.push(classes[index]);
+        }
+      }
+      if (actualClasses.length > 0) {
+        otherAttributes['class'] = {
+          name: 'class',
+          value: actualClasses.join(' '),
+          type: 'attr'
+        };
+      }
+      return otherAttributes;
+    },
+
+    sortAttributes: function (a, b) {
+      var nameA = a.name.toLowerCase();
+      var nameB = b.name.toLowerCase();
+      if (nameA < nameB) {
+        return -1;
+      }
+      if (nameA > nameB) {
+        return 1;
+      }
+      return 0;
+    }
+  };
+
+})(jQuery);
diff --git a/drupal7/sites/all/modules/media/modules/media_wysiwyg/wysiwyg_plugins/media_ckeditor/plugin.js b/drupal7/sites/all/modules/media/modules/media_wysiwyg/wysiwyg_plugins/media_ckeditor/plugin.js
new file mode 100644
index 00000000..37fd3b9d
--- /dev/null
+++ b/drupal7/sites/all/modules/media/modules/media_wysiwyg/wysiwyg_plugins/media_ckeditor/plugin.js
@@ -0,0 +1,217 @@
+/*
+Copyright (c) 2003-2013, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+
+/**
+ * @file Plugin for inserting images from Drupal media module
+ *
+ * @TODO Remove all the legecy media wrapper once it's sure nobody uses that
+ * anymore.
+ */
+( function() {
+  var mediaPluginDefinition = {
+    icons: 'media',
+    requires: ['button'],
+    // Check if this instance has widget support. All the default distributions
+    // of the editor have the widget plugin disabled by default.
+    hasWidgetSupport: typeof(CKEDITOR.plugins.registered.widget) != 'undefined',
+    mediaLegacyWrappers: false,
+
+    // Wrap Drupal plugin in a proxy plugin.
+    init: function(editor){
+      editor.addCommand( 'media',
+      {
+        exec: function (editor) {
+          var data = {
+            format: 'html',
+            node: null,
+            content: ''
+          };
+          var selection = editor.getSelection();
+
+          if (selection) {
+            data.node = selection.getSelectedElement();
+            if (data.node) {
+              data.node = data.node.$;
+            }
+            if (selection.getType() == CKEDITOR.SELECTION_TEXT) {
+              if (CKEDITOR.env.ie && CKEDITOR.env.version < 10) {
+                data.content = selection.getNative().createRange().text;
+              }
+              else {
+                data.content = selection.getNative().toString();
+              }
+            }
+            else if (data.node) {
+              // content is supposed to contain the "outerHTML".
+              data.content = data.node.parentNode.innerHTML;
+            }
+          }
+          Drupal.settings.ckeditor.plugins['media'].invoke(data, Drupal.settings.ckeditor.plugins['media'], editor.name);
+        }
+      });
+
+      editor.ui.addButton( 'Media',
+      {
+        label: 'Add media',
+        command: 'media',
+        icon: this.path + 'images/icon.gif'
+      });
+
+      var ckeditorversion = parseFloat(CKEDITOR.version);
+
+      // Because the media comment wrapper don't work well for CKEditor we
+      // replace them by using a custom mediawrapper element.
+      // Instead having
+      // <!--MEDIA-WRAPPER-START-1--><img /><!--MEDIA-WRAPPER-END-1-->
+      // We wrap the placeholder with
+      // <mediawrapper data="1"><img /></mediawrapper>
+      // That way we can deal better with selections - see selectionChange.
+      CKEDITOR.dtd['mediawrapper'] = CKEDITOR.dtd;
+      CKEDITOR.dtd.$blockLimit['mediawrapper'] = 1;
+      CKEDITOR.dtd.$inline['mediawrapper'] = 1;
+      CKEDITOR.dtd.$nonEditable['mediawrapper'] = 1;
+      if (ckeditorversion >= 4.1) {
+        // Register allowed tag for advanced filtering.
+        editor.filter.allow( 'mediawrapper[!data]', 'mediawrapper', true);
+        // Don't remove the data-file_info attribute added by media!
+        editor.filter.allow( '*[!data-file_info]', 'mediawrapper', true);
+        // Ensure image tags accept all kinds of attributes.
+        editor.filter.allow( 'img[*]{*}(*)', 'mediawrapper', true);
+        // Objects should be selected as a whole in the editor.
+        CKEDITOR.dtd.$object['mediawrapper'] = 1;
+      }
+      function prepareDataForWysiwygMode(data) {
+        data = Drupal.media.filter.replaceTokenWithPlaceholder(data);
+        // Legacy media wrapper.
+        mediaPluginDefinition.mediaLegacyWrappers = (data.indexOf("<!--MEDIA-WRAPPER-START-") !== -1);
+        data = data.replace(/<!--MEDIA-WRAPPER-START-(\d+)-->(.*?)<!--MEDIA-WRAPPER-END-\d+-->/gi, '<mediawrapper data="$1">$2</mediawrapper>');
+        return data;
+      }
+      function prepareDataForSourceMode(data) {
+        var replacement = '$2';
+        // Legacy wrapper
+        if (mediaPluginDefinition.mediaLegacyWrappers) {
+          replacement = '<!--MEDIA-WRAPPER-START-$1-->$2<!--MEDIA-WRAPPER-END-$1-->';
+        }
+        data = data.replace(/<mediawrapper data="(.*)">(.*?)<\/mediawrapper>/gi, replacement);
+        data = Drupal.media.filter.replacePlaceholderWithToken(data);
+        return data;
+      }
+
+      // Ensure the tokens are replaced by placeholders while editing.
+      // Check for widget support.
+      if (mediaPluginDefinition.hasWidgetSupport) {
+        editor.widgets.add( 'mediabox',
+        {
+          button: 'Create a mediabox',
+          template: '<mediawrapper></mediawrapper>',
+          editables: {},
+          allowedContent: '*',
+          upcast: function( element ) {
+            if (element.name != 'mediawrapper') {
+              // Ensure media tokens are converted to media placeholdes.
+              element.setHtml(prepareDataForWysiwygMode(element.getHtml()));
+            }
+            return element.name == 'mediawrapper';
+          },
+
+          downcast: function( widgetElement ) {
+            var token = prepareDataForSourceMode(widgetElement.getOuterHtml());
+            return new CKEDITOR.htmlParser.text(token);
+            return element.name == 'mediawrapper';
+          }
+        });
+      }
+      else if (ckeditorversion >= 4) {
+        // CKEditor >=4.0
+        editor.on('setData', function( event ) {
+          event.data.dataValue = prepareDataForWysiwygMode(event.data.dataValue);
+        });
+      }
+      else {
+        // CKEditor >=3.6 behaviour.
+        editor.on( 'beforeSetMode', function( event, data ) {
+          event.removeListener();
+          var wysiwyg = editor._.modes[ 'wysiwyg' ];
+          var source = editor._.modes[ 'source' ];
+          wysiwyg.loadData = CKEDITOR.tools.override( wysiwyg.loadData, function( org )
+          {
+            return function( data ) {
+              return ( org.call( this, prepareDataForWysiwygMode(data)) );
+            };
+          } );
+          source.loadData = CKEDITOR.tools.override( source.loadData, function( org )
+          {
+            return function( data ) {
+              return ( org.call( this, prepareDataForSourceMode(data) ) );
+            };
+          } );
+        });
+      }
+
+      // Provide alternative to the widget functionality introduced in 4.3.
+      if (!mediaPluginDefinition.hasWidgetSupport) {
+        // Ensure tokens instead the html element is saved.
+        editor.on('getData', function( event ) {
+          event.data.dataValue = prepareDataForSourceMode(event.data.dataValue);
+        });
+
+        // Ensure our enclosing wrappers are always included in the selection.
+        editor.on('selectionChange', function( event ) {
+          var ranges = editor.getSelection().getRanges().createIterator();
+          var newRanges = [];
+          var currRange;
+          while(currRange = ranges.getNextRange()) {
+            var commonAncestor = currRange.getCommonAncestor(false);
+            if (commonAncestor && typeof(commonAncestor.getName) != 'undefined' && commonAncestor.getName() == 'mediawrapper') {
+              var range = new CKEDITOR.dom.range( editor.document );
+              if (currRange.collapsed === true) {
+                // Don't allow selection within the wrapper element.
+                if (currRange.startOffset == 0) {
+                  // While v3 plays nice with setting start and end to avoid
+                  // editing within the media wrapper element, v4 ignores that.
+                  // Thus we try to move the cursor further away.
+                  if (parseInt(CKEDITOR.version) > 3) {
+                    range.setStart(commonAncestor.getPrevious());
+                    range.setEnd(commonAncestor.getPrevious());
+                  }
+                  else {
+                    range.setStartBefore(commonAncestor);
+                  }
+                }
+                else {
+                  // While v3 plays nice with setting start and end to avoid
+                  // editing within the media wrapper element, v4 ignores that.
+                  // Thus we try to move the cursor further away.
+                  if (parseInt(CKEDITOR.version) > 3) {
+                    range.setStart(commonAncestor.getNext(), 1);
+                    range.setEnd(commonAncestor.getNext(), 1);
+                  }
+                  else {
+                    range.setStartAfter(commonAncestor);
+                  }
+                }
+              }
+              else {
+                // Always select the whole wrapper element.
+                range.setStartBefore(commonAncestor);
+                range.setEndAfter(commonAncestor);
+              }
+              newRanges.push(range);
+            }
+          }
+          if (newRanges.length) {
+            editor.getSelection().selectRanges(newRanges);
+          }
+        });
+      }
+    }
+  };
+  // Add dependency to widget plugin if possible.
+  if (parseFloat(CKEDITOR.version) >= 4.3 && mediaPluginDefinition.hasWidgetSupport) {
+    mediaPluginDefinition.requires.push('widget');
+  }
+  CKEDITOR.plugins.add( 'media', mediaPluginDefinition);
+} )();
diff --git a/drupal7/sites/all/modules/media/modules/media_wysiwyg_view_mode/media_wysiwyg_view_mode.info b/drupal7/sites/all/modules/media/modules/media_wysiwyg_view_mode/media_wysiwyg_view_mode.info
index e026c8f2..765a7a17 100644
--- a/drupal7/sites/all/modules/media/modules/media_wysiwyg_view_mode/media_wysiwyg_view_mode.info
+++ b/drupal7/sites/all/modules/media/modules/media_wysiwyg_view_mode/media_wysiwyg_view_mode.info
@@ -3,14 +3,15 @@ description = Enables files inside of the WYSIWYG editor to be displayed using a
 package = Media
 core = 7.x
 
-dependencies[] = media
-dependencies[] = wysiwyg
+dependencies[] = media_wysiwyg
 
 configure = admin/config/media/wysiwyg-view-mode
 
-; Information added by drupal.org packaging script on 2013-10-25
-version = "7.x-2.0-alpha3"
+files[] = media_wysiwyg_view_mode.test
+
+; Information added by Drupal.org packaging script on 2014-10-04
+version = "7.x-2.0-alpha4"
 core = "7.x"
 project = "media"
-datestamp = "1382744872"
+datestamp = "1412422430"
 
diff --git a/drupal7/sites/all/modules/media/modules/media_wysiwyg_view_mode/media_wysiwyg_view_mode.module b/drupal7/sites/all/modules/media/modules/media_wysiwyg_view_mode/media_wysiwyg_view_mode.module
index bd9231d0..d36bec71 100644
--- a/drupal7/sites/all/modules/media/modules/media_wysiwyg_view_mode/media_wysiwyg_view_mode.module
+++ b/drupal7/sites/all/modules/media/modules/media_wysiwyg_view_mode/media_wysiwyg_view_mode.module
@@ -58,9 +58,9 @@ function media_wysiwyg_view_mode_entity_info_alter(&$entity_info) {
 }
 
 /**
- * Implements hook_media_wysiwyg_allowed_view_modes_alter().
+ * Implements hook_media_wysiwyg_wysiwyg_allowed_view_modes_alter().
  */
-function media_wysiwyg_view_mode_media_wysiwyg_allowed_view_modes_alter(&$view_modes, &$file) {
+function media_wysiwyg_view_mode_media_wysiwyg_wysiwyg_allowed_view_modes_alter(&$view_modes, &$file) {
   if (variable_get("media_wysiwyg_view_mode_{$file->type}_wysiwyg_restricted_view_modes_status", FALSE) == TRUE) {
     $restricted_view_modes = variable_get("media_wysiwyg_view_mode_{$file->type}_wysiwyg_restricted_view_modes", array());
 
@@ -73,17 +73,17 @@ function media_wysiwyg_view_mode_media_wysiwyg_allowed_view_modes_alter(&$view_m
 }
 
 /**
- * Implements hook_media_token_to_markup_alter().
+ * Implements hook_media_wysiwyg_token_to_markup_alter().
  */
-function media_wysiwyg_view_mode_media_token_to_markup_alter(&$element, $tag_info, $settings) {
+function media_wysiwyg_view_mode_media_wysiwyg_token_to_markup_alter(&$element, $tag_info, $settings) {
   if (!empty($settings['wysiwyg'])) {
     $file = $tag_info['file'];
 
     if (variable_get("media_wysiwyg_view_mode_{$file->type}_file_wysiwyg_view_mode_status", FALSE) == TRUE) {
-      $element = media_get_file_without_label($file, variable_get("media_wysiwyg_view_mode_{$file->type}_file_wysiwyg_view_mode", 'wysiwyg'), $settings);
+      $element = media_wysiwyg_get_file_without_label($file, variable_get("media_wysiwyg_view_mode_{$file->type}_file_wysiwyg_view_mode", 'wysiwyg'), $settings);
     }
     else {
-      $element = media_get_file_without_label($file, $tag_info['view_mode'], $settings);
+      $element = media_wysiwyg_get_file_without_label($file, $tag_info['view_mode'], $settings);
     }
   }
 }
@@ -93,12 +93,27 @@ function media_wysiwyg_view_mode_media_token_to_markup_alter(&$element, $tag_inf
  */
 function media_wysiwyg_view_mode_form_alter(&$form, $form_state, $form_id)  {
   switch ($form_id)  {
-    case 'media_format_form':
-      $file = $form['#media'];
+    case 'media_wysiwyg_format_form':
+      $file = $form_state['file'];
 
-      $default_view_mode = variable_get('media__wysiwyg_default_view_mode', 'full');
-
-      $view_mode = !empty($form_state['values']['format']) ? $form_state['values']['format'] : $default_view_mode;
+      // Check to see if a view mode ("format") has already been specified for
+      //  this media item. First, check for a standard form-submitted value.
+      if (!empty($form_state['values']['format'])) {
+        $view_mode = $form_state['values']['format'];
+      }
+      // Second, check the request for a JSON-encoded value.
+      elseif (isset($_GET['fields'])) {
+        $query_fields = drupal_json_decode($_GET['fields']);
+        if (isset($query_fields['format'])) {
+          $view_mode = $query_fields['format'];
+        }
+      }
+      // If we were unable to determine a view mode, or we found a view mode
+      //  that does not exist in the list of format options presented on this
+      //  form, use the default view mode.
+      if (!isset($view_mode) || !array_key_exists($view_mode, $form['options']['format']['#options'])) {
+        $view_mode = variable_get('media_wysiwyg_wysiwyg_default_view_mode', 'full');
+      }
 
       $form['preview'] = file_view_file($file, $view_mode);
       $form['preview']['#prefix'] = '<div id="preview">';
@@ -112,17 +127,17 @@ function media_wysiwyg_view_mode_form_alter(&$form, $form_state, $form_id)  {
         'wrapper' => 'preview',
       );
 
-      $view_modes = media_get_wysiwyg_allowed_view_modes($file);
+      $view_modes = media_wysiwyg_get_wysiwyg_allowed_view_modes($file);
       $formats = $options = array();
       foreach ($view_modes as $view_mode => $view_mode_info) {
         //@TODO: Display more verbose information about which formatter and what it does.
         $options[$view_mode] = $view_mode_info['label'];
 
         if (variable_get("media_wysiwyg_view_mode_{$file->type}_file_wysiwyg_view_mode_status", FALSE) == TRUE) {
-          $element = media_get_file_without_label($file, variable_get("media_wysiwyg_view_mode_{$file->type}_file_wysiwyg_view_mode", 'wysiwyg'), array('wysiwyg' => TRUE));
+          $element = media_wysiwyg_get_file_without_label($file, variable_get("media_wysiwyg_view_mode_{$file->type}_file_wysiwyg_view_mode", 'wysiwyg'), array('wysiwyg' => TRUE));
         }
         else {
-          $element = media_get_file_without_label($file, $view_mode, array('wysiwyg' => TRUE));
+          $element = media_wysiwyg_get_file_without_label($file, $view_mode, array('wysiwyg' => TRUE));
         }
 
         // Make a pretty name out of this.
diff --git a/drupal7/sites/all/modules/media/modules/media_wysiwyg_view_mode/media_wysiwyg_view_mode.test b/drupal7/sites/all/modules/media/modules/media_wysiwyg_view_mode/media_wysiwyg_view_mode.test
new file mode 100644
index 00000000..a51dc2fa
--- /dev/null
+++ b/drupal7/sites/all/modules/media/modules/media_wysiwyg_view_mode/media_wysiwyg_view_mode.test
@@ -0,0 +1,65 @@
+<?php
+
+/**
+ * @file
+ * Tests for media_wysiwyg_view_mode.module.
+ */
+
+/**
+ * Defines base class for media_wysiwyg_view_mode test cases.
+ */
+class MediaWYSIWYGViewModeTestHelper extends MediaWYSIWYGTestHelper {
+  function setUp() {
+    parent::setUp('media_wysiwyg_view_mode');
+
+    $web_user = $this->drupalCreateUser(array('administer media wysiwyg view mode', 'view files'));
+    $this->drupalLogin($web_user);
+  }
+}
+
+/**
+ * Test configuring view modes available on the format form.
+ */
+class FormatFormViewModesTest extends MediaWYSIWYGViewModeTestHelper {
+  public static function getInfo() {
+    return array(
+      'name' => 'Format Form WYSIWYG View Modes',
+      'description' => 'Test configuring view modes available on the format form.',
+      'group' => 'Media WYSIWYG View Mode',
+    );
+  }
+
+  function setUp() {
+    parent::setUp();
+  }
+
+  /**
+   * Configure format form view mode restrictions and ensure that they are followed.
+   */
+  function testAllowedFormatFormViewModes() {
+    // Load the Media WYSIWYG View Mode administration page.
+    $this->drupalGet('admin/config/media/wysiwyg-view-mode');
+    $this->assertResponse(200, t('The privileged user can access the Media WYSIWYG View Mode administration page.'));
+
+    // Create an image file to test with.
+    $files = $this->drupalGetTestFiles('image');
+    $files[0]->status = FILE_STATUS_PERMANENT;
+    $file = file_save($files[0]);
+    $fid = $file->fid;
+
+    // The default view mode should be selected by default.
+    $this->drupalGet('media/' . $fid . '/format-form');
+    $this->assertOptionSelected('edit-format', 'default');
+
+    // Restrict the use of the default view mode.
+    variable_set('media_wysiwyg_view_mode_image_wysiwyg_restricted_view_modes_status', TRUE);
+    $restricted_view_modes = array(
+      'default' => 'default',
+    );
+    variable_set('media_wysiwyg_view_mode_image_wysiwyg_restricted_view_modes', $restricted_view_modes);
+
+    // The teaser view mode should now be selected by default.
+    $this->drupalGet('media/' . $fid . '/format-form');
+    $this->assertOptionSelected('edit-format', 'teaser');
+  }
+}
diff --git a/drupal7/sites/all/modules/media/modules/mediafield/mediafield.info b/drupal7/sites/all/modules/media/modules/mediafield/mediafield.info
index a79d9df9..ed00075c 100644
--- a/drupal7/sites/all/modules/media/modules/mediafield/mediafield.info
+++ b/drupal7/sites/all/modules/media/modules/mediafield/mediafield.info
@@ -4,9 +4,9 @@ package = Media
 core = 7.x
 dependencies[] = media
 
-; Information added by drupal.org packaging script on 2013-10-25
-version = "7.x-2.0-alpha3"
+; Information added by Drupal.org packaging script on 2014-10-04
+version = "7.x-2.0-alpha4"
 core = "7.x"
 project = "media"
-datestamp = "1382744872"
+datestamp = "1412422430"
 
diff --git a/drupal7/sites/all/modules/media/tests/media.entity.test b/drupal7/sites/all/modules/media/tests/media.entity.test
deleted file mode 100644
index f2f40dee..00000000
--- a/drupal7/sites/all/modules/media/tests/media.entity.test
+++ /dev/null
@@ -1,63 +0,0 @@
-<?php
-
-/**
- * @file
- * Tests for media entity controllers.
- */
-
-/**
- * Defines media entity creation and management test cases.
- */
-class MediaEntityTest extends MediaTestHelper {
-
-  /**
-   * Provides test information.
-   */
-  public static function getInfo() {
-    return array(
-      'name' => 'Media entity',
-      'description' => 'Tests media entity handling',
-      'group' => 'Media',
-    );
-  }
-
-  /**
-   * Test the ability to create and query media items.
-   */
-  public function testQueryMedia() {
-    $text_files = $this->drupalGetTestFiles('text');
-    $images = $this->drupalGetTestFiles('image');
-
-    // Moves serveral images to public://
-    foreach (array_merge($text_files, $images) as $file) {
-      // file_uri_to_object triggers a fatal error to d.o testbot.
-      // lets remove for now..
-      // $file = file_uri_to_object($file->uri);
-      file_save($file);
-    }
-
-    $query = new EntityFieldQuery();
-    $query->entityCondition('entity_type', 'file');
-    $query->propertyCondition('uri', 'public://%', 'LIKE');
-    $result = $query->execute();
-    $this->assertEqual(count($result['file']), count($images) + count($text_files), 'Returned results as expected for like % condition.');
-
-    $query = new EntityFieldQuery();
-    $query->entityCondition('entity_type', 'file');
-    $query->propertyCondition('uri', '%.jpg', 'LIKE');
-    $result = $query->execute();
-    $this->assertEqual(count($result['file']), 2, 'Returned 2 results as expected for jpgs.');
-
-    $query = new EntityFieldQuery();
-    $query->entityCondition('entity_type', 'file');
-    $query->propertyCondition('type', 'image');
-    $result = $query->execute();
-    $this->assertEqual(count($result['file']), count($images), 'Returned expected results for type query.');
-
-    $query = new EntityFieldQuery();
-    $query->entityCondition('entity_type', 'file');
-    $query->propertyCondition('uri', 'http://%', 'LIKE');
-    $result = $query->execute();
-    $this->assertEqual(count($result), 0, 'Returned 0 results as expected for http scheme uris.');
-  }
-}
diff --git a/drupal7/sites/all/modules/media/tests/media.test b/drupal7/sites/all/modules/media/tests/media.test
index aaf6dcd6..97e99ef1 100644
--- a/drupal7/sites/all/modules/media/tests/media.test
+++ b/drupal7/sites/all/modules/media/tests/media.test
@@ -6,14 +6,1140 @@
  */
 
 /**
- * Defines base class for media test cases.
+ * Provides methods specifically for testing Media module's field handling.
  */
-class MediaTestHelper extends DrupalWebTestCase {
+class MediaFileFieldTestCase extends DrupalWebTestCase {
+  protected $admin_user;
+
+  function setUp() {
+    // Since this is a base class for many test cases, support the same
+    // flexibility that DrupalWebTestCase::setUp() has for the modules to be
+    // passed in as either an array or a variable number of string arguments.
+    $modules = func_get_args();
+    if (isset($modules[0]) && is_array($modules[0])) {
+      $modules = $modules[0];
+    }
+    $modules[] = 'media';
+    $modules[] = 'media_module_test';
+    parent::setUp($modules);
+    $this->admin_user = $this->drupalCreateUser(array('access content', 'view files', 'view own files', 'access media browser', 'access administration pages', 'administer site configuration', 'administer users', 'administer permissions', 'administer content types', 'administer nodes', 'administer files', 'bypass node access', 'bypass file access'));
+    $this->drupalLogin($this->admin_user);
+  }
+
+  /**
+   * Retrieves a sample file of the specified type.
+   */
+  function getTestFile($type_name, $size = NULL) {
+    // Get a file to upload.
+    $file = current($this->drupalGetTestFiles($type_name, $size));
+
+    // Add a filesize property to files as would be read by file_load().
+    $file->filesize = filesize($file->uri);
+
+    return $file;
+  }
+
+  /**
+   * Creates a new file entity.
+   *
+   * @param $settings
+   *   A list of settings that will be added to the entity defaults.
+   */
+  protected function createFileEntity($settings = array()) {
+    $file = new stdClass();
+
+    // Populate defaults array.
+    $settings += array(
+      'filepath' => 'Файл для тестирования ' . $this->randomName(), // Prefix with non-latin characters to ensure that all file-related tests work with international filenames.
+      'filemime' => 'text/plain',
+      'uid' => 1,
+      'timestamp' => REQUEST_TIME,
+      'status' => FILE_STATUS_PERMANENT,
+      'contents' => "file_put_contents() doesn't seem to appreciate empty strings so let's put in some data.",
+      'scheme' => file_default_scheme(),
+      'type' => NULL,
+    );
+
+    $filepath = $settings['scheme'] . '://' . $settings['filepath'];
+
+    file_put_contents($filepath, $settings['contents']);
+    $this->assertTrue(is_file($filepath), t('The test file exists on the disk.'), 'Create test file');
+
+    $file = new stdClass();
+    $file->uri = $filepath;
+    $file->filename = drupal_basename($file->uri);
+    $file->filemime = $settings['filemime'];
+    $file->uid = $settings['uid'];
+    $file->timestamp = $settings['timestamp'];
+    $file->filesize = filesize($file->uri);
+    $file->status = $settings['status'];
+    $file->type = $settings['type'];
+
+    // The file type is used as a bundle key, and therefore, must not be NULL.
+    if (!isset($file->type)) {
+      $file->type = FILE_TYPE_NONE;
+    }
+
+    // If the file isn't already assigned a real type, determine what type should
+    // be assigned to it.
+    if ($file->type === FILE_TYPE_NONE) {
+      $type = file_get_type($file);
+      if (isset($type)) {
+        $file->type = $type;
+      }
+    }
+
+    // Write the record directly rather than calling file_save() so we don't
+    // invoke the hooks.
+    $this->assertNotIdentical(drupal_write_record('file_managed', $file), FALSE, t('The file was added to the database.'), 'Create test file');
+
+    return $file;
+  }
+
+  /**
+   * Creates a new file field.
+   *
+   * @param $name
+   *   The name of the new field (all lowercase), exclude the "field_" prefix.
+   * @param $type_name
+   *   The node type that this field will be added to.
+   * @param $field_settings
+   *   A list of field settings that will be added to the defaults.
+   * @param $instance_settings
+   *   A list of instance settings that will be added to the instance defaults.
+   * @param $widget_settings
+   *   A list of widget settings that will be added to the widget defaults.
+   */
+  function createFileField($name, $type_name, $field_settings = array(), $instance_settings = array(), $widget_settings = array()) {
+    $field = array(
+      'field_name' => $name,
+      'type' => 'file',
+      'settings' => array(),
+      'cardinality' => !empty($field_settings['cardinality']) ? $field_settings['cardinality'] : 1,
+    );
+    $field['settings'] = array_merge($field['settings'], $field_settings);
+    field_create_field($field);
+
+    $this->attachFileField($name, 'node', $type_name, $instance_settings, $widget_settings);
+  }
+
+  /**
+   * Attaches a file field to an entity.
+   *
+   * @param $name
+   *   The name of the new field (all lowercase), exclude the "field_" prefix.
+   * @param $entity_type
+   *   The entity type this field will be added to.
+   * @param $bundle
+   *   The bundle this field will be added to.
+   * @param $field_settings
+   *   A list of field settings that will be added to the defaults.
+   * @param $instance_settings
+   *   A list of instance settings that will be added to the instance defaults.
+   * @param $widget_settings
+   *   A list of widget settings that will be added to the widget defaults.
+   */
+  function attachFileField($name, $entity_type, $bundle, $instance_settings = array(), $widget_settings = array()) {
+    $instance = array(
+      'field_name' => $name,
+      'label' => $name,
+      'entity_type' => $entity_type,
+      'bundle' => $bundle,
+      'required' => !empty($instance_settings['required']),
+      'settings' => array(),
+      'widget' => array(
+        'type' => 'media_generic',
+        'settings' => array(),
+      ),
+    );
+    $instance['settings'] = array_merge($instance['settings'], $instance_settings);
+    $instance['widget']['settings'] = array_merge($instance['widget']['settings'], $widget_settings);
+    field_create_instance($instance);
+  }
+
+  /**
+   * Attaches a file to a node.
+   */
+  function attachNodeFile($file, $field_name, $nid_or_type, $new_revision = TRUE, $extras = array()) {
+    $langcode = LANGUAGE_NONE;
+    $edit = array(
+      "title" => $this->randomName(),
+      'revision' => (string) (int) $new_revision,
+    );
+
+    if (is_numeric($nid_or_type)) {
+      $nid = $nid_or_type;
+    }
+    else {
+      // Add a new node.
+      $extras['type'] = $nid_or_type;
+      $node = $this->drupalCreateNode($extras);
+      $nid = $node->nid;
+      // Save at least one revision to better simulate a real site.
+      $this->drupalCreateNode(get_object_vars($node));
+      $node = node_load($nid, NULL, TRUE);
+      $this->assertNotEqual($nid, $node->vid, 'Node revision exists.');
+    }
+
+    // Attach a file to the node.
+    $edit['media[' . $field_name . '_' . $langcode . '_0]'] = $file->fid;
+    $this->drupalPost("node/$nid/edit", $edit, t('Save'));
+
+    return $nid;
+  }
+
+  /**
+   * Replaces a file within a node.
+   */
+  function replaceNodeFile($file, $field_name, $nid, $new_revision = TRUE) {
+    $edit = array(
+      $field_name . '[' . LANGUAGE_NONE . '][0][fid]' => $file->fid,
+      'revision' => (string) (int) $new_revision,
+    );
+
+    $this->drupalPost('node/' . $nid . '/edit', array(), t('Remove'));
+    $this->drupalPost(NULL, $edit, t('Save'));
+  }
+
+  /**
+   * Asserts that a file exists physically on disk.
+   */
+  function assertFileExists($file, $message = NULL) {
+    $message = isset($message) ? $message : format_string('File %file exists on the disk.', array('%file' => $file->uri));
+    $this->assertTrue(is_file($file->uri), $message);
+  }
+
+  /**
+   * Asserts that a file exists in the database.
+   */
+  function assertFileEntryExists($file, $message = NULL) {
+    entity_get_controller('file')->resetCache();
+    $db_file = file_load($file->fid);
+    $message = isset($message) ? $message : format_string('File %file exists in database at the correct path.', array('%file' => $file->uri));
+    $this->assertEqual($db_file->uri, $file->uri, $message);
+  }
+
+  /**
+   * Asserts that a file does not exist on disk.
+   */
+  function assertFileNotExists($file, $message = NULL) {
+    $message = isset($message) ? $message : format_string('File %file exists on the disk.', array('%file' => $file->uri));
+    $this->assertFalse(is_file($file->uri), $message);
+  }
+
+  /**
+   * Asserts that a file does not exist in the database.
+   */
+  function assertFileEntryNotExists($file, $message) {
+    entity_get_controller('file')->resetCache();
+    $message = isset($message) ? $message : format_string('File %file exists in database at the correct path.', array('%file' => $file->uri));
+    $this->assertFalse(file_load($file->fid), $message);
+  }
+
+  /**
+   * Asserts that a file's status is set to permanent in the database.
+   */
+  function assertFileIsPermanent($file, $message = NULL) {
+    $message = isset($message) ? $message : format_string('File %file is permanent.', array('%file' => $file->uri));
+    $this->assertTrue($file->status == FILE_STATUS_PERMANENT, $message);
+  }
+}
+
+/**
+ * Tests the 'media' element type.
+ *
+ * @todo Create a MediaFileTestCase base class and move MediaFileFieldTestCase
+ *   methods that aren't related to fields into it.
+ */
+class MediaElementTestCase extends MediaFileFieldTestCase {
+  public static function getInfo() {
+    return array(
+      'name' => 'Media element test',
+      'description' => 'Tests the media element type.',
+      'group' => 'Media',
+    );
+  }
+
+  /**
+   * Tests the media element type.
+   */
+  function testMedia() {
+    // Check that $element['#size'] is passed to the child upload element.
+    $this->drupalGet('media/test');
+    $this->assertFieldByXpath('//input[@name="media[nested_media]" and @size="13"]', NULL, 'The custom #size attribute is passed to the child upload element.');
+
+    // Perform the tests with all permutations of $form['#tree'] and
+    // $element['#extended'].
+    foreach (array(0, 1) as $tree) {
+      foreach (array(0, 1) as $extended) {
+        $test_file = $this->getTestFile('text');
+        $test_file->uid = $this->admin_user->uid;
+        $test_file = file_save($test_file);
+        $path = 'media/test/' . $tree . '/' . $extended;
+        $input_base_name = $tree ? 'nested_media' : 'media';
+
+        // Submit without a file.
+        $this->drupalPost($path, array(), t('Save'));
+        $this->assertRaw(t('The file id is %fid.', array('%fid' => 0)), 'Submitted without a file.');
+
+        // Submit a new file, without using the Attach button.
+        $edit = array('media[' . $input_base_name . ']' => $test_file->fid);
+        $this->drupalPost($path, $edit, t('Save'));
+        $this->assertRaw(t('The file id is %fid.', array('%fid' => $test_file->fid)), 'Submit handler has correct file info.');
+
+        // Now, test the Attach and Remove buttons, with and without Ajax.
+        foreach (array(FALSE) as $ajax) {
+          // Attach, then Submit.
+          $this->drupalGet($path);
+          $edit = array('media[' . $input_base_name . ']' => $test_file->fid);
+          if ($ajax) {
+            $this->drupalPostAJAX(NULL, $edit, $input_base_name . '_attach_button');
+          }
+          else {
+            $this->drupalPost(NULL, $edit, t('Attach'));
+          }
+          $this->drupalPost(NULL, array(), t('Save'));
+          $this->assertRaw(t('The file id is %fid.', array('%fid' => $test_file->fid)), 'Submit handler has correct file info.');
+
+          // Attach, then Remove, then Submit.
+          $this->drupalGet($path);
+          $edit = array('media[' . $input_base_name . ']' => $test_file->fid);
+          if ($ajax) {
+            $this->drupalPostAJAX(NULL, $edit, $input_base_name . '_attach_button');
+            $this->drupalPostAJAX(NULL, array(), $input_base_name . '_remove_button');
+          }
+          else {
+            $this->drupalPost(NULL, $edit, t('Attach'));
+            $this->drupalPost(NULL, array(), t('Remove'));
+          }
+          $this->drupalPost(NULL, array(), t('Save'));
+          $this->assertRaw(t('The file id is %fid.', array('%fid' => 0)), 'Submission after file attachment and removal was successful.');
+        }
+      }
+    }
+  }
+}
+
+/**
+ * Test media file administration page functionality.
+ */
+class MediaAdminTestCase extends MediaFileFieldTestCase {
+  public static function getInfo() {
+    return array(
+      'name' => 'Media file administration',
+      'description' => 'Test media file administration page functionality.',
+      'group' => 'Media',
+    );
+  }
+
+  function setUp() {
+    parent::setUp();
+    // Remove the "view files" permission which is set
+    // by default for all users so we can test this permission
+    // correctly.
+    $roles = user_roles();
+    foreach ($roles as $rid => $role) {
+      user_role_revoke_permissions($rid, array('view files'));
+    }
+
+    $this->base_user_1 = $this->drupalCreateUser(array('administer files'));
+    $this->base_user_2 = $this->drupalCreateUser(array('administer files', 'view own private files'));
+    $this->base_user_3 = $this->drupalCreateUser(array('administer files', 'view private files'));
+    $this->base_user_4 = $this->drupalCreateUser(array('administer files', 'edit any document files', 'delete any document files', 'edit any image files', 'delete any image files'));
+  }
+
+  /**
+   * Tests that the table sorting works on the files admin pages.
+   */
+  function testFilesAdminSort() {
+    $i = 0;
+    foreach (array('dd', 'aa', 'DD', 'bb', 'cc', 'CC', 'AA', 'BB') as $prefix) {
+      $this->createFileEntity(array('filepath' => $prefix . $this->randomName(6), 'timestamp' => $i));
+      $i++;
+    }
+
+    // Test that the default sort by file_managed.timestamp DESC actually fires properly.
+    $files_query = db_select('file_managed', 'fm')
+      ->fields('fm', array('fid'))
+      ->orderBy('timestamp', 'DESC')
+      ->execute()
+      ->fetchCol();
+
+    $files_form = array();
+    $this->drupalGet('admin/content/file/thumbnails');
+    foreach ($this->xpath('//ul[@class="media-list-thumbnails"]/li/div[@data-fid]/@data-fid') as $input) {
+      $files_form[] = $input;
+    }
+    $this->assertEqual($files_query, $files_form, 'Files are sorted in the form according to the default query.');
+
+    // Compare the rendered HTML node list to a query for the files ordered by
+    // filename to account for possible database-dependent sort order.
+    $files_query = db_select('file_managed', 'fm')
+      ->fields('fm', array('fid'))
+      ->orderBy('filename')
+      ->execute()
+      ->fetchCol();
+
+    $files_form = array();
+    $this->drupalGet('admin/content/file/thumbnails', array('query' => array('sort' => 'asc', 'order' => 'Title')));
+    foreach ($this->xpath('//ul[@class="media-list-thumbnails"]/li/div[@data-fid]/@data-fid') as $input) {
+      $files_form[] = $input;
+    }
+    $this->assertEqual($files_query, $files_form, 'Files are sorted in the form the same as they are in the query.');
+  }
+
+  /**
+   * Tests files overview with different user permissions.
+   */
+  function testFilesAdminPages() {
+    $files['public_image'] = $this->createFileEntity(array('scheme' => 'public', 'uid' => $this->base_user_1->uid, 'type' => 'image'));
+    $files['public_document'] = $this->createFileEntity(array('scheme' => 'public', 'uid' => $this->base_user_2->uid, 'type' => 'document'));
+    $files['private_image'] = $this->createFileEntity(array('scheme' => 'private', 'uid' => $this->base_user_1->uid, 'type' => 'image'));
+    $files['private_document'] = $this->createFileEntity(array('scheme' => 'private', 'uid' => $this->base_user_2->uid, 'type' => 'document'));
+
+    // Verify view and edit links for any file.
+    $this->drupalGet('admin/content/file/thumbnails');
+    $this->assertResponse(200);
+    foreach ($files as $file) {
+      $this->assertLinkByHref('file/' . $file->fid);
+      $this->assertLinkByHref('file/' . $file->fid . '/edit');
+      // Verify tableselect.
+      $this->assertFieldByName('files[' . $file->fid . ']', '', t('Tableselect found.'));
+    }
+
+    // Verify no operation links are displayed for regular users.
+    $this->drupalLogout();
+    $this->drupalLogin($this->base_user_1);
+    $this->drupalGet('admin/content/file/thumbnails');
+    $this->assertResponse(200);
+    $this->assertLinkByHref('file/' . $files['public_image']->fid);
+    $this->assertLinkByHref('file/' . $files['public_document']->fid);
+    $this->assertNoLinkByHref('file/' . $files['public_image']->fid . '/edit');
+    $this->assertNoLinkByHref('file/' . $files['public_document']->fid . '/edit');
+
+    // Verify no tableselect.
+    $this->assertNoFieldByName('files[' . $files['public_image']->fid . ']', '', t('No tableselect found.'));
+
+    // Verify private file is displayed with permission.
+    $this->drupalLogout();
+    $this->drupalLogin($this->base_user_2);
+    $this->drupalGet('admin/content/file/thumbnails');
+    $this->assertResponse(200);
+    $this->assertLinkByHref('file/' . $files['private_document']->fid);
+    // Verify no operation links are displayed.
+    $this->assertNoLinkByHref('file/' . $files['private_document']->fid . '/edit');
+
+    // Verify user cannot see private file of other users.
+    $this->assertNoLinkByHref('file/' . $files['private_image']->fid);
+    $this->assertNoLinkByHref('file/' . $files['private_image']->fid . '/edit');
+
+    // Verify no tableselect.
+    $this->assertNoFieldByName('files[' . $files['private_document']->fid . ']', '', t('No tableselect found.'));
+
+    // Verify private file is displayed with permission.
+    $this->drupalLogout();
+    $this->drupalLogin($this->base_user_3);
+    $this->drupalGet('admin/content/file/thumbnails');
+    $this->assertResponse(200);
+
+    // Verify user can see private file of other users.
+    $this->assertLinkByHref('file/' . $files['private_document']->fid);
+    $this->assertLinkByHref('file/' . $files['private_image']->fid);
+
+    // Verify operation links are displayed for users with appropriate permission.
+    $this->drupalLogout();
+    $this->drupalLogin($this->base_user_4);
+    $this->drupalGet('admin/content/file/thumbnails');
+    $this->assertResponse(200);
+    foreach ($files as $file) {
+      $this->assertLinkByHref('file/' . $file->fid);
+      $this->assertLinkByHref('file/' . $file->fid . '/edit');
+    }
+
+    // Verify file access can be bypassed.
+    $this->drupalLogout();
+    $this->drupalLogin($this->admin_user);
+    $this->drupalGet('admin/content/file/thumbnails');
+    $this->assertResponse(200);
+    foreach ($files as $file) {
+      $this->assertLinkByHref('file/' . $file->fid);
+      $this->assertLinkByHref('file/' . $file->fid . '/edit');
+    }
+  }
+}
+
+/**
+ * Tests the media browser 'Library' tab.
+ */
+class MediaBrowserLibraryTestCase extends MediaFileFieldTestCase {
+  public static function getInfo() {
+    return array(
+      'name' => 'Media browser library test',
+      'description' => 'Tests the media browser library tab.',
+      'group' => 'Media',
+    );
+  }
+
+  function setUp() {
+    parent::setUp();
+    $this->base_user_1 = $this->drupalCreateUser(array('access media browser', 'create files', 'administer files'));
+    $this->base_user_2 = $this->drupalCreateUser(array('access media browser', 'create files', 'administer files', 'view own private files'));
+    $this->base_user_3 = $this->drupalCreateUser(array('access media browser', 'create files', 'administer files', 'view private files'));
+  }
+
+  /**
+   * Tests that the views sorting works on the media browser 'Library' tab.
+   */
+  function testFilesBrowserSort() {
+    // Load only the 'Library' tab of the media browser.
+    $options = array(
+      'query' => array(
+        'enabledPlugins' => array(
+          'media_default--media_browser_1' => 'media_default--media_browser_1',
+        ),
+      ),
+    );
+
+    $i = 0;
+    foreach (array('dd', 'aa', 'DD', 'bb', 'cc', 'CC', 'AA', 'BB') as $prefix) {
+      $this->createFileEntity(array('filepath' => $prefix . $this->randomName(6), 'timestamp' => $i));
+      $i++;
+    }
+
+    // Test that the default sort by file_managed.timestamp DESC actually fires properly.
+    $files_query = db_select('file_managed', 'fm')
+      ->fields('fm', array('fid'))
+      ->orderBy('timestamp', 'DESC')
+      ->execute()
+      ->fetchCol();
+
+    $files_form = array();
+    $this->drupalGet('media/browser', $options);
+    foreach ($this->xpath('//ul[@class="media-list-thumbnails"]/li/div[@data-fid]/@data-fid') as $input) {
+      $files_form[] = $input;
+    }
+    $this->assertEqual($files_query, $files_form, 'Files are sorted in the form according to the default query.');
+  }
 
   /**
-   * Enable media and file entity modules for testing.
+   * Tests media browser 'Library' tab with different user permissions.
    */
-  public function setUp() {
-    parent::setUp(array('media', 'file_entity'));
+  function testFilesBrowserLibrary() {
+    // Load only the 'Library' tab of the media browser.
+    $options = array(
+      'query' => array(
+        'enabledPlugins' => array(
+          'media_default--media_browser_1' => 'media_default--media_browser_1',
+        ),
+      ),
+    );
+
+    $files['public_image'] = $this->createFileEntity(array('scheme' => 'public', 'uid' => $this->base_user_1->uid, 'type' => 'image'));
+    $files['public_document'] = $this->createFileEntity(array('scheme' => 'public', 'uid' => $this->base_user_2->uid, 'type' => 'document'));
+    $files['private_image'] = $this->createFileEntity(array('scheme' => 'private', 'uid' => $this->base_user_1->uid, 'type' => 'image'));
+    $files['private_document'] = $this->createFileEntity(array('scheme' => 'private', 'uid' => $this->base_user_2->uid, 'type' => 'document'));
+
+    // Verify all files are displayed for administrators.
+    $this->drupalGet('media/browser', $options);
+    $this->assertResponse(200);
+    foreach ($files as $file) {
+      $xpath = $this->buildXPathQuery('//ul[@class="media-list-thumbnails"]/li/div[@data-fid=:fid]/@data-fid', array(
+        ':fid' => $file->fid,
+      ));
+      $this->assertFieldByXPath($xpath, TRUE, format_string('File with file ID %fid found.', array('%fid' => $file->fid)));
+    }
+
+    // Verify public files are displayed.
+    $this->drupalLogout();
+    $this->drupalLogin($this->base_user_1);
+    $this->drupalGet('media/browser', $options);
+    $this->assertResponse(200);
+    $xpath = $this->buildXPathQuery('//ul[@class="media-list-thumbnails"]/li/div[@data-fid=:fid]/@data-fid', array(
+      ':fid' => $files['public_image']->fid,
+    ));
+    $this->assertFieldByXPath($xpath, TRUE, format_string('File with file ID %fid found.', array('%fid' => $files['public_image']->fid)));
+    $xpath = $this->buildXPathQuery('//ul[@class="media-list-thumbnails"]/li/div[@data-fid=:fid]/@data-fid', array(
+      ':fid' => $files['public_document']->fid,
+    ));
+    $this->assertFieldByXPath($xpath, TRUE, format_string('File with file ID %fid found.', array('%fid' => $files['public_document']->fid)));
+
+    // Verify private file is displayed with permission.
+    $this->drupalLogout();
+    $this->drupalLogin($this->base_user_2);
+    $this->drupalGet('media/browser', $options);
+    $this->assertResponse(200);
+    $xpath = $this->buildXPathQuery('//ul[@class="media-list-thumbnails"]/li/div[@data-fid=:fid]/@data-fid', array(
+      ':fid' => $files['private_document']->fid,
+    ));
+    $this->assertFieldByXPath($xpath, TRUE, format_string('File with file ID %fid found.', array('%fid' => $files['private_document']->fid)));
+
+    // Verify user cannot see private file of other users.
+    $xpath = $this->buildXPathQuery('//ul[@class="media-list-thumbnails"]/li/div[@data-fid=:fid]/@data-fid', array(
+      ':fid' => $files['private_image']->fid,
+    ));
+    $this->assertNoFieldByXPath($xpath, TRUE, format_string('File with file ID %fid not found.', array('%fid' => $files['private_image']->fid)));
+
+    // Verify private file is displayed with permission.
+    $this->drupalLogout();
+    $this->drupalLogin($this->base_user_3);
+    $this->drupalGet('media/browser', $options);
+    $this->assertResponse(200);
+
+    // Verify user can see private file of other users.
+    $xpath = $this->buildXPathQuery('//ul[@class="media-list-thumbnails"]/li/div[@data-fid=:fid]/@data-fid', array(
+      ':fid' => $files['private_document']->fid,
+    ));
+    $this->assertFieldByXPath($xpath, TRUE, format_string('File with file ID %fid found.', array('%fid' => $files['private_document']->fid)));
+    $xpath = $this->buildXPathQuery('//ul[@class="media-list-thumbnails"]/li/div[@data-fid=:fid]/@data-fid', array(
+      ':fid' => $files['private_image']->fid,
+    ));
+    $this->assertFieldByXPath($xpath, TRUE, format_string('File with file ID %fid found.', array('%fid' => $files['private_image']->fid)));
+
+    // Verify file access can be bypassed.
+    $this->drupalLogout();
+    $this->drupalLogin($this->admin_user);
+    $this->drupalGet('media/browser', $options);
+    $this->assertResponse(200);
+    foreach ($files as $file) {
+      $xpath = $this->buildXPathQuery('//ul[@class="media-list-thumbnails"]/li/div[@data-fid=:fid]/@data-fid', array(
+        ':fid' => $file->fid,
+      ));
+      $this->assertFieldByXPath($xpath, TRUE, format_string('File with file ID %fid found.', array('%fid' => $file->fid)));
+    }
+  }
+}
+
+/**
+ * Tests the media browser settings.
+ */
+class MediaBrowserSettingsTestCase extends MediaFileFieldTestCase {
+  public static function getInfo() {
+    return array(
+      'name' => 'Media browser settings test',
+      'description' => 'Tests the media browser settings.',
+      'group' => 'Media',
+    );
+  }
+
+  function setUp() {
+    parent::setUp('file_test');
+  }
+
+  /**
+   * Tests the media browser settings.
+   */
+  function testBrowserSettings() {
+    $settings = array(
+      'scheme' => array('public', 'private'),
+      'type' => array('image', 'document'),
+      'extension' => array('jpg', 'txt'),
+    );
+
+    // Perform the tests with unique permutations of $scheme, $type and
+    // $extension.
+    foreach ($settings['scheme'] as $scheme) {
+      foreach ($settings['type'] as $type) {
+        foreach ($settings['extension'] as $extension) {
+          $file = $this->createFileEntity(array('scheme' => $scheme, 'uid' => $this->admin_user->uid, 'type' => $type, 'filemime' => media_get_extension_mimetype($extension)));
+
+          $options = array(
+            'query' => array(
+              'enabledPlugins' => array(
+                'media_default--media_browser_1' => 'media_default--media_browser_1',
+              ),
+              'schemes' => array($scheme),
+              'types' => array($type),
+              'file_extensions' => $extension,
+            ),
+          );
+
+          // Verify that the file is displayed.
+          $this->drupalGet('media/browser', $options);
+          $this->assertResponse(200);
+          $xpath = $this->buildXPathQuery('//ul[@class="media-list-thumbnails"]/li/div[@data-fid=:fid]/@data-fid', array(
+            ':fid' => $file->fid,
+          ));
+          $this->assertFieldByXPath($xpath, TRUE, format_string('File with file ID %fid found.', array('%fid' => $file->fid)));
+
+          // Verify that no other files are also displayed.
+          $files = $this->xpath('//ul[@class="media-list-thumbnails"]/li/div[@data-fid]');
+          $this->assertEqual(count($files), 1, 'There is only one file that matches the current browser configuration.');
+        }
+      }
+    }
+
+    // Perform the tests with none and all of the restrictions.
+    foreach (array('none', 'all') as $restrictions) {
+      $options = array(
+        'query' => array(
+          'enabledPlugins' => array(
+            'media_default--media_browser_1' => 'media_default--media_browser_1',
+          ),
+        ),
+      );
+
+      switch ($restrictions) {
+        case 'none':
+          $options['query']['schemes'] = array();
+          $options['query']['types'] = array();
+          $options['query']['file_extensions'] = array();
+          break;
+        case 'all':
+          $options['query']['schemes'] = $settings['scheme'];
+          $options['query']['types'] = $settings['type'];
+          $options['query']['file_extensions'] = implode(' ', $settings['extension']);
+          break;
+      }
+
+      // Verify that all of the files are displayed.
+      $this->drupalGet('media/browser', $options);
+      $this->assertResponse(200);
+      $files = $this->xpath('//ul[@class="media-list-thumbnails"]/li/div[@data-fid]');
+      $this->assertEqual(count($files), 8, format_string('All of the files were displayed when %restrictions of the restrictions were enabled.', array('%restrictions' => $restrictions)));
+    }
+
+    // Verify that extension restrictions do not affect remote files.
+    $scheme = 'dummy-remote';
+    $type = 'video';
+    $extension = 'mp4';
+
+    $file = $this->createFileEntity(array('scheme' => $scheme, 'uid' => $this->admin_user->uid, 'type' => $type, 'filemime' => media_get_extension_mimetype($extension)));
+
+    $options = array(
+      'query' => array(
+        'enabledPlugins' => array(
+          'media_default--media_browser_1' => 'media_default--media_browser_1',
+        ),
+        'schemes' => array($scheme, 'public'), // Include a local stream wrapper in order to trigger extension restrictions.
+        'types' => array($type),
+        'file_extensions' => 'fake', // Use an invalid file extension to ensure that it does not affect restrictions.
+      ),
+    );
+
+    // Verify that the file is displayed.
+    $this->drupalGet('media/browser', $options);
+    $this->assertResponse(200);
+    $xpath = $this->buildXPathQuery('//ul[@class="media-list-thumbnails"]/li/div[@data-fid=:fid]/@data-fid', array(
+      ':fid' => $file->fid,
+    ));
+    $this->assertFieldByXPath($xpath, TRUE, format_string('File with file ID %fid found.', array('%fid' => $file->fid)));
+
+    // Verify that no other files are also displayed.
+    $files = $this->xpath('//ul[@class="media-list-thumbnails"]/li/div[@data-fid]');
+    $this->assertEqual(count($files), 1, 'There is only one file that matches the current browser configuration.');
+  }
+}
+
+/**
+ * Tests the media browser 'My files' tab.
+ */
+class MediaBrowserMyFilesTestCase extends MediaFileFieldTestCase {
+  public static function getInfo() {
+    return array(
+      'name' => 'Media browser my files test',
+      'description' => 'Tests the media browser my files tab.',
+      'group' => 'Media',
+    );
+  }
+
+  function setUp() {
+    parent::setUp();
+    $this->base_user_1 = $this->drupalCreateUser(array('access media browser', 'create files', 'administer files'));
+    $this->base_user_2 = $this->drupalCreateUser(array('access media browser', 'create files', 'administer files', 'view own files'));
+    $this->base_user_3 = $this->drupalCreateUser(array('access media browser', 'create files', 'administer files', 'view own files', 'view own private files'));
+  }
+
+  /**
+   * Tests media browser 'My files' tab with different user permissions.
+   */
+  function testFilesBrowserMyFiles() {
+    // Load only the 'My files' tab of the media browser.
+    $options = array(
+      'query' => array(
+        'enabledPlugins' => array(
+          'media_default--media_browser_my_files' => 'media_default--media_browser_my_files',
+        ),
+      ),
+    );
+
+    $files['public_image'] = $this->createFileEntity(array('scheme' => 'public', 'uid' => $this->base_user_2->uid, 'type' => 'image'));
+    $files['public_document'] = $this->createFileEntity(array('scheme' => 'public', 'uid' => $this->base_user_3->uid, 'type' => 'document'));
+    $files['private_image'] = $this->createFileEntity(array('scheme' => 'private', 'uid' => $this->base_user_2->uid, 'type' => 'image'));
+    $files['private_document'] = $this->createFileEntity(array('scheme' => 'private', 'uid' => $this->base_user_3->uid, 'type' => 'document'));
+
+    // Verify administrators do not have any special access to files.
+    $this->drupalGet('media/browser', $options);
+    $this->assertResponse(200);
+    foreach ($files as $file) {
+      $xpath = $this->buildXPathQuery('//ul[@class="media-list-thumbnails"]/li/div[@data-fid=:fid]/@data-fid', array(
+        ':fid' => $file->fid,
+      ));
+      $this->assertNoFieldByXPath($xpath, TRUE, format_string('File with file ID %fid not found.', array('%fid' => $file->fid)));
+    }
+
+    // Verify users require the 'view own files' permission in order to access
+    // the 'My files' tab.
+    $this->drupalLogout();
+    $this->drupalLogin($this->base_user_1);
+    $this->drupalGet('media/browser', $options);
+    $this->assertResponse(200);
+    $xpath = $this->buildXPathQuery('//div[@class="media_default--media_browser_my_files"]');
+    $this->assertNoFieldByXPath($xpath, TRUE, 'User with insufficient permissions was unable to view the My files tab.');
+
+    // Verify own public files are displayed.
+    $this->drupalLogout();
+    $this->drupalLogin($this->base_user_2);
+    $this->drupalGet('media/browser', $options);
+    $this->assertResponse(200);
+    $xpath = $this->buildXPathQuery('//ul[@class="media-list-thumbnails"]/li/div[@data-fid=:fid]/@data-fid', array(
+      ':fid' => $files['public_image']->fid,
+    ));
+    $this->assertFieldByXPath($xpath, TRUE, format_string('File with file ID %fid found.', array('%fid' => $files['public_image']->fid)));
+
+    // Verify own private file is displayed with permission.
+    $this->drupalLogout();
+    $this->drupalLogin($this->base_user_3);
+    $this->drupalGet('media/browser', $options);
+    $this->assertResponse(200);
+    $xpath = $this->buildXPathQuery('//ul[@class="media-list-thumbnails"]/li/div[@data-fid=:fid]/@data-fid', array(
+      ':fid' => $files['private_document']->fid,
+    ));
+    $this->assertFieldByXPath($xpath, TRUE, format_string('File with file ID %fid found.', array('%fid' => $files['private_document']->fid)));
+
+    // Verify user cannot see files of other users.
+    $xpath = $this->buildXPathQuery('//ul[@class="media-list-thumbnails"]/li/div[@data-fid=:fid]/@data-fid', array(
+      ':fid' => $files['public_image']->fid,
+    ));
+    $this->assertNoFieldByXPath($xpath, TRUE, format_string('File with file ID %fid not found.', array('%fid' => $files['public_image']->fid)));
+    $xpath = $this->buildXPathQuery('//ul[@class="media-list-thumbnails"]/li/div[@data-fid=:fid]/@data-fid', array(
+      ':fid' => $files['private_image']->fid,
+    ));
+    $this->assertNoFieldByXPath($xpath, TRUE, format_string('File with file ID %fid not found.', array('%fid' => $files['private_image']->fid)));
+  }
+}
+
+/**
+ * Tests the 'media' element type settings.
+ */
+class MediaElementSettingsTestCase extends MediaFileFieldTestCase {
+  public static function getInfo() {
+    return array(
+      'name' => 'Media element settings test',
+      'description' => 'Tests the media element type JavaScript settings.',
+      'group' => 'Media',
+    );
+  }
+
+  /**
+   * Tests the media element type settings.
+   */
+  function testElementSettings() {
+    $form = array(
+      '#type' => 'media',
+    );
+    drupal_render($form);
+    $javascript = drupal_get_js();
+    $global = array(
+      'media' => array(
+        'global' => array(
+          'global' => array(
+            'types' => array(),
+            'schemes' => array(),
+          ),
+        ),
+      ),
+    );
+    $settings = drupal_json_encode(drupal_array_merge_deep_array($global));
+    $this->assertTrue(strpos($javascript, $settings) > 0, 'Rendered media element adds the global settings.');
+  }
+
+  /**
+   * Tests the media file field widget settings.
+   */
+  function testWidgetSettings() {
+    // Use 'page' instead of 'article', so that the 'article' image field does
+    // not conflict with this test. If in the future the 'page' type gets its
+    // own default file or image field, this test can be made more robust by
+    // using a custom node type.
+    $type_name = 'page';
+    $field_name = strtolower($this->randomName());
+    $this->createFileField($field_name, $type_name);
+    $field = field_info_field($field_name);
+    $instance = field_info_instance('node', $field_name, $type_name);
+
+    $javascript = $this->drupalGet("node/add/$type_name");
+    $field_widget = array(
+        'elements' => array(
+          '#edit-' . $field_name . '-' . LANGUAGE_NONE . '-0' => array(
+            'global' => array(
+              'types' => array(
+                0 => 'image',
+              ),
+              'enabledPlugins' => array(),
+              'schemes' => array(
+                0 => 'public',
+                1 => 'private',
+              ),
+              'file_directory' => '',
+              'file_extensions' => 'txt',
+              'max_filesize' => '',
+              'uri_scheme' => 'public',
+            ),
+          ),
+        ),
+    );
+    $settings = drupal_json_encode(drupal_array_merge_deep_array($field_widget));
+    $this->assertTrue(strpos($javascript, $settings) > 0, 'Media file field widget adds element-specific settings.');
+  }
+}
+
+/**
+ * Tests file handling with node revisions.
+ */
+class MediaFileFieldRevisionTestCase extends MediaFileFieldTestCase {
+  public static function getInfo() {
+    return array(
+      'name' => 'Media file field revision test',
+      'description' => 'Test creating and deleting revisions with files attached.',
+      'group' => 'Media',
+    );
+  }
+
+  /**
+   * Tests creating multiple revisions of a node and managing attached files.
+   *
+   * Expected behaviors:
+   *  - Adding a new revision will make another entry in the field table, but
+   *    the original file will not be duplicated.
+   *  - Deleting a revision should not delete the original file if the file
+   *    is in use by another revision.
+   *  - When the last revision that uses a file is deleted, the original file
+   *    should be deleted also.
+   */
+  function testRevisions() {
+    $type_name = 'article';
+    $field_name = strtolower($this->randomName());
+    $this->createFileField($field_name, $type_name);
+    $field = field_info_field($field_name);
+    $instance = field_info_instance('node', $field_name, $type_name);
+
+    // Attach the same fields to users.
+    $this->attachFileField($field_name, 'user', 'user');
+
+    $test_file = $this->getTestFile('text');
+    $test_file->uid = $this->admin_user->uid;
+    $test_file = file_save($test_file);
+
+    // Create a new node with the uploaded file.
+    $nid = $this->attachNodeFile($test_file, $field_name, $type_name);
+
+    // Check that the file exists on disk and in the database.
+    $node = node_load($nid, NULL, TRUE);
+    $node_file_r1 = (object) $node->{$field_name}[LANGUAGE_NONE][0];
+    $node_vid_r1 = $node->vid;
+    $this->assertFileExists($node_file_r1, 'New file saved to disk on node creation.');
+    $this->assertFileEntryExists($node_file_r1, 'File entry exists in database on node creation.');
+    $this->assertFileIsPermanent($node_file_r1, 'File is permanent.');
+
+    // Upload another file to the same node in a new revision.
+    $this->replaceNodeFile($test_file, $field_name, $nid);
+    $node = node_load($nid, NULL, TRUE);
+    $node_file_r2 = (object) $node->{$field_name}[LANGUAGE_NONE][0];
+    $node_vid_r2 = $node->vid;
+    $this->assertFileExists($node_file_r2, 'Replacement file exists on disk after creating new revision.');
+    $this->assertFileEntryExists($node_file_r2, 'Replacement file entry exists in database after creating new revision.');
+    $this->assertFileIsPermanent($node_file_r2, 'Replacement file is permanent.');
+
+    // Check that the original file is still in place on the first revision.
+    $node = node_load($nid, $node_vid_r1, TRUE);
+    $this->assertEqual($node_file_r1, (object) $node->{$field_name}[LANGUAGE_NONE][0], 'Original file still in place after replacing file in new revision.');
+    $this->assertFileExists($node_file_r1, 'Original file still in place after replacing file in new revision.');
+    $this->assertFileEntryExists($node_file_r1, 'Original file entry still in place after replacing file in new revision');
+    $this->assertFileIsPermanent($node_file_r1, 'Original file is still permanent.');
+
+    // Save a new version of the node without any changes.
+    // Check that the file is still the same as the previous revision.
+    $this->drupalPost('node/' . $nid . '/edit', array('revision' => '1'), t('Save'));
+    $node = node_load($nid, NULL, TRUE);
+    $node_file_r3 = (object) $node->{$field_name}[LANGUAGE_NONE][0];
+    $node_vid_r3 = $node->vid;
+    $this->assertEqual($node_file_r2, $node_file_r3, 'Previous revision file still in place after creating a new revision without a new file.');
+    $this->assertFileIsPermanent($node_file_r3, 'New revision file is permanent.');
+
+    // Revert to the first revision and check that the original file is active.
+    $this->drupalPost('node/' . $nid . '/revisions/' . $node_vid_r1 . '/revert', array(), t('Revert'));
+    $node = node_load($nid, NULL, TRUE);
+    $node_file_r4 = (object) $node->{$field_name}[LANGUAGE_NONE][0];
+    $node_vid_r4 = $node->vid;
+    $this->assertEqual($node_file_r1, $node_file_r4, 'Original revision file still in place after reverting to the original revision.');
+    $this->assertFileIsPermanent($node_file_r4, 'Original revision file still permanent after reverting to the original revision.');
+
+    // Delete the second revision and check that the file is kept (since it is
+    // still being used by the third revision).
+    $this->drupalPost('node/' . $nid . '/revisions/' . $node_vid_r2 . '/delete', array(), t('Delete'));
+    $this->assertFileExists($node_file_r3, 'Second file is still available after deleting second revision, since it is being used by the third revision.');
+    $this->assertFileEntryExists($node_file_r3, 'Second file entry is still available after deleting second revision, since it is being used by the third revision.');
+    $this->assertFileIsPermanent($node_file_r3, 'Second file entry is still permanent after deleting second revision, since it is being used by the third revision.');
+
+    // Attach the second file to a user.
+    $user = $this->drupalCreateUser();
+    $edit = (array) $user;
+    $edit[$field_name][LANGUAGE_NONE][0] = (array) $node_file_r3;
+    user_save($user, $edit);
+    $this->drupalGet('user/' . $user->uid . '/edit');
+
+    // Delete the third revision and check that the file is not deleted yet.
+    $this->drupalPost('node/' . $nid . '/revisions/' . $node_vid_r3 . '/delete', array(), t('Delete'));
+    $this->assertFileExists($node_file_r3, 'Second file is still available after deleting third revision, since it is being used by the user.');
+    $this->assertFileEntryExists($node_file_r3, 'Second file entry is still available after deleting third revision, since it is being used by the user.');
+    $this->assertFileIsPermanent($node_file_r3, 'Second file entry is still permanent after deleting third revision, since it is being used by the user.');
+
+    // Delete the user and check that the file still exists.
+    user_delete($user->uid);
+    // TODO: This seems like a bug in File API. Clearing the stat cache should
+    // not be necessary here. The file really exists, but stream wrappers
+    // doesn't seem to think so unless we clear the PHP file stat() cache.
+    clearstatcache();
+    // @todo Files referenced from entity revisions cannot currently be deleted after the entity is deleted.
+    // @see https://drupal.org/node/1613290
+    // $this->assertFileNotExists($node_file_r3, 'Second file is now deleted after deleting third revision, since it is no longer being used by any other nodes.');
+    // $this->assertFileEntryNotExists($node_file_r3, 'Second file entry is now deleted after deleting third revision, since it is no longer being used by any other nodes.');
+
+    // Delete the entire node and check that the original file is deleted.
+    $this->drupalPost('node/' . $nid . '/delete', array(), t('Delete'));
+    $this->assertFileNotExists($node_file_r1, 'Original file is deleted after deleting the entire node with two revisions remaining.');
+    $this->assertFileEntryNotExists($node_file_r1, 'Original file entry is deleted after deleting the entire node with two revisions remaining.');
+  }
+}
+
+/**
+ * Tests various validations.
+ */
+class MediaFileFieldValidateTestCase extends MediaFileFieldTestCase {
+  protected $field;
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Media file field validation tests',
+      'description' => 'Tests validation functions such as required.',
+      'group' => 'Media',
+    );
+  }
+
+  /**
+   * Tests the required property on file fields.
+   */
+  function testRequired() {
+    $type_name = 'article';
+    $field_name = strtolower($this->randomName());
+    $this->createFileField($field_name, $type_name, array(), array('required' => '1'));
+    $field = field_info_field($field_name);
+    $instance = field_info_instance('node', $field_name, $type_name);
+
+    $test_file = $this->getTestFile('text');
+    $test_file->uid = $this->admin_user->uid;
+    $test_file = file_save($test_file);
+
+    // Try to post a new node without attaching a file.
+    $langcode = LANGUAGE_NONE;
+    $edit = array("title" => $this->randomName());
+    $this->drupalPost('node/add/' . $type_name, $edit, t('Save'));
+    $this->assertRaw(t('!title field is required.', array('!title' => $instance['label'])), 'Node save failed when required file field was empty.');
+
+    // Create a new node with the attached file.
+    $nid = $this->attachNodeFile($test_file, $field_name, $type_name);
+    $this->assertTrue($nid !== FALSE, format_string('attachNodeFile(@test_file, @field_name, @type_name) succeeded', array('@test_file' => $test_file->uri, '@field_name' => $field_name, '@type_name' => $type_name)));
+
+    $node = node_load($nid, NULL, TRUE);
+
+    $node_file = (object) $node->{$field_name}[LANGUAGE_NONE][0];
+    $this->assertFileExists($node_file, 'File exists after attaching to the required field.');
+    $this->assertFileEntryExists($node_file, 'File entry exists after attaching to the required field.');
+
+    // Try again with a multiple value field.
+    field_delete_field($field_name);
+    $this->createFileField($field_name, $type_name, array('cardinality' => FIELD_CARDINALITY_UNLIMITED), array('required' => '1'));
+
+    // Try to post a new node without attaching a file in the multivalue field.
+    $edit = array('title' => $this->randomName());
+    $this->drupalPost('node/add/' . $type_name, $edit, t('Save'));
+    $this->assertRaw(t('!title field is required.', array('!title' => $instance['label'])), 'Node save failed when required multiple value file field was empty.');
+
+    // Create a new node with the attached file into the multivalue field.
+    $nid = $this->attachNodeFile($test_file, $field_name, $type_name);
+    $node = node_load($nid, NULL, TRUE);
+    $node_file = (object) $node->{$field_name}[LANGUAGE_NONE][0];
+    $this->assertFileExists($node_file, 'File exists after attaching to the required multiple value field.');
+    $this->assertFileEntryExists($node_file, 'File entry exists after attaching to the required multipel value field.');
+
+    // Remove our file field.
+    field_delete_field($field_name);
+  }
+}
+
+/**
+ * Tests that formatters are working properly.
+ */
+class MediaFileFieldDisplayTestCase extends MediaFileFieldTestCase {
+  public static function getInfo() {
+    return array(
+      'name' => 'Media file field display tests',
+      'description' => 'Test the display of file fields in node and views.',
+      'group' => 'Media',
+    );
+  }
+
+  /**
+   * Tests normal formatter display on node display.
+   */
+  function testNodeDisplay() {
+    $field_name = strtolower($this->randomName());
+    $type_name = 'article';
+    $field_settings = array(
+      'display_field' => '1',
+      'display_default' => '1',
+    );
+    $instance_settings = array(
+      'description_field' => '1',
+    );
+    $widget_settings = array();
+    $this->createFileField($field_name, $type_name, $field_settings, $instance_settings, $widget_settings);
+    $field = field_info_field($field_name);
+    $instance = field_info_instance('node', $field_name, $type_name);
+
+    // Create a new node *without* the file field set, and check that the field
+    // is not shown for each node display.
+    $node = $this->drupalCreateNode(array('type' => $type_name));
+    $file_formatters = array('file_default', 'file_table', 'file_url_plain', 'hidden');
+    foreach ($file_formatters as $formatter) {
+      $edit = array(
+        "fields[$field_name][type]" => $formatter,
+      );
+      $this->drupalPost("admin/structure/types/manage/$type_name/display", $edit, t('Save'));
+      $this->drupalGet('node/' . $node->nid);
+      $this->assertNoText($field_name, format_string('Field label is hidden when no file attached for formatter %formatter', array('%formatter' => $formatter)));
+    }
+
+    $test_file = $this->getTestFile('text');
+    $test_file->uid = $this->admin_user->uid;
+    $test_file = file_save($test_file);
+
+    // Create a new node with the attached file.
+    $nid = $this->attachNodeFile($test_file, $field_name, $type_name);
+    $this->drupalGet('node/' . $nid . '/edit');
+
+    // Check that the media thumbnail is displaying with the file name.
+    $node = node_load($nid, NULL, TRUE);
+    $node_file = (object) $node->{$field_name}[LANGUAGE_NONE][0];
+    $thumbnail = media_get_thumbnail_preview($node_file);
+    $default_output = drupal_render($thumbnail);
+    $this->assertRaw($default_output, 'Default formatter displaying correctly on full node view.');
+
+    // Turn the "display" option off and check that the file is no longer displayed.
+    $edit = array($field_name . '[' . LANGUAGE_NONE . '][0][display]' => FALSE);
+    $this->drupalPost('node/' . $nid . '/edit', $edit, t('Save'));
+
+    $this->assertNoRaw($default_output, 'Field is hidden when "display" option is unchecked.');
+
   }
 }
diff --git a/drupal7/sites/all/modules/media/tests/media_module_test.info b/drupal7/sites/all/modules/media/tests/media_module_test.info
new file mode 100644
index 00000000..6e5b5416
--- /dev/null
+++ b/drupal7/sites/all/modules/media/tests/media_module_test.info
@@ -0,0 +1,12 @@
+name = Media test
+description = Provides hooks for testing Media module functionality.
+package = Media
+core = 7.x
+hidden = TRUE
+
+; Information added by Drupal.org packaging script on 2014-10-04
+version = "7.x-2.0-alpha4"
+core = "7.x"
+project = "media"
+datestamp = "1412422430"
+
diff --git a/drupal7/sites/all/modules/media/tests/media_module_test.module b/drupal7/sites/all/modules/media/tests/media_module_test.module
new file mode 100644
index 00000000..d4add679
--- /dev/null
+++ b/drupal7/sites/all/modules/media/tests/media_module_test.module
@@ -0,0 +1,64 @@
+<?php
+
+/**
+ * @file
+ * Provides Media module pages for testing purposes.
+ */
+
+/**
+ * Implements hook_menu().
+ */
+function media_module_test_menu() {
+  $items = array();
+
+  $items['media/test'] = array(
+    'title' => 'Media test',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('media_module_test_form'),
+    'access arguments' => array('view files'),
+  );
+
+  return $items;
+}
+
+/**
+ * Form constructor for testing a 'media' element.
+ *
+ * @see media_module_test_form_submit()
+ * @ingroup forms
+ */
+function media_module_test_form($form, &$form_state, $tree = TRUE, $extended = FALSE) {
+  $form['#tree'] = (bool) $tree;
+
+  $form['nested']['media'] = array(
+    '#type' => 'media',
+    '#title' => t('Media'),
+    '#extended' => (bool) $extended,
+    '#size' => 13,
+  );
+
+  $form['textfield'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Type a value and ensure it stays'),
+  );
+
+  $form['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Save'),
+  );
+
+  return $form;
+}
+
+/**
+ * Form submission handler for media_module_test_form().
+ */
+function media_module_test_form_submit($form, &$form_state) {
+  if ($form['#tree']) {
+    $fid = $form['nested']['media']['#extended'] ? $form_state['values']['nested']['media']['fid'] : $form_state['values']['nested']['media'];
+  }
+  else {
+    $fid = $form['nested']['media']['#extended'] ? $form_state['values']['media']['fid'] : $form_state['values']['media'];
+  }
+  drupal_set_message(t('The file id is %fid.', array('%fid' => $fid)));
+}
diff --git a/drupal7/sites/all/modules/media/views/media_default.view.inc b/drupal7/sites/all/modules/media/views/media_default.view.inc
index e66ed112..54074650 100644
--- a/drupal7/sites/all/modules/media/views/media_default.view.inc
+++ b/drupal7/sites/all/modules/media/views/media_default.view.inc
@@ -28,9 +28,9 @@ $handler->display->display_options['query']['options']['query_tags'] = array(
   0 => 'media_browser',
 );
 $handler->display->display_options['exposed_form']['type'] = 'basic';
-$handler->display->display_options['exposed_form']['options']['autosubmit'] = TRUE;
+$handler->display->display_options['exposed_form']['options']['reset_button'] = FALSE;
 $handler->display->display_options['pager']['type'] = 'full';
-$handler->display->display_options['pager']['options']['items_per_page'] = '10';
+$handler->display->display_options['pager']['options']['items_per_page'] = '25';
 $handler->display->display_options['pager']['options']['offset'] = '0';
 $handler->display->display_options['pager']['options']['id'] = '0';
 $handler->display->display_options['style_plugin'] = 'media_browser';
@@ -39,7 +39,7 @@ $handler->display->display_options['empty']['area']['id'] = 'area';
 $handler->display->display_options['empty']['area']['table'] = 'views';
 $handler->display->display_options['empty']['area']['field'] = 'area';
 $handler->display->display_options['empty']['area']['content'] = 'No files available.';
-$handler->display->display_options['empty']['area']['format'] = 'plain_text';
+$handler->display->display_options['empty']['area']['format'] = filter_fallback_format();
 /* Field: File: Name */
 $handler->display->display_options['fields']['filename']['id'] = 'filename';
 $handler->display->display_options['fields']['filename']['table'] = 'file_managed';
diff --git a/drupal7/sites/all/modules/media/wysiwyg_plugins/media.inc b/drupal7/sites/all/modules/media/wysiwyg_plugins/media.inc
deleted file mode 100644
index d90b79f4..00000000
--- a/drupal7/sites/all/modules/media/wysiwyg_plugins/media.inc
+++ /dev/null
@@ -1,91 +0,0 @@
-<?php
-
-/**
- * @file
- * Define the WYSIWYG browser plugin.
- */
-
-/**
- * Implements WYSIWYG's hook_INCLUDE_plugin().
- */
-function media_media_plugin() {
-  // Include the required browser JS.
-  // @todo: wyswiyg should allow libraries and multiple js files
-  // to be defined by this hook.
-  // @see http://drupal.org/node/1039076
-  media_include_browser_js();
-
-  // Add the filter handling.
-  drupal_add_js(drupal_get_path('module', 'media') . '/js/media.filter.js');
-
-  // Plugin definition.
-  $plugins['media'] = array(
-    'title' => variable_get('media__wysiwyg_title', t('Media browser')),
-    'vendor url' => 'http://drupal.org/project/media',
-    'icon path' => drupal_get_path('module', 'media') . '/images',
-    'icon file' => 'wysiwyg-media.gif',
-    'icon title' => variable_get('media__wysiwyg_icon_title', t('Add media')),
-    // @todo: move this to the plugin directory for the wysiwyg plugin.
-    'js path' => drupal_get_path('module', 'media') . '/js',
-    'js file' => 'wysiwyg-media.js',
-    'css file' => NULL,
-    'css path' => NULL,
-    'settings' => array(
-      'global' => array(
-        'enabledPlugins' => variable_get('media__wysiwyg_browser_plugins', array()),
-        'file_directory' => variable_get('media__wysiwyg_upload_directory', ''),
-        'types' => variable_get('media__wysiwyg_allowed_types', array('audio', 'image', 'video', 'document')),
-        'id' => 'media_wysiwyg',
-      ),
-    ),
-  );
-
-  return $plugins;
-}
-
-/**
- * Prepares the page to be able to launch the media browser.
- *
- * Defines default variables.
- */
-function media_include_browser_js() {
-  static $included;
-  if ($included) {
-    return;
-  }
-  $included = TRUE;
-  module_load_include('inc', 'media', 'includes/media.browser');
-  $javascript = media_browser_js();
-  foreach ($javascript as $key => $definitions) {
-    foreach ($definitions as $definition) {
-      $function = 'drupal_add_' . $key;
-      // Since the arguments to pass are variable, use call_user_func_array().
-      // This will not handle all potential drupal_add_*() functions directly
-      // but covers the js and library needed here, which are unlikely to be
-      // expanded since this function is only a workaround for a wysiwyg
-      // limitation.
-      call_user_func_array($function, $definition);
-    }
-  }
-  // Add wysiwyg-specific settings.
-  $settings = array('wysiwyg_allowed_attributes' => variable_get('media__wysiwyg_allowed_attributes', array('height', 'width', 'hspace', 'vspace', 'border', 'align', 'style', 'class', 'id', 'usemap', 'data-picture-group', 'data-picture-align')));
-  drupal_add_js(array('media' => $settings), 'setting');
-}
-
-/**
- * Element validate callback for the media WYSIWYG button.
- */
-function media_wysiwyg_button_element_validate($element, &$form_state) {
-  if (!empty($element['#value'])) {
-    $format = filter_format_load($form_state['build_info']['args'][0]->format);
-    $filters = filter_list_format($format->format);
-    if (empty($filters['media_filter']->status)) {
-      form_error($element, t('The <em>Convert Media tags to markup</em> filter must be enabled for the <a href="@format-link">@format format</a> in order to use the Media browser WYSIWYG button.', array(
-        '@format-link' => url('admin/config/content/formats/' . $format->format, array('query' => array('destination' => $_GET['q']))),
-        '@format' => $format->name,
-      )));
-    }
-  }
-
-  return $element;
-}
diff --git a/drupal7/sites/all/modules/webform/components/date.inc b/drupal7/sites/all/modules/webform/components/date.inc
index 7a0a8b88..07a1322c 100644
--- a/drupal7/sites/all/modules/webform/components/date.inc
+++ b/drupal7/sites/all/modules/webform/components/date.inc
@@ -166,6 +166,10 @@ function webform_expand_date($element) {
     $timestring = webform_strtodate('c', $element['#default_value'], $timezone);
     $element['#default_value'] = webform_date_array($timestring, 'date');
   }
+  // Prevent an error in PHP 5.4 caused by core's treatment of the #value.
+  if (isset($element['#value'])) {
+    unset($element['#value']);
+  }
 
   // Set defaults according to existing #default_value (set by Form API)
   if (isset($element['#default_value']['month']) || isset($element['#default_value']['day']) || isset($element['#default_value']['year'])) {
diff --git a/drupal7/sites/all/modules/webform/components/fieldset.inc b/drupal7/sites/all/modules/webform/components/fieldset.inc
index eddc3b90..63ad33a1 100644
--- a/drupal7/sites/all/modules/webform/components/fieldset.inc
+++ b/drupal7/sites/all/modules/webform/components/fieldset.inc
@@ -74,7 +74,7 @@ function _webform_render_fieldset($component, $value = NULL, $filter = TRUE) {
  * Pre-render function to set a fieldset ID.
  */
 function webform_fieldset_prerender($element) {
-  $element['#id'] = drupal_html_id('webform-component-' . str_replace('_', '-', implode('--', array_slice($element['#parents'], 1))));
+  $element['#id'] = 'webform-component-' . str_replace('_', '-', implode('--', array_slice($element['#parents'], 1)));
   return $element;
 }
 
diff --git a/drupal7/sites/all/modules/webform/components/file.inc b/drupal7/sites/all/modules/webform/components/file.inc
index 7f46e1ce..561c0754 100644
--- a/drupal7/sites/all/modules/webform/components/file.inc
+++ b/drupal7/sites/all/modules/webform/components/file.inc
@@ -212,7 +212,7 @@ function _webform_edit_file_check_directory($element) {
   $scheme = $element['extra']['scheme']['#value'];
   $directory = $element['extra']['directory']['#value'];
 
-  $destination_dir = file_stream_wrapper_uri_normalize($scheme . '://' . $directory . '/webform');
+  $destination_dir = file_stream_wrapper_uri_normalize($scheme . '://webform/' . $directory);
 
   // Sanity check input to prevent use parent (../) directories.
   if (preg_match('/\.\.[\/\\\]/', $destination_dir . '/')) {
diff --git a/drupal7/sites/all/modules/webform/components/markup.inc b/drupal7/sites/all/modules/webform/components/markup.inc
index 9bb628b6..100a8602 100644
--- a/drupal7/sites/all/modules/webform/components/markup.inc
+++ b/drupal7/sites/all/modules/webform/components/markup.inc
@@ -66,9 +66,6 @@ function _webform_render_markup($component, $value = NULL, $filter = TRUE) {
     '#translatable' => array('title', 'markup'),
   );
 
-  // TODO: Remove when #markup becomes available in D7.
-  $element['#value'] = $element['#markup'];
-
   return $element;
 }
 
diff --git a/drupal7/sites/all/modules/webform/components/number.inc b/drupal7/sites/all/modules/webform/components/number.inc
index 6b0391bb..16152f11 100644
--- a/drupal7/sites/all/modules/webform/components/number.inc
+++ b/drupal7/sites/all/modules/webform/components/number.inc
@@ -276,9 +276,17 @@ function _webform_render_number($component, $value = NULL, $filter = TRUE) {
     '#max' => $component['extra']['max'],
     '#step' => $component['extra']['step'] ? abs($component['extra']['step']) : '',
     '#integer' => $component['extra']['integer'],
-    '#translatable' => array('title', 'description'),
+    '#point' => $component['extra']['point'],
+    '#separator' => $component['extra']['separator'],
+    '#decimals' => $component['extra']['decimals'],
+    '#translatable' => array('title', 'description', 'field_prefix', 'field_suffix'),
   );
 
+  // Set the decimal count to zero for integers.
+  if ($element['#integer'] && $element['#decimals'] === '') {
+    $element['#decimals'] = 0;
+  }
+
   // Flip the min and max properties to make min less than max if needed.
   if ($element['#min'] !== '' && $element['#max'] !== '' && $element['#min'] > $element['#max']) {
     $max = $element['#min'];
@@ -318,7 +326,15 @@ function _webform_render_number($component, $value = NULL, $filter = TRUE) {
 
   // Set user-entered values.
   if (isset($value[0])) {
-    $element['#default_value'] = $value[0];
+    // If the value has been standardized, convert it to the expected format
+    // for display to the user.
+    if (webform_number_format_match($value[0], '.', '')) {
+      $element['#default_value'] = _webform_number_format($component, $value[0]);
+    }
+    // Otherwise use the user-defined input.
+    else {
+      $element['#default_value'] = $value[0];
+    }
   }
 
   // Enforce uniqueness.
@@ -385,28 +401,17 @@ function _webform_analysis_number($component, $sids = array(), $single = FALSE)
 
   $population = array();
   $submissions = 0;
-  $nonzero = 0;
-  $not_empty = 0;
+  $non_zero = 0;
+  $non_empty = 0;
   $sum = 0;
 
   $result = $query->execute();
   foreach ($result as $data) {
     $value = trim($data['data']);
-    if ($value == '') {
-      $number = 0.0;
-    }
-    else {
-      $number = $value * 1.0;
-    }
-
-    if ($value !== '') {
-      $not_empty++;
-    }
-
-    if ($number > 0) {
-      $nonzero++;
-      $sum += $number;
-    }
+    $number = (float)$value;
+    $non_empty += (integer)($value !== '');
+    $non_zero += (integer)($number != 0.0);
+    $sum += $number;
     $population[] = $number;
     $submissions++;
   }
@@ -414,10 +419,10 @@ function _webform_analysis_number($component, $sids = array(), $single = FALSE)
 
   // Average and population count.
   if ($component['extra']['excludezero']) {
-    $average = $nonzero ? ($sum / $nonzero) : 0;
+    $average = $non_zero ? ($sum / $non_zero) : 0;
     $average_title = t('Average !mu excluding zeros/blanks', array('!mu' => $advanced_stats ? '(&mu;)' : ''));
     // Sample (sub-set of total population).
-    $population_count = $nonzero - 1;
+    $population_count = $non_zero - 1;
     $sigma = 'sd';
     $description = t('sample');
   }
@@ -434,8 +439,8 @@ function _webform_analysis_number($component, $sids = array(), $single = FALSE)
   $average = _webform_number_format($component, $average);
   $sum = _webform_number_format($component, $sum);
 
-  $rows[0] = array(t('Zero/blank'), ($submissions - $nonzero));
-  $rows[1] = array(t('User entered value'), $not_empty);
+  $rows[0] = array(t('Zero/blank'), ($submissions - $non_zero));
+  $rows[1] = array(t('User entered value'), $non_empty);
   $rows[2] = array(t('Sum') . ($advanced_stats ? ' (&Sigma;)' : ''), $sum);
   $rows[3] = array($average_title, $average);
 
@@ -561,12 +566,20 @@ function _webform_csv_data_number($component, $export_options, $value) {
  *   None. Calls a form_set_error if the number is not valid.
  */
 function _webform_validate_number($element, &$form_state) {
+  // Trim spaces for basic cleanup.
   $value = trim($element['#value']);
   form_set_value($element, $value, $form_state);
 
   if ($value != '') {
+    // First check that the entered value matches the expected value.
+    if (!webform_number_format_match($value, $element['#point'], $element['#separator'])) {
+      form_error($element, t('%name field value must format numbers as "@example".', array('%name' => $element['#title'], '@example' => webform_number_format(12345.6789, $element['#decimals'], $element['#point'], $element['#separator']))));
+      return;
+    }
+
     // Numeric test.
-    if (is_numeric($value)) {
+    $numeric_value = webform_number_standardize($value, $element['#point']);
+    if (is_numeric($numeric_value)) {
       // Range test.
       if ($element['#min'] != '' && $element['#max'] != '') {
         // Flip minimum and maximum if needed.
@@ -578,25 +591,25 @@ function _webform_validate_number($element, &$form_state) {
           $min = $element['#max'];
           $max = $element['#min'];
         }
-        if ($value > $max || $value < $min) {
-          form_error($element, t('%name field value of @value should be in the range @min to @max.', array('%name' => $element['#title'], '@value' => $value, '@min' => $min, '@max' => $max)));
+        if ($numeric_value > $max || $numeric_value < $min) {
+          form_error($element, t('%name field value of @value should be in the range @min to @max.', array('%name' => $element['#title'], '@value' => $value, '@min' => $element['#min'], '@max' => $element['#max'])));
         }
       }
-      elseif ($element['#max'] != '' && $value > $element['#max']) {
+      elseif ($element['#max'] != '' && $numeric_value > $element['#max']) {
         form_error($element, t('%name field value must be less than @max.', array('%name' => $element['#title'], '@max' => $element['#max'])));
       }
-      elseif ($element['#min'] != '' && $value < $element['#min']) {
+      elseif ($element['#min'] != '' && $numeric_value < $element['#min']) {
         form_error($element, t('%name field value must be greater than @min.', array('%name' => $element['#title'], '@min' => $element['#min'])));
       }
 
       // Integer test.
-      if ($element['#integer'] && !is_int($value * 1)) {
+      if ($element['#integer'] && !is_int($numeric_value * 1)) {
         form_error($element, t('%name field value of @value must be an integer.', array('%name' => $element['#title'], '@value' => $value)));
       }
 
       // Step test.
       $starting_number = $element['#min'] ? $element['#min'] : 0;
-      if ($element['#step'] != 0 && webform_modulo($element['#value'] - $starting_number, $element['#step']) != 0) {
+      if ($element['#step'] != 0 && webform_modulo($numeric_value - $starting_number, $element['#step']) != 0) {
         $samples = array(
           $starting_number,
           $starting_number + ($element['#step'] * 1),
@@ -615,7 +628,20 @@ function _webform_validate_number($element, &$form_state) {
       form_error($element, t('%name field value of @value must be numeric.', array('%name' => $element['#title'], '@value' => $value)));
     }
   }
+}
 
+/**
+ * Implements _webform_submit_component().
+ */
+function _webform_submit_number($component, $value) {
+  // Because _webform_validate_number() ensures the format matches when moving
+  // forward through a form, this should always pass before saving into the
+  // database. When moving backwards in a form, do not adjust the value, since
+  // it has not yet been validated.
+  if (webform_number_format_match($value, $component['extra']['point'], $component['extra']['separator'])) {
+    $value = webform_number_standardize($value, $component['extra']['point']);
+  }
+  return $value;
 }
 
 /**
@@ -721,15 +747,38 @@ function _webform_number_select_options($component) {
 }
 
 /**
- * Apply number format.
+ * Apply number format based on a component and number value.
  */
 function _webform_number_format($component, $value) {
+  return webform_number_format($value, $component['extra']['decimals'], $component['extra']['point'], $component['extra']['separator']);
+}
+
+/**
+ * Validates if a provided number string matches an expected format.
+ *
+ * This function allows the thousands separator to be optional, but decimal
+ * points must be in the right location.
+ *
+ * Based on http://stackoverflow.com/questions/5917082/regular-expression-to-match-numbers-with-or-without-commas-and-decimals-in-text.
+ */
+function webform_number_format_match($value, $point, $separator) {
+  return preg_match('/^(-? ?[1-9](?:\d{0,2})(?:' . ($separator ? (preg_quote($separator, '/') . '?') : '') . '\d{3})*(?:' . preg_quote($point, '/') . '\d*[0-9])?|0?' . preg_quote($point, '/') . '\d*[1-9]|0)$/', $value);
+}
+
+/**
+ * Format a number with thousands separator, decimal point, and decimal places.
+ *
+ * This function is a wrapper around PHP's native number_format(), but allows
+ * the decimal places parameter to be NULL or an empty string, resulting in a
+ * behavior of no change to the decimal places.
+ */
+function webform_number_format($value, $decimals = NULL, $point = '.', $separator = ',') {
   if (!is_numeric($value)) {
     return '';
   }
+
   // If no decimal places are specified, do a best guess length of decimals.
-  $decimals = $component['extra']['decimals'];
-  if ($decimals === '') {
+  if (is_null($decimals) || $decimals === '') {
     // If it's an integer, no decimals needed.
     if (is_int(($value . '') * 1)) {
       $decimals = 0;
@@ -742,7 +791,23 @@ function _webform_number_format($component, $value) {
     }
   }
 
-  return number_format($value, $decimals, $component['extra']['point'], $component['extra']['separator']);
+  return number_format($value, $decimals, $point, $separator);
+}
+
+/**
+ * Given a number, convert it to string compatible with a PHP float.
+ *
+ * @param string $value
+ *   The string value to be standardized into a numeric string.
+ * @param $point
+ *   The point separator between the whole number and the decimals.
+ */
+function webform_number_standardize($value, $point) {
+  // For simplicity, strip everything that's not the decimal point.
+  $value = preg_replace('/[^\-0-9' . preg_quote($point, '/') . ']/', '', $value);
+  // Convert the decimal point to a period.
+  $value = str_replace($point, '.', $value);
+  return $value;
 }
 
 /**
diff --git a/drupal7/sites/all/modules/webform/includes/webform.report.inc b/drupal7/sites/all/modules/webform/includes/webform.report.inc
index 56a29db9..1117b8ff 100644
--- a/drupal7/sites/all/modules/webform/includes/webform.report.inc
+++ b/drupal7/sites/all/modules/webform/includes/webform.report.inc
@@ -730,12 +730,13 @@ function webform_results_export($node, $format = 'delimited', $options = array()
       // Let each component determine its headers.
       if (webform_component_feature($component['type'], 'csv')) {
         $component_header = (array) webform_component_invoke($component['type'], 'csv_headers', $component, $options);
+        // Allow modules to modify the component CSV header.
+        drupal_alter('webform_csv_header', $component_header, $component);
+
+        // Merge component CSV header to overall CSV header
         $header[0] = array_merge($header[0], (array) $component_header[0]);
         $header[1] = array_merge($header[1], (array) $component_header[1]);
         $header[2] = array_merge($header[2], (array) $component_header[2]);
-
-        // Allow modules to modify the CSV header.
-        drupal_alter('webform_csv_header', $component_header, $component);
       }
     }
   }
diff --git a/drupal7/sites/all/modules/webform/includes/webform.submissions.inc b/drupal7/sites/all/modules/webform/includes/webform.submissions.inc
index 433914af..16bb1db6 100644
--- a/drupal7/sites/all/modules/webform/includes/webform.submissions.inc
+++ b/drupal7/sites/all/modules/webform/includes/webform.submissions.inc
@@ -463,7 +463,7 @@ function webform_submission_resend($form, $form_state, $node, $submission) {
     );
 
     $form['actions'] = array('#type' => 'actions');
-    $form['actions']['resend'] = array(
+    $form['actions']['submit'] = array(
       '#type' => 'submit',
       '#value' => t('Resend e-mails'),
     );
diff --git a/drupal7/sites/all/modules/webform/js/select-admin.js b/drupal7/sites/all/modules/webform/js/select-admin.js
index cdc00324..a9830afa 100644
--- a/drupal7/sites/all/modules/webform/js/select-admin.js
+++ b/drupal7/sites/all/modules/webform/js/select-admin.js
@@ -48,7 +48,7 @@ Drupal.webform.selectOptionsLoad = function(result) {
       $('#' + result.elementId).val(result.options).attr('readonly', 'readonly');
     }
     else {
-      $('#' + result.elementId).attr('readonly', '');
+      $('#' + result.elementId).removeAttr('readonly');
     }
   }
 }
diff --git a/drupal7/sites/all/modules/webform/webform.api.php b/drupal7/sites/all/modules/webform/webform.api.php
index 9142ee44..73ec89d1 100644
--- a/drupal7/sites/all/modules/webform/webform.api.php
+++ b/drupal7/sites/all/modules/webform/webform.api.php
@@ -770,10 +770,9 @@ function _webform_submit_component($component, $value) {
  */
 function _webform_delete_component($component, $value) {
   // Delete corresponding files when a submission is deleted.
-  $filedata = unserialize($value['0']);
-  if (isset($filedata['filepath']) && is_file($filedata['filepath'])) {
-    unlink($filedata['filepath']);
-    db_query("DELETE FROM {files} WHERE filepath = '%s'", $filedata['filepath']);
+  if (!empty($value[0]) && ($file = webform_get_file($value[0]))) {
+    file_usage_delete($file, 'webform');
+    file_delete($file);
   }
 }
 
diff --git a/drupal7/sites/all/modules/webform/webform.info b/drupal7/sites/all/modules/webform/webform.info
index c11a5dcc..cc25c6b2 100644
--- a/drupal7/sites/all/modules/webform/webform.info
+++ b/drupal7/sites/all/modules/webform/webform.info
@@ -24,9 +24,9 @@ files[] = tests/permissions.test
 files[] = tests/submission.test
 files[] = tests/webform.test
 
-; Information added by Drupal.org packaging script on 2014-02-12
-version = "7.x-3.20"
+; Information added by Drupal.org packaging script on 2014-10-07
+version = "7.x-3.21"
 core = "7.x"
 project = "webform"
-datestamp = "1392182305"
+datestamp = "1412682050"
 
diff --git a/drupal7/sites/all/modules/webform/webform.module b/drupal7/sites/all/modules/webform/webform.module
index d8066843..2e7f3c8e 100644
--- a/drupal7/sites/all/modules/webform/webform.module
+++ b/drupal7/sites/all/modules/webform/webform.module
@@ -151,21 +151,19 @@ function webform_menu() {
     'type' => MENU_LOCAL_TASK,
   );
   $items['node/%webform_menu/webform/emails/%webform_menu_email'] = array(
-    'title' => 'Edit e-mail settings',
     'load arguments' => array(1),
     'page arguments' => array('webform_email_edit_form', 1, 4),
     'access callback' => 'node_access',
     'access arguments' => array('update', 1),
     'file' => 'includes/webform.emails.inc',
-    'type' => MENU_LOCAL_TASK,
+    'type' => MENU_CALLBACK,
   );
   $items['node/%webform_menu/webform/emails/%webform_menu_email/delete'] = array(
-    'title' => 'Delete e-mail settings',
     'load arguments' => array(1),
     'page arguments' => array('webform_email_delete_form', 1, 4),
     'access callback' => 'node_access',
     'access arguments' => array('update', 1),
-    'type' => MENU_LOCAL_TASK,
+    'type' => MENU_CALLBACK,
   );
 
   // Node component forms.
@@ -1010,6 +1008,7 @@ function webform_webform_submission_render_alter(&$renderable) {
   // are being displayed.
   $node = $renderable['#node'];
   $is_admin = webform_results_access($node);
+  module_load_include('inc', 'webform', 'includes/webform.components');
   if (empty($renderable['#email']) && !$is_admin) {
     // Find and hide the display of all hidden components.
     foreach ($node->webform['components'] as $cid => $component) {
@@ -2086,11 +2085,6 @@ function _webform_client_form_rule_check($node, $component, $page_num, $form_sta
     }
   }
 
-  // Private component?
-  if ($component['extra']['private']) {
-    $show_component = webform_results_access($node);
-  }
-
   return $show_component;
 }
 
@@ -2126,12 +2120,16 @@ function _webform_client_form_rule_check($node, $component, $page_num, $form_sta
  */
 function _webform_client_form_add_component($node, $component, $component_value, &$parent_fieldset, &$form, $form_state, $submission, $format = 'form', $page_num = 0, $filter = TRUE) {
   $cid = $component['cid'];
+  $component_access = empty($component['extra']['private']) || webform_results_access($node);
 
   // Load with submission information if necessary.
   if ($format != 'form') {
     // This component is display only.
     $data = empty($submission->data[$cid]['value']) ? NULL : $submission->data[$cid]['value'];
     if ($display_element = webform_component_invoke($component['type'], 'display', $component, $data, $format)) {
+      // Set access based on the private property.
+      $element['#access'] = $component_access;
+
       // Ensure the component is added as a property.
       $display_element['#webform_component'] = $component;
 
@@ -2159,6 +2157,9 @@ function _webform_client_form_add_component($node, $component, $component_value,
     // Add this user-defined field to the form (with all the values that are always available).
     $data = isset($submission->data[$cid]['value']) ? $submission->data[$cid]['value'] : NULL;
     if ($element = webform_component_invoke($component['type'], 'render', $component, $data, $filter)) {
+      // Set access based on the private property.
+      $element['#access'] = $component_access;
+
       // Ensure the component is added as a property.
       $element['#webform_component'] = $component;
 
@@ -2709,6 +2710,12 @@ function theme_webform_element($variables) {
   }
   $output = '<div class="' . implode(' ', $wrapper_classes) . '" id="webform-component-' . $parents . '">' . "\n";
 
+  // If #title_display is none, set it to invisible instead - none only used if
+  // we have no title at all to use.
+  if ($element['#title_display'] == 'none') {
+    $variables['element']['#title_display'] = 'invisible';
+    $element['#title_display'] = 'invisible';
+  }
   // If #title is not set, we don't display any label or required marker.
   if (!isset($element['#title'])) {
     $element['#title_display'] = 'none';
@@ -3359,6 +3366,7 @@ function webform_format_email_address($address, $name, $node = NULL, $submission
     if ($encode) {
       $name = mime_header_encode($name);
     }
+    $name = trim($name);
     return '"' . $name . '" <' . $address . '>';
   }
   else {
@@ -3769,13 +3777,20 @@ function webform_tt($name, $string, $langcode = NULL, $update = FALSE) {
 function webform_email_html_capable() {
   // TODO: Right now we only support MIME Mail and HTML Mail. Support others
   // if available through a hook?
-  if (module_exists('mimemail')) {
-    $mail_systems = variable_get('mail_system', array('default-system' => 'DefaultMailSystem'));
-    $enable = (!isset($mail_systems['webform']) || $mail_systems['webform'] == 'MimeMailSystem') ? 'MimeMailSystem' : FALSE;
-  }
-  elseif (module_exists('htmlmail')) {
-    $mail_systems = variable_get('mail_system', array('default-system' => 'DefaultMailSystem'));
-    $enable = (!isset($mail_systems['webform']) || $mail_systems['webform'] == 'HTMLMailSystem') ? 'HTMLMailSystem' : FALSE;
+  $supported_html_modules = array(
+    'mimemail' => 'MimeMailSystem',
+    'htmlmail' => 'HTMLMailSystem',
+  );
+  foreach ($supported_html_modules as $mail_module => $mail_system_name) {
+    if (module_exists($mail_module)) {
+      $mail_systems = variable_get('mail_system', array('default-system' => 'DefaultMailSystem'));
+      if (isset($mail_systems['webform'])) {
+        $enable = strpos($mail_systems['webform'], $mail_system_name) !== FALSE ? $mail_systems['webform'] : FALSE;
+      }
+      else {
+        $enable = $mail_system_name;
+      }
+    }
   }
   if (!empty($enable)) {
     // We assume that if a solution exists even if it's not specified we should
