diff --git a/imagefield_zip.admin.inc b/imagefield_zip.admin.inc
index 93bc45c..07df690 100755
--- a/imagefield_zip.admin.inc
+++ b/imagefield_zip.admin.inc
@@ -6,7 +6,7 @@
  */
 
 /**
- * Page generation fucntion for admin/settings/imageinfo-cache
+ * Page generation function for admin/settings/imageinfo-cache
  */
 function imagefield_zip_admin_page() {
   $output = '';
@@ -20,28 +20,103 @@ function imagefield_zip_admin_form($form_state) {
   $form = array();
 
   foreach (content_types() as $node_type => $info) {
-    $node_type = check_plain($node_type);
     foreach ($info['fields'] as $field_name => $data) {
-      $field_name = check_plain($field_name);
-      if ($data['type'] == 'filefield') {
-        $form['imagefield_zip_cck_widget_' . $node_type . '_' . $field_name] = array(
-          '#type'           => 'radios',
-          '#title'          => t('%node - %field: Location of the zip upload field', array(
-            '%node' => $info['name'],
-            '%field' => $data['field_name'],
-          )),
-          '#default_value'  => variable_get('imagefield_zip_cck_widget_' . $node_type . '_' . $field_name, IMAGEFIELD_ZIP_CCK_WIDGET),
-          '#description'    => t('Link to this widget: <a href="@link">@name</a>', array(
-            '@link' => url('admin/content/node-type/' . str_replace('_', '-', $node_type) . '/fields/' . $field_name),
-            '@name' => $info['name'] . ' - ' . $data['field_name'],
-          )),
-          '#options' => array(
-            0 => t('Above Imagefield'),
-            1 => t('Below Imagefield'),
-            2 => t('Disabled'),
-          ),
-        );
+      // Skip if not a filefield
+      // not multiple fields
+      // not an imagefield widget
+      if ($data['type'] != 'filefield' || empty($data['multiple']) || $data['widget']['module'] != 'imagefield') {
+        continue;
       }
+
+      $form['imagefield_zip_' . $node_type . '_' . $field_name] = array(
+        '#type'           => 'fieldset',
+        '#title'          => t('%node - %field',array(
+          '%node' => $info['name'],
+          '%field' => $data['widget']['label'],
+        )),
+        '#description'    => t('Link to this widget: <a href="@link">@name</a>', array(
+          '@link' => url('admin/content/node-type/' . str_replace('_', '-', $node_type) . '/fields/' . $field_name),
+          '@name' => $info['type'] . ' - ' . $data['field_name'],
+        )),
+      );
+      $form['imagefield_zip_' . $node_type . '_' . $field_name]['imagefield_zip_cck_widget_' . $node_type . '_' . $field_name] = array(
+        '#type'           => 'radios',
+        '#title'          => t('Location of the zip upload field'),
+        '#default_value'  => variable_get('imagefield_zip_cck_widget_' . $node_type . '_' . $field_name, IMAGEFIELD_ZIP_CCK_WIDGET),
+        '#options' => array(
+          0 => t('Above Imagefield'),
+          1 => t('Below Imagefield'),
+          2 => t('Disabled'),
+        ),
+      );
+      $form['imagefield_zip_' . $node_type . '_' . $field_name]['imagefield_zip_upload_mode_' . $node_type . '_' . $field_name] = array(
+        '#type'           => 'radios',
+        '#title'          => t('Upload field mode'),
+        '#default_value'  => variable_get('imagefield_zip_upload_mode_' . $node_type . '_' . $field_name, IMAGEFIELD_ZIP_UPLOAD_MODE),
+        '#options' => array(
+          0 => t('Zip Files Only'),
+          1 => t('HTML 5 Multi-upload Only'),
+          2 => t('Both Zip & HTML 5'),
+        ),
+      );
+      $form['imagefield_zip_' . $node_type . '_' . $field_name]['imagefield_zip_fallback_' . $node_type . '_' . $field_name] = array(
+        '#type'           => 'radios',
+        '#title'          => t('Non HTML5 Fallback Mode'),
+        '#default_value'  => variable_get('imagefield_zip_fallback_' . $node_type . '_' . $field_name, IMAGEFIELD_ZIP_FALLBACK),
+        '#options' => array(
+          0 => t('Degrade to zip only'),
+          1 => t('Show message that your browser does not support HTML5'),
+          2 => t('Disable Multi Upload'),
+        ),
+      );
+
+      // Create javascript variable names;
+      $location_vis_function = "imagefield_zip_upload_widget_visibility_${node_type}_${field_name}";
+      $fallback_vis_function = "imagefield_zip_fallback_visibility_${node_type}_${field_name}";
+      $node_type_css = str_replace('_', '-', $node_type);
+      $field_name_css = str_replace('_', '-', $field_name);
+
+      $cck_widget = "edit-imagefield-zip-cck-widget-$node_type_css-$field_name_css-2";
+      $cck_widget_wrapper = "edit-imagefield-zip-cck-widget-$node_type_css-$field_name_css-2-wrapper";
+      $upload_mode = "edit-imagefield-zip-upload-mode-$node_type_css-$field_name_css-1";
+      $upload_mode_wrapper = "edit-imagefield-zip-upload-mode-$node_type_css-$field_name_css-1-wrapper";
+      $fallback_wrapper = "edit-imagefield-zip-fallback-$node_type_css-$field_name_css-0-wrapper";
+
+      $widget_vis = "
+// Location Radio Logic.
+function ${location_vis_function}() {
+  if ($('#${cck_widget}:checked').val() !== undefined) {
+    $('#${upload_mode_wrapper}').parent().parent().hide();
+    $('#${fallback_wrapper}').parent().parent().hide();
+  }
+  else {
+    $('#${upload_mode_wrapper}').parent().parent().show();
+    if ($('#${upload_mode}:checked').val() !== undefined) {
+      $('#${fallback_wrapper}').parent().parent().show();
+    }
+  }
+}
+$(${location_vis_function});
+
+$(function(){ $('#${cck_widget_wrapper}').parent().change(function (){
+  ${location_vis_function}();
+})});
+
+// Upload Field Logic.
+function ${fallback_vis_function}() {
+  if ($('#${upload_mode}:checked').val() !== undefined && $('#${cck_widget}:checked').val() === undefined) {
+    $('#${fallback_wrapper}').parent().parent().show();
+  }
+  else {
+    $('#${fallback_wrapper}').parent().parent().hide();
+  }
+}
+$(${fallback_vis_function});
+$(function(){ $('#${upload_mode_wrapper}').parent().change(function (){
+  ${fallback_vis_function}();
+})});
+";
+      drupal_add_js($widget_vis, 'inline', 'footer');
     }
   }
 
@@ -54,6 +129,8 @@ function imagefield_zip_admin_form($form_state) {
 function imagefield_zip_cck_widget_form(&$form, $form_state, $form_id) {
   // Get widget settings.
   $widget_settings = variable_get('imagefield_zip_cck_widget_' . $form['#field']['type_name'] . '_' . $form['#field']['field_name'], IMAGEFIELD_ZIP_CCK_WIDGET);
+  $upload_mode = variable_get('imagefield_zip_upload_mode_' . $form['#field']['type_name'] . '_' . $form['#field']['field_name'], IMAGEFIELD_ZIP_UPLOAD_MODE);
+  $fallback_mode = variable_get('imagefield_zip_fallback_' . $form['#field']['type_name'] . '_' . $form['#field']['field_name'], IMAGEFIELD_ZIP_FALLBACK);
 
   // Add in settings form.
   $form['widget']['imagefield_zip'] = array(
@@ -73,23 +150,82 @@ function imagefield_zip_cck_widget_form(&$form, $form_state, $form_id) {
       2 => t('Disabled'),
     ),
   );
+  $form['widget']['imagefield_zip']['imagefield_zip_upload_mode'] = array(
+    '#type'           => 'radios',
+    '#title'          => t('Upload field mode'),
+    '#default_value'  => $upload_mode,
+    '#options' => array(
+      0 => t('Zip Files Only'),
+      1 => t('HTML 5 Multi-upload Only'),
+      2 => t('Both Zip & HTML 5'),
+    ),
+  );
+  $form['widget']['imagefield_zip']['imagefield_zip_fallback'] = array(
+    '#type'           => 'radios',
+    '#title'          => t('Non HTML5 Fallback Mode'),
+    '#default_value'  => $fallback_mode,
+    '#options' => array(
+      0 => t('Degrade to zip only'),
+      1 => t('Show message that your browser does not support HTML5'),
+      2 => t('Disable Multi Upload'),
+    ),
+  );
 
   // Add in submit handler.
   if (!in_array('imagefield_zip_cck_widget_form_submit', $form['#submit'])) {
     $form['#submit'][] = 'imagefield_zip_cck_widget_form_submit';
   }
 
+  $widget_vis = "
+// Location Radio Logic.
+function imagefield_zip_upload_widget_visibility() {
+  if ($('#edit-imagefield-zip-location-2:checked').val() !== undefined) {
+    $('#edit-imagefield-zip-upload-mode-0-wrapper').parent().parent().hide();
+    $('#edit-imagefield-zip-fallback-0-wrapper').parent().parent().hide();
+  }
+  else {
+    $('#edit-imagefield-zip-upload-mode-0-wrapper').parent().parent().show();
+    if ($('#edit-imagefield-zip-upload-mode-1:checked').val() !== undefined) {
+      $('#edit-imagefield-zip-fallback-0-wrapper').parent().parent().show();
+    }
+  }
+}
+$(imagefield_zip_upload_widget_visibility);
+$(function(){ $('#edit-imagefield-zip-location-2-wrapper').parent().change(function (){imagefield_zip_upload_widget_visibility();})});
+
+// Upload Field Logic.
+function imagefield_zip_fallback_widget_visibility() {
+  if ($('#edit-imagefield-zip-upload-mode-1:checked').val() !== undefined && $('#edit-imagefield-zip-location-2:checked').val() === undefined) {
+    $('#edit-imagefield-zip-fallback-0-wrapper').parent().parent().show();
+  }
+  else {
+    $('#edit-imagefield-zip-fallback-0-wrapper').parent().parent().hide();
+  }
+}
+$(imagefield_zip_fallback_widget_visibility);
+$(function(){ $('#edit-imagefield-zip-upload-mode-1-wrapper').parent().change(function (){imagefield_zip_fallback_widget_visibility();})});
+";
+  drupal_add_js($widget_vis, 'inline');
 }
 
 /**
  * Implements hook_form_submit().
  */
 function imagefield_zip_cck_widget_form_submit($form, &$form_state) {
-  if (!isset($form_state['values']['imagefield_zip_location'])) {
+  if (   !isset($form_state['values']['imagefield_zip_location'])
+      && !isset($form_state['values']['imagefield_zip_upload_mode'])
+      && !isset($form_state['values']['imagefield_zip_fallback'])
+        ) {
     return;
   }
 
   // Save value.
   variable_set('imagefield_zip_cck_widget_' . $form['#field']['type_name'] . '_' . $form['#field']['field_name'], (int) $form_state['values']['imagefield_zip_location']);
   unset($form_state['values']['imagefield_zip_location']);
+
+  variable_set('imagefield_zip_upload_mode_' . $form['#field']['type_name'] . '_' . $form['#field']['field_name'], (int) $form_state['values']['imagefield_zip_upload_mode']);
+  unset($form_state['values']['imagefield_zip_upload_mode']);
+
+  variable_set('imagefield_zip_fallback_' . $form['#field']['type_name'] . '_' . $form['#field']['field_name'], (int) $form_state['values']['imagefield_zip_fallback']);
+  unset($form_state['values']['imagefield_zip_fallback']);
 }
diff --git a/imagefield_zip.ahah.inc b/imagefield_zip.ahah.inc
index db117e6..9be5fdc 100644
--- a/imagefield_zip.ahah.inc
+++ b/imagefield_zip.ahah.inc
@@ -10,12 +10,12 @@
  */
 function imagefield_zip_js($type_name, $field_name) {
   // Get all images from the zip field.
-  $images = imagefield_zip_save_and_extract_upload($field_name . '_zip');
+  $images = imagefield_zip_save_and_extract_upload($field_name . '_zip', $type_name);
 
   // Generate HTML for the images that where uploaded
   $result = imagefield_zip_add_files_to_form($type_name, $field_name, $images);
 
-  // Destory the orginal zip upload form and replace it with the clean clone.
+  // Destroy the original zip upload form and replace it with the clean clone.
   $id = 'edit-' . str_replace('_', '-', $field_name) . '-upload';
   $extra_js = '<script type="text/javascript">
   _imagefield_zip_' . $field_name . '_cloned.insertAfter(_imagefield_zip_' . $field_name . '_real);
@@ -147,7 +147,7 @@ function imagefield_zip_add_files_to_form($type_name, $field_name, $files) {
 
   // Let other modules alter it.
   // We pass an empty array as hook_form_alter's usual 'form_state' parameter,
-  // instead of $form_atate (for reasons we may never remember).
+  // instead of $form_state (for reasons we may never remember).
   // However, this argument is still expected to be passed by-reference
   // (and PHP5.3 will throw an error if it isn't.) This leads to:
   $data = &$form_element;
@@ -204,7 +204,7 @@ function imagefield_zip_add_files_to_form($type_name, $field_name, $files) {
   $output_js = isset($javascript['setting']) ? '<script type="text/javascript">jQuery.extend(Drupal.settings, '. drupal_to_js(call_user_func_array('array_merge_recursive', $javascript['setting'])) .');</script>' : '';
 
   // Using drupal_json() breaks filefield's file upload, because the jQuery
-  // Form plugin handles file uploads in a way that is not compatible with
+  // Form plug-in handles file uploads in a way that is not compatible with
   // 'text/javascript' response type.
   $GLOBALS['devel_shutdown'] =  FALSE;
   return $output . $output_js;
@@ -215,12 +215,12 @@ function imagefield_zip_add_files_to_form($type_name, $field_name, $files) {
  */
 function imagefield_zip_multigroup_js($type_name, $group_name) {
   // Get all images from the zip field.
-  $images = imagefield_zip_save_and_extract_upload($group_name . '_zip');
+  $images = imagefield_zip_save_and_extract_upload($group_name . '_zip', $type_name);
 
   // Generate HTML for the images that where uploaded
   $result = imagefield_zip_add_files_to_multigroup_form($type_name, $group_name, $images);
 
-  // Destory the orginal zip upload form and replace it with the clean clone.
+  // Destroy the original zip upload form and replace it with the clean clone.
   $id = 'edit-' . str_replace('_', '-', $group_name) . '-upload';
   $extra_js = '<script type="text/javascript">
   _imagefield_zip_' . $group_name . '_cloned.insertAfter(_imagefield_zip_' . $group_name . '_real);
@@ -358,7 +358,7 @@ function imagefield_zip_add_files_to_multigroup_form($type_name_url, $group_name
     $delta_element = &$form[$group_name][$delta][$target_field];
     // Put the file in the new element.
     if ($file = field_file_save_file($file->filepath, $delta_element['#upload_validators'], $dest)) {
-      // Set array perents to prevent php notices.
+      // Set array parents to prevent php notices.
       $delta_element['#array_parents'][] = $target_field;
       // Set the default value of the widget to the extracted file.
       $delta_element['#default_value'] = filefield_widget_value($delta_element, (array) $file);
@@ -408,7 +408,7 @@ function imagefield_zip_add_files_to_multigroup_form($type_name_url, $group_name
   $output_js = isset($javascript['setting']) ? '<script type="text/javascript">jQuery.extend(Drupal.settings, '. drupal_to_js(call_user_func_array('array_merge_recursive', $javascript['setting'])) .');</script>' : '';
 
   // Using drupal_json() breaks filefield's file upload, because the jQuery
-  // Form plugin handles file uploads in a way that is not compatible with
+  // Form plug-in handles file uploads in a way that is not compatible with
   // 'text/javascript' response type.
   $GLOBALS['devel_shutdown'] =  FALSE;
   return $output . $output_js;
diff --git a/imagefield_zip.install b/imagefield_zip.install
index 1342a9e..3305a83 100644
--- a/imagefield_zip.install
+++ b/imagefield_zip.install
@@ -27,6 +27,10 @@ function imagefield_zip_install() {
  * Implementation of hook_uninstall().
  */
 function imagefield_zip_uninstall() {
+  // Remove imagefield_zip_*_% variables.
+  db_query("DELETE FROM {variable} WHERE name LIKE 'imagefield_zip_cck_widget_%'");
+  db_query("DELETE FROM {variable} WHERE name LIKE 'imagefield_zip_upload_mode_%'");
+  db_query("DELETE FROM {variable} WHERE name LIKE 'imagefield_zip_fallback_%'");
 }
 
 /**
@@ -47,7 +51,7 @@ function imagefield_zip_requirements($phase) {
     }
   }
   if (empty($requirements)) {
-    $requirements['imagefield_zipn'] = array(
+    $requirements['imagefield_zip'] = array(
       'title' => $t('Zip support'),
       'value' => $t('Installed'),
     );
diff --git a/imagefield_zip.module b/imagefield_zip.module
index 3d89dd3..9fede87 100644
--- a/imagefield_zip.module
+++ b/imagefield_zip.module
@@ -8,7 +8,17 @@
 /**
  * Default location of zip upload form.
  */
-define('IMAGEFIELD_ZIP_CCK_WIDGET', 1);
+define('IMAGEFIELD_ZIP_CCK_WIDGET', 0);
+
+/**
+ * Default mode for the multi upload form.
+ */
+define('IMAGEFIELD_ZIP_UPLOAD_MODE', 0);
+
+/**
+ * Default fallback mode for non html 5 browsers.
+ */
+define('IMAGEFIELD_ZIP_FALLBACK', 0);
 
 /**
  * Implementation of hook_menu().
@@ -87,12 +97,6 @@ function imagefield_zip_form_alter(&$form, &$form_state, $form_id) {
 }
 
 /**
- * Implementation of hook_form_validate().
- */
-function _imagefield_zip_element_validate(&$element, &$form_state) {
-}
-
-/**
  * After_build function to modify CCK fields
  */
 function _imagefield_zip_form_after_build(&$form, &$form_state) {
@@ -113,7 +117,6 @@ function _imagefield_zip_form_after_build(&$form, &$form_state) {
     }
 
     $in_a_group = FALSE;
-
     // Set the weight if in a group.
     if (!isset($form[$field_name]) && !empty($_imagefield_zip['groups'])) {
       foreach ($_imagefield_zip['groups'] as $group_name) {
@@ -149,14 +152,14 @@ function _imagefield_zip_form_after_build(&$form, &$form_state) {
  *   field/group name.
  */
 function _imagefield_zip_add_inline_js(&$name) {
-  $settigns = array(
+  $settings = array(
     'imagefield_zip_names' => array($name),
   );
-  drupal_add_js($settigns, 'setting');
+  drupal_add_js($settings, 'setting');
 }
 
 /**
- * Get the fieldgroups attaced to a field.
+ * Get the fieldgroups attached to a field.
  *
  * @see fieldgroup_form_alter()
  */
@@ -194,7 +197,7 @@ function imagefield_zip_get_groups(&$form) {
  * Recursively walk down the $form array looking for the CCK elements to modify
  *
  * @param $array array
- *     the $form array or piece of the form array when called recursivly (must be passed by reference)
+ *     the $form array or piece of the form array when called recursively (must be passed by reference)
  * @param $cck_field string
  *    key name to look for.
  * @param $zip_field array
@@ -224,51 +227,83 @@ function _imagefield_zip_cck_walker(&$array, &$cck_field, &$zip_field) {
  * @return array
  *   array of image file objects.
  */
-function imagefield_zip_save_and_extract_upload($field_name) {
-  $files_array = imagefield_zip_files_array_extractor($field_name);
+function imagefield_zip_save_and_extract_upload($field_name, $node_type) {
+  $content_type = content_types($node_type);
+  $target_field = str_replace('_zip', '', $field_name);
+  if (strpos($target_field, 'group_') === 0) {
+    $fields = _imagefield_zip_fields($content_type);
+    $groups = fieldgroup_groups($node_type);
+
+    // Find the correct field to add the images to.
+    foreach ($fields as $temp_field_name => $field) {
+      if (isset($groups[$target_field]['fields'][$temp_field_name])) {
+        $target_field = $temp_field_name;
+        break;
+      }
+    }
+  }
+  $upload_mode = variable_get('imagefield_zip_upload_mode_' . $node_type . '_' . $target_field, NULL);
+  $formats = $content_type['fields'][$target_field]['widget']['file_extensions'];
 
+  $files_array = imagefield_zip_files_array_extractor($field_name);
   $images = array();
-  foreach ($files_array as $file_array) {
-    if (substr($file_array['files']['name'][$field_name], -4) === '.zip') {
-      // File validation array for file_save_upload()
-      //  Has a .zip file extension.
-      //  Is valid zip.
-      $validators = array(
-        'file_validate_extensions' => array('zip'),
-        'imagefield_zip_is_valid_zip' => array(),
-      );
-    }
-    else {
-      $validators = array();
-    }
+  if (!empty($files_array)) {
+    foreach ($files_array as $file_array) {
+      $file = imagefield_zip_file_save_upload($field_name, array(), FALSE, FILE_EXISTS_RENAME, $file_array);
+      if (!$file) {
+        watchdog('imagefield_zip', 'Failed to save uploaded file', array(), WATCHDOG_ERROR);
+        continue;
+      }
 
-    $file = imagefield_zip_file_save_upload($field_name, $validators, FALSE, FILE_EXISTS_RENAME, $file_array);
-    if ($file) {
       $extracted = array();
-      // Extract all files.
-      if (substr($file->filepath, -4) === '.zip') {
-        $extracted = imagefield_zip_extract($file->filepath);
+      // Verify & extract files.
+      if ($upload_mode == 0) {
+        // Zip only
+        if (!imagefield_zip_is_valid_zip($file)) {
+          continue;
+        }
+        $extracted = imagefield_zip_extract($file, $formats);
       }
-      else {
+      elseif ($upload_mode == 1) {
+        // Images only
+        if (!imagefield_zip_is_image($file, $formats)) {
+          continue;
+        }
         $extracted[] = $file;
       }
-
-      if (!empty($extracted)) {
-        // Only select valid image files
-        $new_images = array_filter($extracted, '_imagefield_zip_is_archived_image');
-        $images = array_merge($images, $new_images);
-      }
-      else {
-        watchdog('imagefield_zip', 'Unpacked archive appears to be empty.', array(), WATCHDOG_WARNING);
+      elseif ($upload_mode == 2) {
+        // Images & zip only.
+        if (!imagefield_zip_is_image($file, $formats)) {
+          if (!imagefield_zip_is_valid_zip($file)) {
+            continue;
+          }
+          $extracted = imagefield_zip_extract($file, $formats);
+        }
+        else {
+          $extracted[] = $file;
+        }
       }
 
-      if (substr($file->filepath, -4) === '.zip') {
-        // Delete the zip file as we extracted and used everything we wanted from it.
-        imagefield_zip_delete_file($file);
+      if (empty($extracted)) {
+        watchdog('imagefield_zip', 'No images uploaded.', array(), WATCHDOG_WARNING);
+        continue;
       }
+      $images = array_merge($images, $extracted);
     }
-    else {
-      watchdog('imagefield_zip', 'Failed to save uploaded file', array(), WATCHDOG_ERROR);
+  }
+
+  if (empty($images)) {
+    if (empty($files_array)) {
+      drupal_set_message('No file selected.', 'warning');
+    }
+    elseif ($upload_mode == 0) {
+      drupal_set_message('The file uploaded was not a valid zip file.', 'warning');
+    }
+    elseif ($upload_mode == 1) {
+      drupal_set_message(t('Only image files in these formats can be uploaded: @formats.', array('@formats' => $formats)), 'warning');
+    }
+    elseif ($upload_mode == 2) {
+      drupal_set_message(t('Only files in these formats can be uploaded: @formats zip.', array('@formats' => $formats)), 'warning');
     }
   }
 
@@ -276,7 +311,7 @@ function imagefield_zip_save_and_extract_upload($field_name) {
 }
 
 /**
- * Stores the image files from ZIP files to the appropriate imagefields.
+ * Stores image files from ZIP files/html5 multi-upload to the appropriate imagefields.
  *
  * @see imagefield_zip_page()
  */
@@ -327,7 +362,7 @@ function imagefield_zip_page_submit($form, &$form_state) {
     }
 
     // Get images from the zip file.
-    $images = imagefield_zip_save_and_extract_upload($field_name);
+    $images = imagefield_zip_save_and_extract_upload($field_name, $type);
     if (empty($images)) {
       continue;
     }
@@ -404,109 +439,196 @@ function _imagefield_zip_form(&$form, &$field_name, &$node, &$groups) {
     $weight = -0.01;
   }
 
-  $max_filesize = format_size(parse_size(file_upload_max_size()));
+  $upload_mode = variable_get('imagefield_zip_upload_mode_' . $node->type . '_' . $field_name, IMAGEFIELD_ZIP_UPLOAD_MODE);
+  $fallback_mode = variable_get('imagefield_zip_fallback_' . $node->type . '_' . $field_name, IMAGEFIELD_ZIP_FALLBACK);
+
   global $_imagefield_zip;
 
   if (!empty($groups)) {
     foreach ($groups as $group_name => $group) {
-      if (!empty($group['fields'][$field_name])) {
+      if (empty($group['fields'][$field_name])) {
+        continue;
+      }
 
-        // Code adapted from content_multigroup_add_more().
-        if (empty($group['settings']['multigroup']['multiple']) || (isset($group['settings']['multigroup']['multiple']) && $group['settings']['multigroup']['multiple'] != 1)) {
-          continue;
-        }
+      // Code adapted from content_multigroup_add_more().
+      if (empty($group['settings']['multigroup']['multiple']) || (isset($group['settings']['multigroup']['multiple']) && $group['settings']['multigroup']['multiple'] != 1)) {
+        continue;
+      }
 
-        // Make sure the form is cached so ahah can work.
-        $form['#cache'] = TRUE;
-        $content_type = content_types($group['type_name']);
-        $group_name = $group['group_name'];
-        $group_name_css = str_replace('_', '-', $group_name);
-        $_imagefield_zip['groups'][] = $group_name;
+      // Make sure the form is cached so ahah can work.
+      $form['#cache'] = TRUE;
+      $content_type = content_types($group['type_name']);
+      $_imagefield_zip['groups'][] = $group['group_name'];
 
-        $form[$group_name .'_zip'] = array(
-          '#weight' => $weight,
-        );
-        $form[$group_name .'_zip'][$group_name . '_upload'] = array(
-          '#type' => 'file',
-          '#title' => t('Zip Upload for @name', array('@name' => $group_name)),
-          '#name' => "files[{$group_name}_zip][]",
-          '#description' => t('To upload multiple images at a time, attach a ZIP file here. The zip must contain only the allowed image formats. Maximum Filesize: @max_filesize', array('@max_filesize' => $max_filesize)),
-          '#attributes' => array(
-            'accept' => 'zip'
-          ),
-          '#element_validate' => array('_imagefield_zip_element_validate'),
-          '#attributes' => array('multiple' => 'multiple'),
-        );
-        $form[$group_name .'_zip'][$group_name . '_button'] = array(
-          '#type' => 'submit',
-          '#value' => t('Upload'),
-          // Submit callback for disabled JavaScript. drupal_get_form() might get
-          // the form from the cache, so we can't rely on content_form_alter()
-          // including this file. Therefore, call a proxy function to do this.
-          '#submit' => array('content_multigroup_add_more_submit'),
-          '#ahah' => array(
-            'path' => 'imagefield_zip/ahah-multigroup/' . $content_type['url_str'] . '/' . $group_name,
-            'wrapper' => $group_name_css .'-items',
-            'method' => 'replace',
-            'effect' => 'fade',
-          ),
-          // When JS is disabled, the content_add_more_submit handler will find
-          // the relevant field using these entries.
-          '#group_name' => $group_name,
-          '#type_name' => $group['type_name'],
-          '#prefix' => '<div class="clear-block">',
-          '#suffix' => '</div>',
-        );
+      $machine_name = $group['group_name'];
+      $nice_name = $group['label'];
+      $formats = $content_type['fields'][$field_name]['widget']['file_extensions'];
+      $machine_node_type = $node->type;
+      $field_or_group = 'group';
+
+      if (imagefield_zip_build_upload_form($form, $machine_name, $nice_name, $formats, $machine_node_type, $upload_mode, $fallback_mode, $weight, $field_or_group)) {
+        return TRUE;
+      }
+      return FALSE;
+    }
+  }
+
+  $content_type = content_types($node->type);
 
+  $machine_name = $field_name;
+  $nice_name = $content_type['fields'][$field_name]['widget']['label'];
+  $formats = $content_type['fields'][$field_name]['widget']['file_extensions'];
+  $machine_node_type = $node->type;
+  $field_or_group = 'field';
+  $machine_name_css = str_replace('_', '-', $machine_name);
+
+  if (imagefield_zip_build_upload_form($form, $machine_name, $nice_name, $formats, $machine_node_type, $upload_mode, $fallback_mode, $weight, $field_or_group)) {
+    $form[$field_name]['#prefix'] .= '<div id="'. $machine_name_css .'-items">';
+    $form[$field_name]['#suffix'] .= '</div>';
+
+    return TRUE;
+  }
+  return FALSE;
+}
 
+function imagefield_zip_build_upload_form(&$form, $machine_name, $nice_name, $formats, $machine_node_type, $upload_mode, $fallback_mode, $weight, $field_or_group) {
+
+  $machine_name_css = str_replace('_', '-', $machine_name);
+  $max_filesize = format_size(parse_size(file_upload_max_size()));
+  $zip_mime = 'application/zip, application/x-zip, application/x-zip-compressed, application/x-compress, application/x-compressed';
+
+  // The accept attribute only works in chrome; but it's still a nice feature.
+  $formats_array = explode(' ', $formats);
+  // Special handling for jpg/jpeg.
+  $key = array_search('jpg', $formats_array);
+  if ($key !== FALSE) {
+    unset($formats_array[$key]);
+    if (!in_array('jpeg', $formats_array)) {
+      $formats_array[$key] = 'jpeg';
+    }
+  }
+
+  if (imagefield_zip_is_ie()) {
+    if ($upload_mode == 2) {
+      $upload_mode = 0;
+    }
+    if ($upload_mode == 1) {
+      if ($fallback_mode == 0) {
+        $upload_mode = 0;
+      }
+      if ($fallback_mode == 2) {
+        return FALSE;
+      }
+      if ($fallback_mode == 1) {
+        $form[$machine_name .'_zip'] = array(
+          '#type' => 'item',
+          '#title' => t('Add Multiple Images'),
+          '#value' => t('Your browser does not support HTML5 native upload. Try <a href="http://www.google.com/chrome/">Chrome</a>, <a href="http://www.mozilla.org/en-US/products/download.html">Firefox</a> or <a href="http://www.apple.com/safari/download/">Safari</a>.'),
+          '#prefix' => '<div class="zip-fallback-message">',
+          '#suffix' => '</div>',
+        );
         return TRUE;
       }
     }
   }
 
-  $form[$field_name .'_zip'] = array(
-    '#weight' => intval($form[$field_name]['#weight']) + $weight,
+  // Set form defaults.
+  $form[$machine_name .'_zip'] = array(
+    '#prefix' => '<div class="zip-field">',
+    '#suffix' => '</div>',
   );
-  $form[$field_name .'_zip'][$field_name . '_upload'] = array(
+  $form[$machine_name .'_zip'][$machine_name . '_upload'] = array(
     '#type' => 'file',
-    '#title' => t('Zip Upload for @name', array('@name' => $field_name)),
-    '#name' => "files[{$field_name}_zip][]",
-    '#description' => t('To upload multiple images at a time, attach a ZIP file here. The zip must contain only the allowed image formats. Maximum Filesize: @max_filesize', array('@max_filesize' => $max_filesize)),
+    '#size' => 22,
     '#attributes' => array(
-      'accept' => 'zip'
+      'class' => 'zip-upload',
     ),
-    '#element_validate' => array('_imagefield_zip_element_validate'),
-    '#attributes' => array('multiple' => 'multiple'),
   );
-
-  // Code adapted from content_multiple_value_form().
-  // Make sure the form is cached so ahah can work.
-  $form['#cache'] = TRUE;
-  $field_name_css = str_replace('_', '-', $form[$field_name]['#field_name']);
-
-  $form[$field_name .'_zip'][$field_name . '_button'] = array(
-    '#type' => 'submit',
-    '#value' => t('Upload'),
-    // Submit callback for disabled JavaScript. drupal_get_form() might get
-    // the form from the cache, so we can't rely on content_form_alter()
-    // including this file. Therefore, call a proxy function to do this.
-    '#submit' => array('content_add_more_submit_proxy'),
-    '#ahah' => array(
-      'path' => 'imagefield_zip/ahah/'. $node->type .'/'. $field_name,
-      'wrapper' => $field_name_css .'-items',
-      'method' => 'replace',
-      'effect' => 'fade',
-    ),
-    // When JS is disabled, the content_add_more_submit handler will find
-    // the relevant field using these entries.
-    '#field_name' => $field_name,
-    '#type_name' => $form['type']['#value'],
-    '#prefix' => '<div class="clear-block">',
-    '#suffix' => '</div>',
+  $form[$machine_name .'_zip'][$machine_name . '_button'] = array(
+      '#type' => 'submit',
+      '#value' => t('Start Upload'),
+      // Submit callback for disabled JavaScript. drupal_get_form() might get
+      // the form from the cache, so we can't rely on content_form_alter()
+      // including this file. Therefore, call a proxy function to do this.
+      '#ahah' => array(
+        'wrapper' => $machine_name_css .'-items',
+        'method' => 'replace',
+        'effect' => 'fade',
+      ),
+      // When JS is disabled, the content_add_more_submit handler will find
+      // the relevant field using these entries.
+      '#type_name' => $machine_node_type,
+      '#suffix' => '<div class="clear-block"><div class="description zip-description">',
+      '#attributes' => array(
+        'class' => 'zip-submit',
+      ),
   );
 
-  $form[$field_name]['#prefix'] .= '<div id="'. $field_name_css .'-items">';
-  $form[$field_name]['#suffix'] .= '</div>';
+  // Set attributes based off of settings.
+  if ($upload_mode == 0) {
+    $form[$machine_name .'_zip'][$machine_name . '_upload'] += array(
+      '#title' => t('Add Zip File Containing Images'),
+      '#name' => "files[{$machine_name}_zip]",
+    );
+    $form[$machine_name .'_zip'][$machine_name . '_upload']['#attributes'] += array(
+      'accept' => $zip_mime,
+    );
+    $form[$machine_name .'_zip'][$machine_name . '_button']['#suffix'] .= t('Add multiple image files to the @name @type @location by selecting a zip file in the dialog box. Allowed image extensions in the zip: @formats. Maximum zip file size: @max_filesize', array(
+        '@max_filesize' => $max_filesize,
+        '@formats' => $formats,
+        '@name' => $nice_name,
+        '@location' => $weight > 0 ? t('above') : t('below'),
+        '@type' => $field_or_group,
+      )) . '</div></div>';
+  }
+  elseif ($upload_mode == 1) {
+    $form[$machine_name .'_zip'][$machine_name . '_upload'] += array(
+      '#title' => t('Add Multiple Images'),
+      '#name' => "files[{$machine_name}_zip][]",
+    );
+    $form[$machine_name .'_zip'][$machine_name . '_upload']['#attributes'] += array(
+      'multiple' => 'multiple',
+      'accept' => 'image/' . implode(', image/', $formats_array),
+    );
+    $form[$machine_name .'_zip'][$machine_name . '_button']['#suffix'] .= t('Add multiple image files to the @name @type @location by holding the <strong>CTRL key and clicking multiple images</strong> in the dialog. Allowed extensions: @formats with a maximum file size of @max_filesize', array(
+        '@max_filesize' => $max_filesize,
+        '@formats' => $formats,
+        '@name' => $nice_name,
+        '@location' => $weight > 0 ? t('above') : t('below'),
+        '@type' => $field_or_group,
+      )) . '</div></div>';
+  }
+  elseif ($upload_mode == 2) {
+    $form[$machine_name .'_zip'][$machine_name . '_upload'] += array(
+      '#title' => t('Add Multiple Images OR Zip File Containing Images'),
+      '#name' => "files[{$machine_name}_zip][]",
+    );
+    $form[$machine_name .'_zip'][$machine_name . '_upload']['#attributes'] += array(
+      'multiple' => 'multiple',
+      'accept' => 'image/' . implode(', image/', $formats_array) . ', ' . $zip_mime,
+    );
+    $form[$machine_name .'_zip'][$machine_name . '_button']['#suffix'] .= t('Add multiple image files to the @name @type @location by holding the <strong>CTRL key and clicking multiple images</strong> in the dialog. Allowed extensions: @formats with a maximum file size of @max_filesize', array(
+        '@max_filesize' => $max_filesize,
+        '@formats' => $formats . ' zip',
+        '@name' => $nice_name,
+        '@location' => $weight > 0 ? t('above') : t('below'),
+        '@type' => $field_or_group,
+      )) . '</div></div>';
+  }
+
+  // Multigroup or field?
+  if ($field_or_group == 'group') {
+    $form[$machine_name .'_zip']['#weight'] = $weight;
+    $form[$machine_name .'_zip'][$machine_name . '_button']['#submit'] = array('content_multigroup_add_more_submit');
+    $form[$machine_name .'_zip'][$machine_name . '_button']['#ahah']['path'] = 'imagefield_zip/ahah-multigroup/' . $machine_node_type . '/' . $machine_name;
+    $form[$machine_name .'_zip'][$machine_name . '_button']['#group_name'] = $machine_name;
+  }
+  else {
+    $form[$machine_name .'_zip']['#weight'] = intval($form[$machine_name]['#weight']) + $weight;
+    $form[$machine_name .'_zip'][$machine_name . '_button']['#submit'] = array('content_add_more_submit_proxy');
+    $form[$machine_name .'_zip'][$machine_name . '_button']['#ahah']['path'] = 'imagefield_zip/ahah/' . $machine_node_type . '/' . $machine_name;
+    $form[$machine_name .'_zip'][$machine_name . '_button']['#field_name'] = $machine_name;
+  }
 
   return TRUE;
 }
@@ -534,8 +656,11 @@ function _imagefield_zip_fields(&$type) {
  *
  * @param $filepath
  *   Location of zip file.
+ * @param $formats
+ *   String of file extensions to check against.
  */
-function imagefield_zip_extract($filepath) {
+function imagefield_zip_extract($zip_file, $formats) {
+  $filepath = $zip_file->filepath;
   $extracted = array();
   // Exit if zip_open function does not exist.
   if (!function_exists('zip_open')) {
@@ -560,7 +685,7 @@ function imagefield_zip_extract($filepath) {
   $dest = file_destination(file_directory_temp() .'/'. basename($filepath, '.zip'), FILE_EXISTS_RENAME);
   mkdir($dest, 0755);
 
-  // Itterate over each file.
+  // Iterate over each file.
   while ($entry = zip_read($z)) {
     if (!zip_entry_open($z, $entry, 'r')) {
       watchdog('imagefield_zip', 'Failed to read an entry in the uploaded file %filepath. %error', array(
@@ -622,7 +747,13 @@ function imagefield_zip_extract($filepath) {
       $file->filename = $entry_name;
       $file->filemime = file_get_mimetype($file_source);
       $file->filesize = filesize($file_source);
-      $extracted[] = $file;
+
+      if (imagefield_zip_is_image($file, $formats)) {
+        $extracted[] = $file;
+      }
+      else {
+        imagefield_zip_delete_file($file);
+      }
     }
     zip_entry_close($entry);
   }
@@ -631,6 +762,8 @@ function imagefield_zip_extract($filepath) {
   if (isset($content)) {
     unset($content);
   }
+  // Delete the zip file as we extracted and used everything we wanted from it.
+  imagefield_zip_delete_file($zip_file);
 
   return $extracted;
 }
@@ -661,31 +794,49 @@ function imagefield_zip_delete_file(&$file) {
 function imagefield_zip_is_valid_zip(&$file) {
   $errors = array();
   if (!function_exists('zip_open')) {
-    watchdog('imagefield_zip', 'Required function zip_open was not available', array(), WATCHDOG_CRITICAL);
-    $errors[] = t('Required function zip_open was not available');
-    return $errors;
+    return FALSE;
   }
-  if ($z = zip_open($file->filepath)) {
-    zip_close($z);
+  if (substr($file->filepath, -4) !== '.zip') {
+    // Zip file must end in .zip
+    return FALSE;
   }
-  else {
-    $errors[] = t('The file is not a valid zip file or may be corrupt.');
-    watchdog('imagefield_zip', 'Invalid zip file %file', array('%file' => $file), WATCHDOG_ERROR);
+  // See if we can open the zip file.
+  $z = zip_open($file->filepath);
+  if (!is_resource($z)) {
+    return FALSE;
   }
-  return $errors;
+  zip_close($z);
+  return TRUE;
 }
 
 /**
  * Check that the file is an image.
  *
  * @param $file
- *   file object
+ *   file object.
+ * @param $formats
+ *   String of file extensions to check against.
  */
-function _imagefield_zip_is_archived_image(&$file) {
+function imagefield_zip_is_image(&$file, $formats) {
   if (empty($file->filepath)) {
     return FALSE;
   }
 
+  $formats_array = explode(' ', $formats);
+  $valid_file = FALSE;
+  foreach ($formats_array as $ext) {
+    $ext = '.' . $ext;
+    $ext_len = strlen($ext) * -1;
+    if (substr($file->filepath, $ext_len) === $ext) {
+      // file ends in one of the valid formats.
+      $valid_file = TRUE;
+      break;
+    }
+  }
+  if (!$valid_file) {
+    return FALSE;
+  }
+
   $info = image_get_info($file->filepath);
   if (!$info || empty($info['extension'])) {
     return FALSE;
@@ -933,5 +1084,29 @@ function imagefield_zip_files_array_extractor($field_name) {
       }
     }
   }
+  // Remove empty files.
+  foreach ($files_array as $delta => $file_array) {
+     if ($file_array['files']['error'][$field_name] == UPLOAD_ERR_NO_FILE) {
+      unset($files_array[$delta]);
+    }
+  }
   return $files_array;
 }
+
+function imagefield_zip_is_ie() {
+  $is_ie = FALSE;
+  if (isset($_SERVER['HTTP_USER_AGENT'])) {
+    // Strings for testing found via
+    // http://chrisschuld.com/projects/browser-php-detecting-a-users-browser-from-php/
+    // Test for v1 - v1.5 IE
+    // Test for versions > 1.5
+    // Test for Pocket IE
+    if (   stristr($_SERVER['HTTP_USER_AGENT'], 'microsoft internet explorer')
+        || stristr($_SERVER['HTTP_USER_AGENT'], 'msie')
+        || stristr($_SERVER['HTTP_USER_AGENT'], 'mspie')
+        ) {
+      $is_ie = TRUE;
+    }
+  }
+  return $is_ie;
+}
