Index: field_file.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/flexinode/field_file.inc,v
retrieving revision 1.12
diff -u -u -p -r1.12 field_file.inc
--- field_file.inc	16 Apr 2005 12:54:16 -0000	1.12
+++ field_file.inc	2 Aug 2005 17:27:18 -0000
@@ -1,6 +1,11 @@
 <?php
 // $Id: field_file.inc,v 1.12 2005/04/16 12:54:16 JonBob Exp $
 
+// indexes into options array
+define('FLEXINODE_FILE_DESTINATION', 1);
+define('FLEXINODE_FILE_PERMISSION', 2);
+
+
 function flexinode_field_file_name($field) {
   return t('file');
 }
@@ -23,9 +28,28 @@ function flexinode_field_file_db_sort_co
 
 function flexinode_field_file_insert($field, $node) {
   $fieldname = 'flexinode_'. $field->field_id;
-  $node->$fieldname = file_save_upload($node->$fieldname, $node->$fieldname->filename);
+  // either overwrite existing file, or use destination specific to this field
+  $default_dest = variable_get('file_directory_path', 'files');
+  $dest = $default_dest . '/' .$field->options[FLEXINODE_FILE_DESTINATION];
+
+  // TODO: handle case when file_check_directory fails
+  // file_check_directory will attempt to create a directory if it does not exist
+  // how do I abort the insert if directory creation fails???
+  file_check_directory($dest, FILE_CREATE_DIRECTORY, $fieldname);
+
+  $node->$fieldname = file_save_upload($node->$fieldname, $dest, FILE_EXISTS_RENAME);
+
+  // when downloading, the textual_data field must match the
+  // ?file=... parameter as generated by file_create_url.  So for
+  // instance if this node has a file located in
+  // files/private_stuff/foo.txt, we need the string
+  // "private_stuff/foo.txt"
+  // so we emulate file_create_url here.  If the code there changes, this could break
+  $urlpath = trim(substr($node->$fieldname->filepath, strlen($default_dest)), '\\/');
+
   $serialized = is_object($node->$fieldname) ? serialize($node->$fieldname) : '';
-  db_query("INSERT INTO {flexinode_data} (nid, field_id, textual_data, serialized_data) VALUES (%d, %d, '%s', '%s')", $node->nid, $field->field_id, $node->$fieldname->filename, $serialized);
+
+  db_query("INSERT INTO {flexinode_data} (nid, field_id, textual_data, serialized_data) VALUES (%d, %d, '%s', '%s')", $node->nid, $field->field_id, $urlpath, $serialized);
 }
 
 function flexinode_field_file_delete($field, $node, $unconditional = 0) {
@@ -61,6 +85,20 @@ function flexinode_field_file_load($fiel
   return unserialize($node->$fieldname);
 }
 
+function flexinode_field_file_config($field, $edit) {
+  $option_fields .= form_textfield(t('Save File In'),
+								   'options][',
+								   $edit['options'][FLEXINODE_FILE_DESTINATION],
+								   60, 128);
+  // TODO: dropdown list of all known permissions, to avoid typos
+  $option_fields .= form_textfield(t('Permission Required For Download'),
+								   'options][',
+								   $edit['options'][FLEXINODE_FILE_PERMISSION],
+								   60, 128);
+  return form_group(t('Options'), $option_fields,
+					t('Specify a subdirectory of %default_dest where this file should be saved, and require permission to download.  Leave blank to allow anyone to download.', array('%default_dest' => variable_get('file_directory_path', 'files'))));
+}
+
 
 /**
  * @addtogroup themeable
Index: flexinode.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/flexinode/flexinode.module,v
retrieving revision 1.50
diff -u -u -p -r1.50 flexinode.module
--- flexinode.module	25 Jul 2005 16:43:34 -0000	1.50
+++ flexinode.module	2 Aug 2005 17:27:18 -0000
@@ -716,8 +716,29 @@ function flexinode_content($node, $tease
  */
 function flexinode_file_download($file) {
   if (!$file) return false;
-  $result = db_fetch_object(db_query("SELECT f.* FROM {flexinode_data} f WHERE f.textual_data = '%s'", $file));
+  $result = db_fetch_object(db_query("SELECT f.*, ff.options FROM {flexinode_data} f LEFT JOIN {flexinode_field} ff ON f.field_id=ff.field_id WHERE f.textual_data = '%s'", $file));
   if (!$result) return false;
+
+  // check if file has permissions associated with it
+  $options = unserialize($result->options);
+  $permission = $options[FLEXINODE_FILE_PERMISSION];
+  if ($permission && !user_access($permission)) {
+	// returning -1 will cause access to be denied.  A watchdog entry will be written.  However, because it may be difficult for an admin to determine why access is denied, write a more verbose message here.
+	watchdog('access denied', t("%page denied access to download files from node %nid because user does not have '%perm' permission.", array('%page' => $file, '%nid' => $result->nid, '%perm' => $permission)), WATCHDOG_NOTICE);
+	return -1;
+  }
+  // Here I try to limit access to the file only if the user can view the node.
+  // I was thinking node_access would call into the taxonomy_access hooks,
+  // but it doesn't work that way.  Instead it calls flexinode_access() which is only about creating and editing flexinodes.
+  // Anyone know how I can limit access only to those who can view the node???
+  /*  -- doesn't work, commented out.
+  if (!node_access('view', array('nid' => $result->nid))) {
+	watchdog('access denied', t("%page denied access because user is denied access to view node %nid.", array('%page' => $file, '%nid' => $result->nid)), WATCHDOG_NOTICE);
+	return -1;
+  }
+  */
+
+  // file exists and user has permission to download
   $filedb = unserialize($result->serialized_data);
   if ($filedb->type) {
     return array('Content-type: '. $filedb->type, 'Content-Disposition: attachment; filename="'. $file .'"');
