Index: filefield_sources.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/filefield_sources/filefield_sources.module,v
retrieving revision 1.7
diff -u -r1.7 filefield_sources.module
--- filefield_sources.module	13 Mar 2010 01:00:59 -0000	1.7
+++ filefield_sources.module	17 Jun 2010 20:11:45 -0000
@@ -280,6 +280,25 @@
 }
 
 /**
+ * If the transliteration module is available, clean up the file name.
+ */
+function filefield_sources_transliterate($filepath) {
+  if (!module_exists('transliteration')) {
+    return $filepath;
+  }
+
+  module_load_include('inc', 'transliteration');
+
+  $langcode = NULL;
+  if (!empty($_POST['language'])) {
+    $languages = language_list();
+    $langcode = isset($languages[$_POST['language']]) ? $_POST['language'] : NULL;
+  }
+
+  return dirname($filepath) . '/' . transliteration_clean_filename(basename($filepath), $langcode);
+}
+
+/**
  * Theme the display of the sources list.
  */
 function theme_filefield_sources_list($element, $sources) {
Index: sources/reference.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/filefield_sources/sources/reference.inc,v
retrieving revision 1.5
diff -u -r1.5 reference.inc
--- sources/reference.inc	17 Jun 2010 00:10:20 -0000	1.5
+++ sources/reference.inc	17 Jun 2010 20:11:45 -0000
@@ -70,7 +70,8 @@
     $return['sources_reference'] = array(
       '#title' => t('Autocomplete reference options'),
       '#type' => 'fieldset',
-      '#collapsible' => FALSE,
+      '#collapsible' => TRUE,
+      '#collapsed' => TRUE,
     );
 
     $return['sources_reference']['filefield_source_autocomplete'] = array(
Index: sources/attach.inc
===================================================================
RCS file: sources/attach.inc
diff -N sources/attach.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sources/attach.inc	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,252 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * A FileField extension to allow use of files within a server directory.
+ *
+ * The "hooks" in this file are not true hooks, they're called individually
+ * from the main filefield_sources.module in the corresponding hook by the
+ * same name. Any of these hooks could be broken out into a separate module.
+ */
+
+define('FILEFIELD_SOURCE_ATTACH_HINT_TEXT', '0');
+
+/**
+ * Implementation of hook_filefield_source_info().
+ */
+function filefield_source_attach_info() {
+  $source = array();
+  $source['attach'] = array(
+    'name' => t('File attach'),
+    'label' => t('File attach'),
+    'description' => t('Select a file from a local file location on the server.'),
+    'process' => 'filefield_source_attach_process',
+    'value' => 'filefield_source_attach_value',
+  );
+  return $source;
+}
+
+/**
+ * Implementation of hook_theme().
+ */
+function filefield_source_attach_theme() {
+  return array(
+    'filefield_source_attach_element' => array(
+      'arguments' => array('element' => NULL),
+      'file' => 'sources/attach.inc',
+    ),
+ );
+}
+
+/**
+ * Implementation of hook_filefield_source_settings().
+ */
+function filefield_source_attach_settings($op, $field) {
+  $return = array();
+
+  if ($op == 'form') {
+    $return['source_attach'] = array(
+      '#title' => t('File attach settings'),
+      '#type' => 'fieldset',
+      '#collapsible' => TRUE,
+      '#collapsed' => TRUE,
+      '#description' => t('File attach allows for selecting a file from a local file location on the server, commonly used in combination with FTP.'),
+      '#weight' => 1,
+    );
+    $return['source_attach']['filefield_source_attach_path'] = array(
+      '#type' => 'textfield',
+      '#title' => t('File attach path'),
+      '#default_value' => empty($field['filefield_source_attach_path']) ? 'file_attach' : $field['filefield_source_attach_path'],
+      '#size' => 60,
+      '#maxlength' => 128,
+      '#required' => FALSE,
+      '#description' => t('Subdirectory within the "@files" Directory where files will be stored. If a path is not provided, the attach option will not be active.', array('@files' => file_directory_path())),
+      '#element_validate' => array('_filefield_source_attach_file_path_validate'),
+      '#suffix' => theme('token_help', 'user'),
+    );
+    $return['source_attach']['filefield_source_attach_absolute'] = array(
+      '#type' => 'checkbox', 
+      '#title' => t('Use absolute path'),
+      '#default_value' => $field['filefield_source_attach_absolute'],
+      '#description' => t('If checked file attach will not use Drupal files directory and will try use the file attach path from the root of your server. If your File attach path does not start with a "/" your path will be relative to your site\'s real path: %realpath.', array('%realpath' => realpath('./'))),
+    );
+  }
+  elseif ($op == 'save') {
+    $return[] = 'filefield_source_attach_absolute';
+    $return[] = 'filefield_source_attach_path';
+  }
+
+  return $return;
+}
+
+function _filefield_source_attach_file_path_validate($element, &$form_state) {
+  // Strip slashes from the beginning and end of $widget['file_path']
+  $form_state['values']['file_path'] = trim($form_state['values']['file_path'], '\\/');
+
+  // Do not allow the file path to be the same as the file_directory_path().
+  // This causes all sorts of problems with things like file_create_url().
+  if (strpos($form_state['values']['file_path'], file_directory_path()) === 0) {
+    form_error($element, t('The file path (@file_path) cannot start with the system files directory (@files_directory), as this may cause conflicts when building file URLs.', array('@file_path' => $form_state['values']['file_path'], '@files_directory' => file_directory_path())));
+  }  
+}
+
+/**
+ * A #process callback to extend the filefield_widget element type.
+ */
+function filefield_source_attach_process($element, $edit, &$form_state, $form) {
+
+  $field = content_fields($element['#field_name'], $element['#type_name']);
+
+  $element['filefield_attach'] = array(
+    '#theme' => 'filefield_source_attach_element',
+    '#weight' => 100.5,
+    '#access' => empty($element['fid']['#value']),
+    '#filefield_sources_hint_text' => FILEFIELD_SOURCE_ATTACH_HINT_TEXT,
+  );
+
+  $allowed_extensions = implode('|', $element['#upload_validators']['filefield_validate_extensions']);  
+  $path = _filefield_source_attach_directory($field['widget'], $GLOBALS['user']);
+  $options = _filefield_source_attach_get($path, $allowed_extensions);
+
+  // Error messages.
+  if ($options === FALSE || empty($field['widget']['filefield_source_attach_path'])) {
+    $attach_message = t('A file attach directory could not be located.');
+    $attach_description = t('Please check your settings for the %field field.',  array('%field' => $field['widget']['label']));
+  }
+  elseif (!count($options)) {
+    $attach_message = t('There currently no files to attach.');
+    $attach_description = t('Files may be uploaded via to the %directory directory and they will be available to attach here.', array('%directory' => _filefield_source_attach_directory($field['widget'])));
+  }
+
+  if (isset($attach_message)) {
+    $element['filefield_attach']['attach_message'] = array(
+      '#type' => 'item',
+      '#value' => $attach_message,
+      '#description' => $attach_description
+    );
+    return $element;
+  }
+
+  $element['filefield_attach']['path'] = array(
+    '#type' => 'select',
+    '#description' => t('Select available files to attach. If a file is larger than the max upload site please use this method to add files. To add files to this select list you need to upload files using FTP.'),
+    '#options' => $options,
+  );
+
+  $element['filefield_attach']['attach'] = array(
+    '#type' => 'submit',
+    '#value' => t('Attach'),
+    '#submit' => array('node_form_submit_build_node'),
+    '#ahah' => array(
+       'path' => 'filefield/ahah/'. $element['#type_name'] .'/'. $element['#field_name'] .'/'. $element['#delta'],
+       'wrapper' => $element['#id'] .'-ahah-wrapper',
+       'method' => 'replace',
+       'effect' => 'fade',
+    ),
+  );
+
+  return $element;
+}
+
+function _filefield_source_attach_get($path, $allowed_extensions = '.*', $existing = array()) {
+  if (!file_check_directory($path, FILE_CREATE_DIRECTORY)) {
+    drupal_set_message(t('Specified file attach path must exist or be writable.'), 'error');
+    return FALSE;
+  }
+
+  $file_exists = array();
+  $file_attach_options = array();
+  $file_attach = file_scan_directory($path, '.*', array('.', '..', 'CVS', '.svn'), 0, TRUE, $key = 'filename', 0, 0);
+
+  if (count($file_attach)) {
+    $file_attach_options = array('');
+    foreach ($existing as $file_exist) {
+      if (!in_array(basename($file_exist['filepath']), $file_exists)) {
+        $file_exists[] = basename($file_exist['filepath']);
+      }
+    }
+    foreach ($file_attach as $filename => $fileinfo) {
+      $is_attached = '';
+      if (in_array($filename, $file_exists)) {
+        $is_attached = '(A)';
+      }
+      $filepath = str_replace($path, '', $filename);
+      $filepath = trim($filepath, '/');
+      $file_attach_options[$filepath] = $is_attached . ' ' . $filepath;
+    }
+  }
+
+  asort($file_attach_options);
+  return $file_attach_options;
+}
+
+/**
+ * A #filefield_value_callback function.
+ */
+function filefield_source_attach_value($element, &$item) {
+  if (!empty($item['filefield_attach']['path']) && $item['filefield_attach']['path'] !== '0') {
+    $field = content_fields($element['#field_name'], $element['#type_name']);
+    $attach_path = _filefield_source_attach_directory($field['widget'], $GLOBALS['user']);
+    $filename = $attach_path . '/' . $item['filefield_attach']['path'];
+
+    $temp = file_directory_temp();
+
+    if (!file_copy($filename, $temp)) {
+      form_error($element, t('File attach copy error. Please confirm you temp directory is writeable. See !status for setup errors.' , array('!status' => l('status report', 'admin/reports/status'))));
+      return;
+    }
+
+    $filepath = $temp . '/' . basename($filename);  
+    
+    // Perform basic extension check on the file before trying to attach.
+    $extensions = $field['widget']['file_extensions'];
+    $regex = '/\.('. ereg_replace(' +', '|', preg_quote($extensions)) .')$/i';
+    if (!empty($extensions) && !preg_match($regex, $filename)) {
+      form_error($element, t('Only files with the following extensions are allowed: %files-allowed.', array('%files-allowed' => $extensions)));
+      return;
+    }
+
+    // Transliterate the file name if available.
+    $new_filepath = filefield_sources_transliterate($filepath);
+    rename($filepath, $new_filepath);
+    $filepath = $new_filepath;
+
+    if ($file = field_file_save_file($filepath, array(), filefield_widget_file_path($field))) {
+      $item = array_merge($item, $file);
+    }
+
+    // Delete the original file.
+    @unlink($filepath);
+  }
+
+  $item['filefield_attach']['path'] = '';
+}
+
+/**
+ * Theme the output of the autocomplete field.
+ */
+function theme_filefield_source_attach_element($element) {
+  if (isset($element['attach_message'])) {
+    $output = '<p>' . theme('form_element', $element['attach_message'], $element['attach_message']['#value']) . '</p>';
+  }
+  else {
+    $output = theme('select', $element['path']) . theme('submit', $element['attach']);
+  }
+  return '<div class="filefield-source filefield-source-attach clear-block">' . theme('form_element', $element, $output) . '</div>';
+}
+
+function _filefield_source_attach_directory($field, $account = NULL) {
+  $account  = isset($account) ? $account : $GLOBALS['user'];  
+  $path     = $field['filefield_source_attach_path'];
+  $absolute = $field['filefield_source_attach_absolute'];
+
+  // Replace user level tokens.
+  // Node level tokens require a lot of complexity like temporary storage
+  // locations when values don't exist. See the filefield_paths module.
+  if (module_exists('token')) {
+    $path = token_replace($path, 'user', $account);
+  }
+
+  return $absolute ? $path : file_directory_path() . '/' . $path;
+}
