Index: uploadpath.module
===================================================================
--- uploadpath.module	(revision 4330)
+++ uploadpath.module	(working copy)
@@ -46,28 +46,94 @@
     '#type' => 'fieldset',
     '#collapsible' => TRUE,
     '#collapsed' => TRUE,
-    '#description' => t('Other settings'),
     '#weight' => -6
   );
   
-  $form['misc']['uploadpath_bugfix1'] = array(
+  $form['misc']['filenames'] = array(
+    '#title' => t('Filenames'),
+    '#type' => 'fieldset',
+    '#weight' => 0
+  );
+  $form['misc']['filenames']['uploadpath_semantic_filenames'] = array(
     '#type' => 'checkbox',
-    '#title' => t('Set node created and updated time, if not set'),
+    '#title' => t('Semantic filenames'),
     '#return_value' => 1,
-    '#default_value' => variable_get('uploadpath_bugfix1', true),
-    '#description' => t('This is a bugfix for this issue http://drupal.org/node/153737 where [yyyy] etc isn\'t evaluated properly and is only useful if you\'re using date tokens in your paths.'),
+    '#default_value' => variable_get('uploadpath_semantic_filenames', false),
+    '#description' => t('If the file has a description set, use that instead of the filename.  If not, use the node title.'),
     '#weight' => 0,
   );
+  $form['misc']['filenames']['uploadpath_clean_filenames'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Remove non-alphanumeric filename characters.'),
+    '#return_value' => 1,
+    '#default_value' => variable_get('uploadpath_clean_filenames', false),
+    '#weight' => 1,
+  );
+  $form['misc']['filenames']['uploadpath_clean_filenames_underscores'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Replace non-alphanumeric filename characters with underscores.'),
+    '#return_value' => 1,
+    '#default_value' => variable_get('uploadpath_clean_filenames_underscores', false),
+    '#weight' => 2,
+  );
+  $form['misc']['filenames']['uploadpath_lowercase_filenames'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Make all filenames lowercase.'),
+    '#return_value' => 1,
+    '#default_value' => variable_get('uploadpath_lowercase_filenames', false),
+    '#weight' => 3,
+  );
+  $form['misc']['filenames']['uploadpath_limit_length'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Limit filename length to 50 characters (not including path, unique id, or extension)'),
+    '#return_value' => 1,
+    '#default_value' => variable_get('uploadpath_limit_length', true),
+    '#weight' => 4,
+  );
+  $form['misc']['filenames']['uploadpath_uniqueid'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Append a unique id to upload filenames'),
+    '#return_value' => 1,
+    '#default_value' => variable_get('uploadpath_uniqueid', false),
+    '#weight' => 5,
+  );
   
-  $form['misc']['uploadpath_clean_filenames'] = array(
+  $form['misc']['paths'] = array(
+    '#title' => t('Paths'),
+    '#type' => 'fieldset',
+    '#weight' => 1
+  );
+  $form['misc']['paths']['uploadpath_clean_paths'] = array(
     '#type' => 'checkbox',
-    '#title' => t('Clean file upload filenames'),
+    '#title' => t('Remove non-alphanumeric path characters.'),
     '#return_value' => 1,
-    '#default_value' => variable_get('uploadpath_clean_filenames', true),
-    '#description' => t('Rename uploaded files based on file desc node title. characters other than numbers and letters are replaced with underscore and a unique id is appended. maximum total length is 60 characters.'),
+    '#default_value' => variable_get('uploadpath_clean_paths', false),
     '#weight' => 0,
   );
+  $form['misc']['paths']['uploadpath_clean_paths_underscores'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Replace non-alphanumeric path characters with underscores.'),
+    '#return_value' => 1,
+    '#default_value' => variable_get('uploadpath_clean_paths_underscores', false),
+    '#weight' => 1,
+  );
+  $form['misc']['paths']['uploadpath_lowercase_paths'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Make all paths lowercase.'),
+    '#return_value' => 1,
+    '#default_value' => variable_get('uploadpath_lowercase_paths', false),
+    '#weight' => 2,
+  );
   
+  $form['misc']['uploadpath_bugfix1'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Set node created and updated time, if not set'),
+    '#return_value' => 1,
+    '#default_value' => variable_get('uploadpath_bugfix1', true),
+    '#description' => t('This is a bugfix for this issue http://drupal.org/node/153737 where [yyyy] etc isn\'t evaluated properly and is only useful if you\'re using date tokens in your paths.'),
+    '#weight' => 10,
+  );
+  
   $form['node_types_exclude'] = array(
     '#title' => t('Excluded node types'),
     '#type' => 'fieldset',
@@ -154,31 +220,59 @@
 		            $pattern = variable_get('uploadpath_prefix', '');
 	            }
                     
-                if(variable_get('uploadpath_clean_filenames', false) && $node->title){
-                  //convert filename into semantic name based on node title :-)
-                  if($node->files[$key]['description'] && strlen($node->files[$key]['description']) > 3){
-                    $filename_root = $node->files[$key]['description']; //base filename on file desc
-                  }else{
-                    $filename_root = $node->title; //base filename on node title
-                  }
-                  //drupal_set_message($filename_root);
-                  //get path info of file
-                  $file_info = pathinfo($node->files[$key]['filename']);
-                  /*crop lowercase node title to 35 chars max
-                    replace anything except numbers and letters with underscore
-                    add 10 digit unique id and file extension*/
-                  $file_name = preg_replace("/([^a-z0-9])/", '_', strtolower($filename_root));
-                  $file_name = str_replace('__','_', $file_name);
-                  $file_name = substr($file_name, 0, 50);
-                  $file_name = preg_replace("/([^a-z0-9])/", '_', $file_name);
-                  $file_name .= '_'. substr(uniqid(),0,10). '.'. $file_info['extension'];
-                  // apply new, prefixed file name by token replacing the path pattern
-                  $file_path = str_replace(array(' ', "\n", "\t"), '_', token_replace($pattern . '/', 'node', $node));
-                  $file_name = $file_path . $file_name;
-                }else{
-                  // apply new, prefixed file name by token replacing the path pattern
-                  $file_name = str_replace(array(' ', "\n", "\t"), '_', token_replace($pattern . '/', 'node', $node)) . $node->files[$key]['filename'];                      
-                }
+
+                    $original_filename = $node->files[$key]['filename'];
+                    $original_fileinfo = pathinfo($original_filename);
+
+                    $new_filename = $original_filename;
+                    if(variable_get('uploadpath_semantic_filenames', false)) {
+                      // if the file has a nontrivial description, use that as the base filename; otherwise use the node title if it's set
+                      if($node->files[$key]['description'] && strlen($node->files[$key]['description']) > 3) {
+                        $new_filename = $node->files[$key]['description']; //base filename on file desc
+                      } elseif($node->title) {
+                        $new_filename = $node->title; //base filename on node title
+                      }
+                    }
+
+                    if(variable_get('uploadpath_lowercase_filenames', false)) {
+                      $new_filename = strtolower($new_filename);
+                    }
+                    if(variable_get('uploadpath_clean_filenames', false)) {
+                      $new_filename = preg_replace('/([^A-Za-z0-9.])/', '', $new_filename);
+                    }
+                    if(variable_get('uploadpath_clean_filenames_underscores', false)) {
+                      $new_filename = preg_replace('/([^A-Za-z0-9.])/', '_', $new_filename);
+                      $new_filename = preg_replace('/_+/','_', $new_filename);
+                    }
+
+                    if(variable_get('uploadpath_limit_length', false)) {
+                      $new_filename = substr($new_filename, 0, 50);
+                    }
+
+                    if(variable_get('uploadpath_uniqueid', false)) {
+                      $new_filename .= '_' . substr(md5(uniqid()),0,10);
+                    }
+
+                    if( variable_get('uploadpath_semantic_filenames', false) || variable_get('uploadpath_uniqueid', false) ) {
+                      // append the original extension to our newly-generated filename
+                      $new_filename .= '.'. $original_fileinfo['extension'];
+                    }
+
+                    $file_path = str_replace(array(' ', "\n", "\t"), '_', token_replace($pattern . '/', 'node', $node));
+                    if(variable_get('uploadpath_lowercase_paths', false)) {
+                      $file_path = strtolower($file_path);
+                    }
+                    if(variable_get('uploadpath_clean_paths', false)) {
+                      $file_path = preg_replace('/([^A-Za-z0-9\/])/', '', $file_path);
+                    }
+                    if(variable_get('uploadpath_clean_paths_underscores', false)) {
+                      $file_path = preg_replace('/([^A-Za-z0-9\/])/', '_', $file_path);
+                      $file_path = preg_replace('/_+/','_', $file_path);
+                    }
+
+                    $file_name = $file_path . $new_filename;
+
+
                 // SECURITY NOTE:
                 // Tokens include user supplied information and could provide an attack vector.
                 // The current method of creating directories prevents the use of .. or other malicious
