? filefield-d6.patch
Index: filefield.info
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/filefield/filefield.info,v
retrieving revision 1.6
diff -u -p -r1.6 filefield.info
--- filefield.info	10 Jun 2008 14:08:38 -0000	1.6
+++ filefield.info	10 Jun 2008 20:12:51 -0000
@@ -1,5 +1,8 @@
-; $Id: filefield.info,v 1.6 2008/06/10 14:08:38 jpetso Exp $
+; $Id: filefield.info,v 1.5 2007/06/18 22:53:42 dww Exp $
 name = File Field
 description = Defines a file field type.
-dependencies = content mimedetect
+dependencies[] = content
+dependencies[] = token
 package = CCK
+core = 6.x
+php = 5.2
\ No newline at end of file
Index: filefield.install
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/filefield/filefield.install,v
retrieving revision 1.5
diff -u -p -r1.5 filefield.install
--- filefield.install	10 Jun 2008 14:08:38 -0000	1.5
+++ filefield.install	10 Jun 2008 20:12:51 -0000
@@ -1,10 +1,34 @@
 <?php
-// $Id: filefield.install,v 1.5 2008/06/10 14:08:38 jpetso Exp $
+// $Id: filefield.install,v 1.4 2008/01/03 16:40:21 jpetso Exp $
+
+include_once(drupal_get_path('module', 'filefield') .'/field_file.inc');
 
 /**
  * Implementation of hook_install().
  */
 function filefield_install() {
+  content_notify('install', 'filefield');
+}
+
+/**
+* Implementation of hook_uninstall().
+*/
+function filefield_uninstall() {
+  content_notify('uninstall', 'filefield');
+}
+
+/**
+* Implementation of hook_enable().
+*/
+function filefield_enable() {
+  content_notify('enable', 'filefield');
+}
+
+/**
+* Implementation of hook_disable().
+*/
+function filefield_disable() {
+  content_notify('disable', 'filefield');
 }
 
 function filefield_update_1() {
Index: filefield.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/filefield/filefield.module,v
retrieving revision 1.58
diff -u -p -r1.58 filefield.module
--- filefield.module	10 Jun 2008 14:08:38 -0000	1.58
+++ filefield.module	10 Jun 2008 20:12:52 -0000
@@ -1,5 +1,5 @@
 <?php
-// $Id: filefield.module,v 1.58 2008/06/10 14:08:38 jpetso Exp $
+// $Id: filefield.module,v 1.57 2007/12/06 23:50:00 jpetso Exp $
 
 /**
  * @file
@@ -9,19 +9,20 @@
  * table to store the actual file data.
  */
 
-define('FILEFIELD_MINIMUM_PHP', '5.2');
+include_once('field_file.inc');
 
-function filefield_menu($may_cache) {
+function filefield_menu() {
   $items = array();
 
+  $items['filefield/js'] = array(
+    'page callback' => 'filefield_js',
+    'access arguments' => array('view content'),
+    'type' => MENU_CALLBACK,
+  );
+  
+  /*
   if ($may_cache) {
-    $items[] = array(
-      'path' => 'filefield/js',
-      'callback' => 'filefield_js',
-      //'access' => user_access(),
-      'access' => TRUE,
-      'type' => MENU_CALLBACK
-    );
+    
   }
   else if ($_SESSION['filefield']) {
     // Add handlers for previewing new uploads.
@@ -40,26 +41,25 @@ function filefield_menu($may_cache) {
       }
     }
   }
+  */
+  
   return $items;
 }
 
+
 /**
- *  Implementation of hook_requirements().
+ * implementation of hook_content_is_empty
+ *
+ * the result of this determines whether content.module will save
+ * the value of the field.
  */
-function filefield_requirements($phase) {
-  $requirements = array();
-  // Ensure translations don't break at install time
-  $t = get_t();
-
-  if (version_compare(phpversion(), FILEFIELD_MINIMUM_PHP) < 0) {
-    $requirements['filefield_php'] = array(
-      'title' => $t('FileField PHP'),
-      'description' => $t('FileField requires at least PHP %version.', array('%version' => FILEFIELD_MINIMUM_PHP)),
-      'severity' => REQUIREMENT_ERROR
-    );
+function filefield_content_is_empty($item, $field) {
+  if (empty($item['fid'])) {
+    return true;
   }
-
-  return $requirements;
+  else {
+    return false;
+  }  
 }
 
 /**
@@ -87,7 +87,10 @@ function filefield_perm() {
  */
 function filefield_field_info() {
   return array(
-    'file' => array('label' => 'File'),
+    'file' => array(
+      'label' => 'File',
+      'description' => t('Store an arbitrary file.'),
+    ),
   );
 }
 
@@ -114,22 +117,11 @@ function filefield_field_settings($op, $
 
     case 'database columns':
       $columns = array(
-        'fid' => array('type' => 'int', 'not null' => TRUE, 'default' => '0'),
-        'description' => array('type' => 'varchar', length => 255, 'not null' => TRUE, 'default' => "''", 'sortable' => TRUE),
-        'list' => array('type' => 'int', 'not null' => TRUE, 'default' => '0'),
+        'fid' => array('type' => 'int', 'not null' => FALSE),
+        'description' => array('type' => 'varchar', length => 255, 'not null' => FALSE, 'sortable' => TRUE),
+        'list' => array('type' => 'int', 'not null' => FALSE),
       );
       return $columns;
-
-    case 'filters':
-      return array(
-        'not null' => array(
-          'operator' => array('=' => t('Has file')),
-          'list' => 'views_handler_operator_yesno',
-          'list-type' => 'select',
-          'handler' => 'filefield_views_handler_filter_is_not_null',
-        ),
-      );  
-
   }
 }
 
@@ -142,136 +134,64 @@ function filefield_default_item() {
 }
 
 /**
- * insert a file into the database.
- * @param $node
- *    node object file will be associated with.
- * @param $file
- *    file to be inserted, passed by reference since fid should be attached.
- *    
- */
-function filefield_file_insert($node, $field, &$file) {
-  $fieldname = $field['field_name'];
-  
-  // allow tokenized paths.
-  if (function_exists('token_replace')) {
-    global $user;
-    $widget_file_path = token_replace($field['widget']['file_path'], 'user', $user);
-  }
-  else {
-    $widget_file_path = $field['widget']['file_path'];
-  }
- 
-  $filepath = file_create_path($widget_file_path) . '/' . $file['filename'];
-  
-  if (filefield_check_directory($widget_file_path) && $file = file_save_upload((object)$file, $filepath)) {
-    $file = (array)$file;
-    $file['fid'] = db_next_id('{files}_fid');
-    $file['filemime'] = mimedetect_mime($file);
-    db_query("INSERT into {files} (fid, nid, filename, filepath, filemime, filesize)
-              VALUES (%d, %d, '%s','%s','%s',%d)",
-              $file['fid'], $node->nid, $file['filename'], $file['filepath'],
-              $file['filemime'], $file['filesize']);
-    module_invoke_all('filefield', 'file_save', $node, $field, $file);
-    return (array)$file;
-  }
-  else {
-    // Include file name in upload error.
-    form_set_error(NULL, t('File upload was unsuccessful.'));
-    return FALSE;
-  }
-}
-
-
-/**
- * update the file record if necessary
- * @param $node
- * @param $file
- * @param $field
- */
-function filefield_file_update($node, $field, &$file) {
-  $file = (array)$file; 
-  if ($file['delete'] == TRUE) {
-    // don't delete files if we're creating new revisions,
-    // but still return an empty array...
-    if ($node->old_vid) {
-      return array();
-    }
-    if (_filefield_file_delete($node, $field, $file)) {
-      return array();
-    }
-  }
-  if ($file['fid'] == 'upload') {  
-    return filefield_file_insert($node, $field, $file);
-  }
-  else {
-    // if fid is not numeric here we should complain.
-    // else we update the file table.  
-  }
-  return $file;
-}
-
-/**
  * Implementation of hook_field().
  */
-function filefield_field($op, &$node, $field, &$items = array()) {
+function filefield_field($op, $node, $field, &$items, $teaser, $page) {
   $fieldname = $field['field_name'];
   switch ($op) {
     // called after content.module loads default data.
     case 'load':
-      if (is_array($items)) {
-        $items = array_filter($items); // drop empty deltas, cuz cck sends 'em some times.
-      }
-      if (empty($items)) {
-        return array();
-      }
+      if (empty($items)) return;
       foreach ($items as $delta => $item) {
-        if (!empty($item['fid'])) { // otherwise, merge our info with CCK's, and all is fine.
-          $items[$delta] = array_merge($item, _filefield_file_load($item['fid']));
-        }
+        $items[$delta] = array_merge($item, field_file_load($item['fid']));
       }
-      $items = array_values($items); // compact deltas
+      $items = array_values(array_filter($items)); // compact deltas
       return array($fieldname => $items);
+      break;
 
-    // called before content.module defaults.
     case 'insert':
+    case 'update':
       foreach ($items as $delta => $item) {
-        $items[$delta] = filefield_file_insert($node, $field, $item);
+        $items[$delta] = field_file_save($node, $item);
       }
-      $items = array_values($items); // compact deltas
-      filefield_clear_field_session($fieldname);
+      $items = array_values(array_filter($items)); // compact deltas
       break;
-
-    // called before content.module defaults.
-    case 'update':
+      
+    case 'delete revision':
       foreach ($items as $delta => $item) {
-        $items[$delta] = filefield_file_update($node, $field, $item);
+        if (field_file_delete($item)) $items[$delta] = array();
       }
-      $items = array_filter($items); // unset empty items.
       $items = array_values($items); // compact deltas
-      filefield_clear_field_session($fieldname);
       break;
-
-    case 'delete revision':
-      $db_info = content_database_info($field);
+    
+    case 'delete':
       foreach ($items as $delta => $item) {
-        $references = db_result(db_query(
-          "SELECT COUNT(vid) FROM {" . $db_info['table'] . "}
-            WHERE nid = %d AND vid != %d
-            AND " . $db_info['columns']['fid']['column'] . " = %d",
-          $node->nid, $node->vid, $item['fid']
-        ));
-        if ($references || _filefield_file_delete($node, $field, $item)) {
-          $items[$delta] = array();
-        }
+        field_file_delete($item, true);
       }
-      $items = array_values($items); // compact deltas
       break;
 
-    case 'delete':
+    case 'sanitize':
       foreach ($items as $delta => $item) {
-        _filefield_file_delete($node, $field, $item); 
+        /* This is causing an infinite loop.  Skip  it until we know why.
+        // Cleanup $items during node preview.
+        if (empty($item['fid']) || !empty($item['flags']['delete']) || !empty($item['flags']['hidden'])) {
+          unset($items[$delta]);
+        }
+        // Load the complete file if a filepath is not available.
+        if (!empty($item['fid']) && empty($item['filepath'])) {
+          $items[$delta] = array_merge($item, field_file_load($item['fid']));
+        }
+        // Add nid so formatters can create a link to the node.
+        $items[$delta]['nid'] = $node->nid;
+        */
+      }
+      // If completely empty, check for a default image.
+      if (empty($items) && $field['use_default_image'] && $field['default_image']['fid']) {
+        $items[$field['default_image']['fid']] = $field['default_image'];
+        $items[$field['default_image']['fid']] = $node->nid;
       }
       break;
+
   }
 }
 
@@ -283,6 +203,8 @@ function filefield_widget_info() {
     'file' => array(
       'label' => 'File',
       'field types' => array('file'),
+      'multiple values' => CONTENT_HANDLE_CORE,
+      'callbacks' => array('default value' => CONTENT_CALLBACK_CUSTOM),
     ),
   );
 }
@@ -292,45 +214,34 @@ function filefield_widget_info() {
  */
 function filefield_widget_settings($op, $widget) {
   switch ($op) {
-    case 'callbacks':
-      return array('default value' => CONTENT_CALLBACK_CUSTOM);
-
     case 'form':
       $form = array();
       $form['file_extensions'] = array (
         '#type' => 'textfield',
         '#title' => t('Permitted upload file extensions'),
-        '#default_value' => isset($widget['file_extensions']) ? $widget['file_extensions'] : 'txt',
+        '#default_value' => $widget['file_extensions'] ? $widget['file_extensions'] : 'txt',
+        '#required' => TRUE,
         '#size' => 64,
-        '#description' => t('Extensions a user can upload to this field. Separate extensions with a space and do not include the leading dot. Leaving this blank will allow users to upload a file with any extension.'),
+        '#description' => t('Extensions a user can upload to this field. Separate extensions with a space and do not include the leading dot.'),
       );
       $form['file_path'] = array(
         '#type' => 'textfield', 
         '#title' => t('File path'), 
         '#default_value' => $widget['file_path'] ? $widget['file_path'] : '', 
         '#description' => t('Optional subdirectory within the "%dir" directory where files will be stored. Do not include trailing slash.', array('%dir' => variable_get('file_directory_path', 'files'))), 
+        '#element_validate' => array('_filefield_widget_settings_image_path_validate'),
+        '#suffix' => theme('token_help', 'user'),
       );
-      if (function_exists('token_replace')) {
-        $form['file_path']['#description'] .= theme('token_help', 'user');        
-      }
-      // Let extension modules add their settings to the form.
-      foreach (module_implements('filefield_widget_settings') as $module) {
-        $function = $module .'_filefield_widget_settings';
-        $function('form_alter', $widget, $form);
-      }
       return $form;
-    case 'validate':
-      module_invoke_all('filefield_widget_settings', $op, $widget, NULL);
-      break;
     case 'save':
-      $core_settings = array('file_extensions', 'file_path');
-      $additional_settings = module_invoke_all(
-        'filefield_widget_settings', $op, $widget, NULL
-      );
-      return array_merge($core_settings, $additional_settings);
+      return array('file_extensions', 'file_path');
   }
 }
 
+function _filefield_widget_settings_image_path_validate($element, &$form_state) {
+  // Strip slashes from the beginning and end of $widget['image_path']
+  $form_state['values']['image_path'] =  trim($form_state['values']['image_path'], '\\/');
+}
 
 function filefield_clear_session() {
   if (is_array($_SESSION['filefield']) && count($_SESSION['filefield'])) {
@@ -352,41 +263,50 @@ function filefield_clear_field_session($
   }
 }
 
-function _filefield_file_delete($node, $field, $file) {
-  if (is_numeric($file['fid'])) {
-    db_query('DELETE FROM {files} WHERE fid = %d', $file['fid']);
-  }
-  else {
-    unset($_SESSION['filefield'][$field['field_name']][$file['sessionid']]);
-  }
-  module_invoke_all('filefield', 'file_delete', $node, $field, $file);
-  return file_delete($file['filepath']);
-}
-
 /**
  * Implementation of hook_widget().
  */
-function filefield_widget($op, $node, $field, &$items) {
+function filefield_widget(&$form, &$form_state, $field, $items, $delta = 0) {
+  $form['#attributes'] += array('enctype' => 'multipart/form-data');
+ 
+  $widget = array();
+  
+  $widget['fid'] =  array(
+    '#type' => $field['widget']['type'],
+    '#title' => $field['widget']['label'],
+    '#description' =>  $field['widget']['description'],
+    '#default_value' => isset($items[$delta]) ? $items[$delta]['fid'] : null,
+    '#field' => $field,
+    '#delta' => $delta,
+  );
+
+  return $widget;
+}
+
+/*
+function filefield_widget($op, $node, $field, &$node_field) {
   $fieldname = $field['field_name'];
   switch ($op) {
     case 'default value':
       return array();
 
     case 'prepare form values':
-      _filefield_widget_prepare_form_values($node, $field, $items);
+      _filefield_widget_prepare_form_values($node, $field, $node_field);
       break;
 
     case 'form':
-      return  _filefield_widget_form($node, $field, $items);
+      return  _filefield_widget_form($node, $field, $node_field);
 
     case 'validate':
-      _filefield_widget_validate($node, $field, $items);
+      _filefield_widget_validate($node, $field, $node_field);
       break;
   }
 }
+*/
 
-function _filefield_widget_prepare_form_values($node, $field, &$items) {
+function _filefield_widget_prepare_form_values($node, $field, &$node_field) {
   $fieldname = $field['field_name'];
+
   // @todo split this into its own function. determine if we can make it a form element.
   if (!count($_POST)) {
     filefield_clear_session();
@@ -397,27 +317,35 @@ function _filefield_widget_prepare_form_
     // test allowed extensions. We do this when the file is uploaded, rather than waiting for the
     // field itseld to reach op==validate.
     $last_ext = array_pop(explode('.', $file['filename']));
-    $valid = TRUE;
-    // only check extensions if there extensions to check.
-    // @todo: trim & strtolower file_extenstions with a formapi validate callback.
-    if (strlen(trim($field['widget']['file_extensions']))) {
-      $allowed_extensions = array_unique(explode(' ', strtolower(trim($field['widget']['file_extensions']))));
-      $ext = strtolower(array_pop(explode('.', $file['filename'])));
-      if (!in_array($ext, $allowed_extensions)) {
-        $valid = FALSE;
-        form_set_error($field['field_name'] .'_upload', t('Files with the extension %ext are not allowed. Please upload a file with an extension from the following list: %allowed_extensions', array('%ext' => $last_ext, '%allowed_extensions' => $field['widget']['file_extensions'])));
-      }
+    $allowed_extensions = array_unique(explode(' ', trim($field['widget']['file_extensions'])));
+    $valid = FALSE;
+
+    foreach ($allowed_extensions as $allowed_ext) {
+      $allowed_ext = '.'. $allowed_ext;
+      $file_ext = substr($file['filename'], strlen($file['filename']) - strlen($allowed_ext));
+      if (strtolower($file_ext) == strtolower($allowed_ext)) {
+        $valid = TRUE;
+        break;
+      }
+    }
+    if (!$valid) {
+      // set base validation error message.
+      form_set_error($field['field_name'] .'_upload', t('Files with the extension %ext are not allowed. Please upload a file with an extension from the following list: %allowed_extensions', array('%ext' => $last_ext, '%allowed_extensions' => $field['widget']['file_extensions'])));
     }
+    
     // let extended validation from other module happen so we get all error messages.
     // if you implement hook_filefield_file() return FALSE to stop the upload.
-    if (!$valid || in_array(FALSE, module_invoke_all('filefield', 'file_validate', $node, $field, $file))) {
+    if (in_array(FALSE, module_invoke_all('filefield', 'file_validate', $node, $field, $file))) {
+      $valid = FALSE;
+    }
+    
+    if (!$valid) {
       return FALSE;
     }
+
+
     // let modules massage act on the file.
-    foreach(module_implements('filefield') as $module) {
-      $function =  $module .'_filefield';
-      $function('file_prepare', $node, $field, $file);
-    }
+    module_invoke_all('filefield', 'file_prepare', $node, $field, $file);
 
     $filepath = file_create_filename($file['filename'], file_create_path($field['widget']['file_path']));
     if (variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC) == FILE_DOWNLOADS_PRIVATE) {
@@ -433,31 +361,30 @@ function _filefield_widget_prepare_form_
 
     // if this is a single value filefield mark any other files for deletion.
     if (!$field['multiple']) {
-      if (is_array($items)) {
-        foreach($items as $delta => $session_file) {
-          $items[$delta]['delete'] = TRUE;
+      if (is_array($node_field)) {
+        foreach($node_field as $delta => $session_file) {
+          $node_field[$delta]['delete'] = TRUE;
         }
       }
       // Remove old temporary file from session.
       filefield_clear_field_session($fieldname);
     }
-    $file_id = count($items) + count($_SESSION['filefield'][$fieldname]);
+        
+    $file_id = count($node_field) + count($_SESSION['filefield'][$fieldname]);
     $_SESSION['filefield'][$fieldname][$file_id] = $file;
   }
       
   // Load files from preview state. before committing actions.
-  if (!empty($_SESSION['filefield'][$fieldname])) {
+  if (is_array($_SESSION['filefield'][$fieldname]) && count($_SESSION['filefield'][$fieldname])) {
     foreach($_SESSION['filefield'][$fieldname] as $delta => $file) {
-      $items[] = $file;
+      $node_field[] = $file;
     }
   }
 }
 
-function _filefield_widget_form($node, $field, &$items) {
+function _filefield_widget_form($node, $field, &$node_field) {
   drupal_add_js('misc/progress.js');
   drupal_add_js('misc/upload.js');
-  drupal_add_js(drupal_get_path('module', 'filefield') .'/filefield.js');
-
 
   $fieldname = $field['field_name'];
   drupal_add_css(drupal_get_path('module', 'filefield') .'/filefield.css');
@@ -482,30 +409,14 @@ function _filefield_widget_form($node, $
     '#weight' => 100,
   );
 
-  // Construct the upload description out of user supplied text,
-  // maximum upload file size, and (optionally) allowed extensions.
-  $upload_description = empty($field['widget']['description'])
-    ? '' : ($field['widget']['description'] . '<br/>');
-
-  $upload_description .= t('Maximum file size: !size.', array(
-    '!size' => format_size(file_upload_max_size()),
-  ));
-
-  if (!empty($field['widget']['file_extensions'])) {
-    $upload_description .= ' ' . t('Allowed extensions: %ext.', array(
-      '%ext' => $field['widget']['file_extensions']
-    ));
-  }
-
   // Separate from tree becase of that silly things won't be displayed
   // if they are a child of '#type' = form issue
   $form[$fieldname]['new'][$fieldname .'_upload'] = array(
     '#type'  => 'file',
     '#title' => t('Attach new file'),
-    '#description' => $upload_description,
+    '#description' => $field['widget']['description'] . t('<br />Allowed extensions: %ext', array('%ext' => $field['widget']['file_extensions'])),
     '#weight' => 9,
     '#tree' => FALSE,
-    '#attributes' => array('accept' => str_replace(' ', '|', trim($field['widget']['file_extensions']))),
   );
 
   $form[$fieldname]['new']['upload'] = array(
@@ -517,14 +428,14 @@ function _filefield_widget_form($node, $
     '#weight' => 10,
   );
 
-  if (is_array($items) && count($items)) {
+  if (is_array($node_field) && count($node_field)) {
     $form[$fieldname]['files'] = array(
       '#parents' => array($fieldname),
       '#theme' => 'filefield_form_current',
       // remember the force_list setting so that the theme function knows
       '#force_list' => $field['force_list'],
     );
-    foreach($items as $delta => $file) {
+    foreach($node_field as $delta => $file) {
       // @todo: split into its own form and theme functions per file like imagefield
       if ($file['filepath'] && !$file['delete']) {
         $form[$fieldname]['files'][$delta] = _filefield_file_form($node, $field, $file);
@@ -577,30 +488,25 @@ function _filefield_widget_form($node, $
 function _filefield_file_form($node, $field, $file) {
   // Lets be a good boy and initialize our variables.
   $form = array();
-  $form['#after_build'] = array('_filefield_file_form_description_reset');
-
   $form['icon'] = array(
     '#type' => 'markup',
     '#value' => theme('filefield_icon', $file),
   );
 
-  $form['file_preview'] = array();
-
   $filepath = ($file['fid'] == 'upload')
               ? file_create_filename($file['filename'], file_create_path($field['widget']['file_path']))
               : $file['filepath'];
 
   $url = file_create_url($filepath);
+  $url = "<small>". check_plain($url) ."</small>";
 
   $form['description'] = array(
       '#type' => 'textfield', 
       '#default_value' => (strlen($file['description'])) ? $file['description'] : $file['filename'], '#maxlength' => 256, 
-      '#size' => 40,
-      '#attributes' => array('class' => 'filefield-description', 'size' => '40'),
   );
   $form['url'] = array(
     '#type' => 'markup',
-    '#value' => l($url, $url),
+    '#value' => t('URL: !url', array('!url' => $url)),
     '#prefix' => '<div class="filefield-edit-file-url">',
     '#suffix' => '</div>',
   );
@@ -635,10 +541,6 @@ function _filefield_file_form($node, $fi
   $form['filesize'] = array('#type' => 'value',  '#value' => $file['filesize']);
   $form['fid'] = array('#type' => 'value',  '#value' => $file['fid']);
 
-  // Remember the current filename for the check in
-  // _filefield_file_form_description_reset() that happens after submission.
-  $form['previous_filepath'] = array('#type' => 'hidden',  '#value' => $file['filepath']);
-
   foreach (module_implements('filefield') as $module) {
     $function = $module .'_filefield';
     $function('file_form', $node, $field, $file, $form);
@@ -646,56 +548,26 @@ function _filefield_file_form($node, $fi
   return $form;
 }
 
-/**
- * This after_build function is needed as fix for tricky Form API behaviour:
- * When using filefield without AJAX uploading, the description field was not
- * updated to a new '#default_value' because the textfield has been submitted,
- * which causes Form API to override the '#default_value'.
- *
- * That bug is fixed with this function by comparing the previous filename
- * to the new one, and resetting the description to the '#default_value'
- * if the filename has changed.
- */
-function _filefield_file_form_description_reset($form, $form_values) {
-  // Don't bother resetting the description of files that stay the same
-  if ($form['fid']['#value'] != 'upload') {
-    return $form;
-  }
-  // Get the previous filename for comparison with the current one.
-  $previous = $form['previous_filepath']['#post'];
-  foreach ($form['previous_filepath']['#parents'] as $parent) {
-    $previous = isset($previous[$parent]) ? $previous[$parent] : NULL;
-  }
-  // If a new file was uploaded (the file path changed), reset the description.
-  if ($previous != $form['filepath']['#value']) {
-    $form['description']['#value'] = $form['description']['#default_value'];
-  }
-  return $form;
-}
-
 
 /**
  * Validate the form widget.
  */
-function _filefield_widget_validate($node, $field, $items) {
-  
-  if (!$field['required']) {
-    return;
-  }
-  
-  // if there aren't any items.. throw an error.
-  if (!count($items)) {
-    form_set_error($field['field_name'], t('@field is required. Please upload a file.', array('@field' => $field['widget']['label'])));
-  }
-  else {
+function _filefield_widget_validate($node, $field, $node_field) {
+  if ($field['required']) {
     // Sum all the items marked for deletion, so we can make sure the end user
     // isn't deleting all of the files.
     $count_deleted = 0;
-    foreach($items as $item) {
-      $count_deleted += isset($item['delete']) && $item['delete'];
+    foreach($node_field as $item) {
+      if ($item['delete']) {
+        $count_deleted++;
+      }
     }
-    if (count($items) == $count_deleted) {
-      form_set_error($field['field_name'], t('@field is required. Please keep at least one file or upload a new one.', array('@field' => $field['widget']['label'])));
+
+    if (!count($node_field)) {
+      form_set_error($field['field_name'], $field['widget']['label'] .' is required. Please upload a file.');
+    }
+    else if (count($node_field) == $count_deleted) {
+      form_set_error($field['field_name'], $field['widget']['label'] .' is required. Please keep at least one file or upload a new one.');
     }
   }
 }
@@ -720,33 +592,17 @@ function filefield_field_formatter($fiel
     $item['list'] = 1; // always show the files if that option is enabled
   }
   if(!empty($item['fid'])) {
-    $item  =  array_merge($item, _filefield_file_load($item['fid']));
-  }
-  if (!empty($item['filepath'])) {
-    drupal_add_css(drupal_get_path('module', 'filefield') .'/filefield.css');
-    return theme('filefield', $item);
+    $file = _filefield_file_load($item['fid']);
   }
-}
-
-function _filefield_file_load($fid = NULL) {
-  // Don't bother if we weren't passed and fid.
-  if (!empty($fid) && is_numeric($fid)) {
-    $result = db_query('SELECT * FROM {files} WHERE fid = %d', $fid);
-    $file = db_fetch_array($result);
-    if ($file) {
-      // let modules load extended attributes.
-      $file += module_invoke_all('filefield', 'file_load', $node, $field, $file);
-      return $file;
-    }
+  if (!empty($file['filepath'])) {
+    return theme('filefield', array_merge($file, $item));
   }
-  // return an empty array if nothing was found.
-  return array();
 }
 
 function theme_filefield_form_current($form) {
   $header = $form['#force_list']
-            ? array('', t('Delete'), '',  t('Description'), t('Size'))
-            : array('', t('Delete'), t('List'), '',  t('Description'), t('Size'));
+            ? array(t('Delete'), t('Description'), t('Size'))
+            : array(t('Delete'), t('List'), t('Description'), t('Size'));
 
   foreach (element_children($form) as $key) {
     // Don't display (hidden) replaced items.
@@ -755,30 +611,31 @@ function theme_filefield_form_current($f
     }
 
     $row = array();
-    // we just going to lose this for now until we figure out how to handle it... 
-    $row[] = drupal_render($form[$key]['file_preview']);  
     $row[] = drupal_render($form[$key]['delete']);
     if (!$form['#force_list']) {
       $row[] = drupal_render($form[$key]['list']);
     }
-    $row[] = drupal_render($form[$key]['icon']);
-    $row[] = drupal_render($form[$key]['description']).
+    $row[] = drupal_render($form[$key]['icon']).
+             drupal_render($form[$key]['description']).
              drupal_render($form[$key]['url']);
     $row[] = drupal_render($form[$key]['size']);
     $rows[] = $row;
   }
-  $output = theme('table', $header, $rows, array('class' => 'filefield-filebrowser'));
+  $output = theme('table', $header, $rows);
   $output .= drupal_render($form);
   return $output;
 }
 
 function theme_filefield_icon($file) {
-  $dashed_mime = check_plain(strtr($file['filemime'], array('/' => '-')));
-
-  if ($icon_url = filefield_icon_url($file)) {
-    $icon = '<img class="field-icon-'. $dashed_mime .'" src="'. $icon_url .'" />';
+  $ext = array_pop(explode('.',$file['filename']));
+  $known_extensions = array('0','ace','aif','ai','ani','asf','asp','avi','bak','bat','bin','bmp','bz2','bz','cab','cdr','cfg','com','conf','cpt','css','cur','dat','db','dcr','dic','diff','dir','dll','dmg','doc','dwg','edir','eml','eps','exe','fla','flv','fon','gif','gz','hqx','html','htm','ico','inc','ini','iso','jpeg','jpg','js','lnk','log','m3u','mdb','midi','mid','mov','mp3','mpeg','mpg','nfo','odb','odc','odf','odg','odm','odp','ods','odt','ogg','otg','oth','otp','ots','ott','patch','pdf','php3','php','phtml','pl','png','pps','ppt','psd','pwl','qt','ram','ra','rar','reg','rpm','rtf','sh','shtml','sit','sql','svg','swf','sxc','sxi','sxw','sys','tar','tgz','tiff','tif','tmp','tpl','ttf','txt','wav','wma','wmv','wp','xls','xml','zip');
+  if (!in_array($ext, $known_extensions))  {
+    $ext = 0;
   }
-  return '<div class="filefield-icon field-icon-'. $dashed_mime .'">'. $icon .'</div>';
+  $imagepath = base_path() . drupal_get_path('module','filefield') .'/ico/'. $ext .'.png';
+
+  return '<div class="filefield-icon-container"><div class="filefield-icon field-icon-'. $ext .'"><img src="'. $imagepath .'" /></div></div>';
+  //return '<div class="filefield-icon-container"><div class="filefield-icon field-icon-'. $ext .'">&nbsp;</div></div>'."\n";
 }
 
 function theme_filefield_view_file($file) {
@@ -791,49 +648,57 @@ function theme_filefield($file) {
             ? file_create_filename($file['filename'], file_create_path($field['widget']['file_path']))
             : $file['filepath'];
 
-    $icon = theme('filefield_icon', $file);
     $url = file_create_url($path);
     $desc = $file['description'];
-    return '<div class="filefield-item">'. $icon . l($desc, $url) .'</div>';
+    return l($desc, $url);
   }
   return '';
 }
 
-function filefield_file_download($file) {
-  $file = file_create_path($file);
-
-  $result = db_query("SELECT * FROM {files} WHERE filepath = '%s'", $file);
-  if (!$file = db_fetch_object($result)) {
-    // We don't really care about this file.
-    return;
+if (!function_exists('upload_file_download')) {
+  function filefield_file_download($file) {
+    $file = file_create_path($file);
+    $result = db_query("SELECT * FROM {files} WHERE filepath = '%s'", $file);
+    if ($file = db_fetch_object($result)) {
+      if (user_access('view filefield uploads')) {
+        $node = node_load($file->nid);
+        if (node_access('view', $node)) {
+          $name = mime_header_encode($file->filename);
+          $type = mime_header_encode($file->filemime);
+          // Serve images and text inline for the browser to display rather than download.
+          $disposition = ereg('^(text/|image/)', $file->filemime) ? 'inline' : 'attachment';
+          return array(
+            'Content-Type: '. $type .'; name='. $name,
+            'Content-Length: '. $file->filesize,
+            'Content-Disposition: '. $disposition .'; filename='. $name,
+            'Cache-Control: private'
+          );
+        }
+        else {
+          return -1; 
+        }
+      }   
+      else {
+        return -1; 
+      }   
+    }   
   }
 
-  $node = node_load($file->nid);
-  if (!node_access('view', $node)) {
-    // You don't have permission to view the node
-    // this file is attached to.
-    return -1;
-  }
- 
-  // @todo: check the node for this file to be referenced in a field 
-  // to determine if it is managed by filefield. and do the access denied part here.
-  if (!user_access('view filefield uploads')) {
-    // sorry you do not have the proper permissions to view
-    // filefield uploads.
-    return -1;
-  }
+}
 
-  // Well I guess you can see this file.
-  $name = mime_header_encode($file->filename);
-  $type = mime_header_encode($file->filemime);
-  // Serve images and text inline for the browser to display rather than download.
-  $disposition = ereg('^(text/|image/)', $file->filemime) ? 'inline' : 'attachment';
-  return array(
-    'Content-Type: '. $type .'; name='. $name,
-    'Content-Length: '. $file->filesize,
-    'Content-Disposition: '. $disposition .'; filename='. $name,
-    'Cache-Control: private',
-  );
+/**
+ * Wrapper function for filefield_check_directory that accepts a form element
+ * to validate - if user specified one. Won't allow form submit unless the
+ * directory exists & is writable
+ * 
+ * @param $form_element
+ *   The form element containing the name of the directory to check.
+ */
+function filefield_form_check_directory($form_element) {
+  if(!empty($form_element['#value'])) {
+    filefield_check_directory($form_element['#value'], $form_element);
+  }
+  return $form_element;
 }
 
 /**
@@ -871,19 +736,19 @@ function filefield_js() {
   $field = content_fields($fieldname, $node->type); // load field data
 
   // Load fids stored by content.module.
-  $items = array();
-  $values = content_field('load', $node, $field, $items, FALSE, FALSE);
-  $items = $values[$fieldname];
+  $node_field = array();
+  $values = content_field('load', $node, $field, $node_field, FALSE, FALSE);
+  $node_field = $values[$fieldname];
 
   // Load additional field data.
-  filefield_field('load', $node, $field, $items, FALSE, FALSE);
+  filefield_field('load', $node, $field, $node_field, FALSE, FALSE);
 
   // Handle uploads and validation.
-  _filefield_widget_prepare_form_values($node, $field, $items);
-  _filefield_widget_validate($node, $field, $items);
+  _filefield_widget_prepare_form_values($node, $field, $node_field);
+  _filefield_widget_validate($node, $field, $node_field);
 
   // Get our new form baby, yeah tiger, get em!
-  $form = _filefield_widget_form($node, $field, $items);
+  $form = _filefield_widget_form($node, $field, $node_field);
 
   foreach (module_implements('form_alter') as $module) {
     $function = $module .'_form_alter';
@@ -897,220 +762,3 @@ function filefield_js() {
   print drupal_to_js(array('status' => TRUE, 'data' => $output));
   exit();
 }
-
-
-
-function filefield_token_list($type = 'all') {
-  if ($type == 'field' || $type == 'all') {
-    $tokens = array();
-    $tokens['file']['fid']         = t("File ID");
-    $tokens['file']['description'] = t("File description");
-    $tokens['file']['filename']    = t("File name");
-    $tokens['file']['filepath']    = t("File path");
-    $tokens['file']['filemime']    = t("File MIME type");
-    $tokens['file']['filesize']    = t("File size");
-    $tokens['file']['view']        = t("Fully formatted HTML file tag");
-    return $tokens;
-  }
-}
-
-function filefield_token_values($type, $object = NULL) {
-  if ($type == 'field') {
-    $item = $object[0];
-    $tokens['fid']         = $item['fid'];
-    $tokens['description'] = $item['description'];
-    $tokens['filename']    = $item['filename'];
-    $tokens['filepath']    = $item['filepath'];
-    $tokens['filemime']    = $item['filemime'];
-    $tokens['filesize']    = $item['filesize'];
-    $tokens['view']        = $item['view'];
-    return $tokens;
-  }
-}
-
-
-/**
- * Custom filter for filefield NOT NULL
- */
-function filefield_views_handler_filter_is_not_null($op, $filter, $filterinfo, &$query) {
-  if ($op == 'handler') {
-    $query->ensure_table($filterinfo['table']);
-    if ($filter['value']) {
-      $qs = '%s.%s > 0';
-    }
-    else {
-      $qs = '%s.%s = 0 OR %s.%s IS NULL';
-    }
-    $query->add_where($qs, $filterinfo['table'], $filterinfo['field'], $filterinfo['table'], $filterinfo['field']);
-  }
-}
-
-
-/**
- * Determine the most appropriate icon for the given file's mimetype.
- *
- * @return The URL of the icon image file, or FALSE if no icon could be found.
- */
-function filefield_icon_url($file) {
-  global $base_url;
-  $theme = variable_get('filefield_icon_theme', 'protocons');
-
-  if ($iconpath = _filefield_icon_path($file, $theme)) {
-    return $base_url .'/'. $iconpath;
-  }
-  return FALSE;
-}
-
-function _filefield_icon_path($file, $theme = 'protocons') {
-  // If there's an icon matching the exact mimetype, go for it.
-  $dashed_mime = strtr($file['filemime'], array('/' => '-'));
-  if ($iconpath = _filefield_create_icon_path($dashed_mime, $theme)) {
-    return $iconpath;
-  }
-  // For a couple of mimetypes, we can "manually" tell a generic icon.
-  if ($generic_name = _filefield_generic_icon_map($file)) {
-    if ($iconpath = _filefield_create_icon_path($generic_name, $theme)) {
-      return $iconpath;
-    }
-  }
-  // Use generic icons for each category that provides such icons.
-  foreach (array('audio', 'image', 'text', 'video') as $category) {
-    if (strpos($file['filemime'], $category .'/') === 0) {
-      if ($iconpath = _filefield_create_icon_path($category .'-x-generic', $theme)) {
-        return $iconpath;
-      }
-    }
-  }
-  // Try application-octet-stream as last fallback.
-  if ($iconpath = _filefield_create_icon_path('application-octet-stream', $theme)) {
-    return $iconpath;
-  }
-  // Sorry, no icon can be found...
-  return FALSE;
-}
-
-function _filefield_create_icon_path($iconname, $theme = 'protocons') {
-  $iconpath = drupal_get_path('module', 'filefield')
-    .'/icons/'. $theme .'/16x16/mimetypes/'. $iconname .'.png';
-  if (file_exists($iconpath)) {
-    return $iconpath;
-  }
-  return FALSE;
-}
-
-function _filefield_generic_icon_map($file) {
-  switch ($file['filemime']) {
-    // Word document types.
-    case 'application/msword':
-    case 'application/vnd.ms-word.document.macroEnabled.12':
-    case 'application/vnd.oasis.opendocument.text':
-    case 'application/vnd.oasis.opendocument.text-template':
-    case 'application/vnd.oasis.opendocument.text-master':
-    case 'application/vnd.oasis.opendocument.text-web':
-    case 'application/vnd.openxmlformats-officedocument.wordprocessingml.document':
-    case 'application/vnd.stardivision.writer':
-    case 'application/vnd.sun.xml.writer':
-    case 'application/vnd.sun.xml.writer.template':
-    case 'application/vnd.sun.xml.writer.global':
-    case 'application/vnd.wordperfect':
-    case 'application/x-abiword':
-    case 'application/x-applix-word':
-    case 'application/x-kword':
-    case 'application/x-kword-crypt':
-      return 'x-office-document';
-
-    // Spreadsheet document types.
-    case 'application/vnd.ms-excel':
-    case 'application/vnd.ms-excel.sheet.macroEnabled.12':
-    case 'application/vnd.oasis.opendocument.spreadsheet':
-    case 'application/vnd.oasis.opendocument.spreadsheet-template':
-    case 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet':
-    case 'application/vnd.stardivision.calc':
-    case 'application/vnd.sun.xml.calc':
-    case 'application/vnd.sun.xml.calc.template':
-    case 'application/vnd.lotus-1-2-3':
-    case 'application/x-applix-spreadsheet':
-    case 'application/x-gnumeric':
-    case 'application/x-kspread':
-    case 'application/x-kspread-crypt':
-      return 'x-office-spreadsheet';
-
-    // Presentation document types.
-    case 'application/vnd.ms-powerpoint':
-    case 'application/vnd.ms-powerpoint.presentation.macroEnabled.12':
-    case 'application/vnd.oasis.opendocument.presentation':
-    case 'application/vnd.oasis.opendocument.presentation-template':
-    case 'application/vnd.openxmlformats-officedocument.presentationml.presentation':
-    case 'application/vnd.stardivision.impress':
-    case 'application/vnd.sun.xml.impress':
-    case 'application/vnd.sun.xml.impress.template':
-    case 'application/x-kpresenter':
-      return 'x-office-presentation';
-
-    // Compressed archive types.
-    case 'application/zip':
-    case 'application/x-zip':
-    case 'application/stuffit':
-    case 'application/x-stuffit':
-    case 'application/x-7z-compressed':
-    case 'application/x-ace':
-    case 'application/x-arj':
-    case 'application/x-bzip':
-    case 'application/x-bzip-compressed-tar':
-    case 'application/x-compress':
-    case 'application/x-compressed-tar':
-    case 'application/x-cpio-compressed':
-    case 'application/x-deb':
-    case 'application/x-gzip':
-    case 'application/x-java-archive':
-    case 'application/x-lha':
-    case 'application/x-lhz':
-    case 'application/x-lzop':
-    case 'application/x-rar':
-    case 'application/x-rpm':
-    case 'application/x-tzo':
-    case 'application/x-tar':
-    case 'application/x-tarz':
-    case 'application/x-tgz':
-      return 'package-x-generic';
-
-    // Script file types.
-    case 'application/ecmascript':
-    case 'application/javascript':
-    case 'application/mathematica':
-    case 'application/vnd.mozilla.xul+xml':
-    case 'application/x-asp':
-    case 'application/x-awk':
-    case 'application/x-cgi':
-    case 'application/x-csh':
-    case 'application/x-m4':
-    case 'application/x-perl':
-    case 'application/x-php':
-    case 'application/x-ruby':
-    case 'application/x-shellscript':
-    case 'text/vnd.wap.wmlscript':
-    case 'text/x-emacs-lisp':
-    case 'text/x-haskell':
-    case 'text/x-literate-haskell':
-    case 'text/x-lua':
-    case 'text/x-makefile':
-    case 'text/x-matlab':
-    case 'text/x-python':
-    case 'text/x-sql':
-    case 'text/x-tcl':
-      return 'text-x-script';
-
-    // HTML aliases.
-    case 'application/xhtml+xml':
-      return 'text-html';
-
-    // Executable types.
-    case 'application/x-macbinary':
-    case 'application/x-ms-dos-executable':
-    case 'application/x-pef-executable':
-      return 'application-x-executable';
-
-    default:
-      return FALSE;
-  }
-}
