Index: upload.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/upload.module,v
retrieving revision 1.31.2.5
diff -u -F^f -r1.31.2.5 upload.module
--- upload.module	25 May 2005 04:28:59 -0000	1.31.2.5
+++ upload.module	24 Jul 2005 21:11:33 -0000
@@ -15,6 +15,8 @@ function upload_help($section) {
       return t('Allows users to upload and attach files to content.');
     case 'admin/settings/upload':
       return t('<p>Users with the <a href="%permissions">upload files permission</a> can upload attachments. You can choose which post types can take attachments on the <a href="%types">content types settings</a> page.</p>', array('%permissions' => url('admin/access'), '%types' => url('admin/node/configure/types')));
+    case 'admin/uploads':
+      return t('<p>Users with the <a href="%permissions">administer uploaded files permission</a> can administer uploaded files.</p>', array('%permissions' => url('admin/access')));
   }
 }
 
@@ -22,7 +24,7 @@ function upload_help($section) {
  * Implementation of hook_perm().
  */
 function upload_perm() {
-  return array('upload files', 'view uploaded files');
+  return array('upload files', 'view uploaded files', 'administer uploaded files');
 }
 
 /**
@@ -56,10 +58,16 @@ function upload_menu($may_cache) {
   if ($may_cache) {
     $items[] = array(
       'path' => 'admin/settings/upload', 'title' => t('uploads'),
+      'callback' => 'upload_settings',
+      'access' => user_access('administer uploaded files'));
+    $items[] = array(
+      'path' => 'upload', 'title' => t('my uploads'),
+      'callback' => 'upload_page',
+      'access' => user_access('upload files'));
+    $items[] = array(
+      'path' => 'admin/upload', 'title' => t('uploads'),
       'callback' => 'upload_admin',
-      'access' => user_access('administer site configuration'),
-      'type' => MENU_NORMAL_ITEM
-    );
+      'access' => user_access('administer uploaded files'));
   }
   else {
     // Add handlers for previewing new uploads.
@@ -80,7 +88,208 @@ function upload_menu($may_cache) {
   return $items;
 }
 
+/*
+ * Menu callback:
+ * Page where admins manage uploaded files
+ */
 function upload_admin() {
+
+  $operations = array(
+    'delete' =>    array(t('Delete the selected files'), '')
+  );
+
+  // Handle operations
+  $op = $_POST['op'];
+  $edit = $_POST['edit'];
+
+  if (($op == t('Update') || $op == t('Delete all')) && isset($edit['operation']) && isset($edit['files'])) {
+    $edit['files'] = array_diff($edit['files'], array(0));
+    if (count($edit['files']) == 0) {
+      form_set_error('', t('Please select some items to perform the update on.'));
+    }
+    else {
+      if ($edit['operation'] == 'delete') {
+        // Mass delete
+        if ($edit['confirm']) {
+          upload_delete('files', $edit['files']);
+          drupal_set_message(t('The items have been deleted.'));
+        }
+        else {
+          $extra = '<ul>';
+          foreach ($edit['files'] as $fid => $value) {
+            if ($value) {
+              $title = db_result(db_query('SELECT filename FROM {files} WHERE fid = %d', $fid));
+              $extra .= '<li>'. form_hidden('files]['. $fid, 1) . check_plain($title) .'</li>';
+            }
+          }
+          $extra .= '</ul>';
+          $extra .= form_hidden('operation', 'delete');
+
+          $output = theme('confirm',
+                          t('Are you sure you want to delete these items?'),
+                          'admin/upload',
+                          t('This action cannot be undone.'),
+                          t('Delete all'),
+                          t('Cancel'),
+                          $extra);
+          print theme('page', $output);
+          return;
+        }
+      }
+    }
+  }
+
+  $header = array(
+    NULL,
+    array('data' => t('Filename'), 'field' => 'filename'),
+    array('data' => t('Title'), 'field' => 'title'),
+    array('data' => t('Author'), 'field' => 'name'),
+    array('data' => t('Size'), 'field' => 'filesize', 'sort' => 'desc'),
+    array('data' => t('Operations'))
+  );
+
+  $sql = "SELECT f.fid, n.nid, n.status, n.title, f.filename, f.filepath, f.filesize, n.uid, u.name FROM {files} f INNER JOIN {node} n ON f.nid = n.nid INNER JOIN {users} u ON u.uid = n.uid";
+  $sql .= tablesort_sql($header);
+  $result = pager_query($sql, 50);
+
+  // Make sure the update controls are disabled if we don't have any rows 
+  // to select from.
+  $disabled = !db_num_rows($result);
+
+  $options = array();
+  foreach ($operations as $key => $value) {
+    $options[$key] = $value[0];
+  }
+
+  $form = form_select(NULL, 'operation', 0, $options, NULL, ($disabled ? 'disabled="disabled"' : ''));
+  $form .= form_submit(t('Update'), 'op', ($disabled ? array('disabled' => 'disabled') : array()));
+
+  $output .= form_group(t('Update options'), "<div class=\"container-inline\">$form</div>");
+
+  $destination = drupal_get_destination();
+  while ($file = db_fetch_object($result)) {
+    $rows[] = array(
+      form_checkbox(NULL, 'files]['. $file->fid, 1, 0),
+      l($file->filename, file_create_url(($file->fid ? $file->filepath : file_create_filename($file->filename, file_create_path())))),
+      ($file->status) ? l($file->title, "node/$file->nid") : $file->title,
+      format_name($file->name),
+      format_size($file->filesize),
+      t('delete')
+    );
+  }
+
+  if ($pager = theme('pager', NULL, 50, 0, tablesort_pager())) {
+    $rows[] = array(array('data' => $pager, 'colspan' => '6'));
+  }
+
+  if (!$rows) {
+    $rows[] = array(array('data' => t('No uploaded files available.'), 'colspan' => '6'));
+  }
+  $output .= theme('table', $header, $rows);
+  print theme('page', form($output, 'post', url('admin/upload')));
+}
+
+/*
+ * Menu callback:
+ * Page where users manage their uploaded files
+ */
+function upload_page() {
+  global $user;
+
+  $operations = array(
+    'delete' =>    array(t('Delete the selected files'), '')
+  );
+
+  // Handle operations
+  $op = $_POST['op'];
+  $edit = $_POST['edit'];
+
+  if (($op == t('Update') || $op == t('Delete all')) && isset($edit['operation']) && isset($edit['files'])) {
+    $edit['files'] = array_diff($edit['files'], array(0));
+    if (count($edit['files']) == 0) {
+      form_set_error('', t('Please select some items to perform the update on.'));
+    }
+    else {
+      if ($edit['operation'] == 'delete') {
+        // Mass delete
+        if ($edit['confirm']) {
+          upload_delete('files', $edit['files']);
+          drupal_set_message(t('The items have been deleted.'));
+        }
+        else {
+          $extra = '<ul>';
+          foreach ($edit['files'] as $fid => $value) {
+            if ($value) {
+              $title = db_result(db_query('SELECT filename FROM {files} WHERE fid = %d', $fid));
+              $extra .= '<li>'. form_hidden('files]['. $fid, 1) . check_plain($title) .'</li>';
+            }
+          }
+          $extra .= '</ul>';
+          $extra .= form_hidden('operation', 'delete');
+
+          $output = theme('confirm',
+                          t('Are you sure you want to delete these items?'),
+                          'upload',
+                          t('This action cannot be undone.'),
+                          t('Delete all'),
+                          t('Cancel'),
+                          $extra);
+          print theme('page', $output);
+          return;
+        }
+      }
+    }
+  }
+
+  $header = array(
+    NULL,
+    array('data' => t('Filename'), 'field' => 'filename'),
+    array('data' => t('Title'), 'field' => 'title'),
+    array('data' => t('Size'), 'field' => 'filesize', 'sort' => 'desc'),
+    array('data' => t('Operations'))
+  );
+
+  $sql = "SELECT f.fid, n.nid, n.status, n.title, f.filename, f.filepath, f.filesize, n.uid FROM {files} f INNER JOIN {node} n ON f.nid = n.nid WHERE n.uid = %d";
+  $sql .= tablesort_sql($header);
+  $result = pager_query($sql, 50, 0, NULL, $user->uid);
+
+  // Make sure the update controls are disabled if we don't have any rows 
+  // to select from.
+  $disabled = !db_num_rows($result);
+
+  $options = array();
+  foreach ($operations as $key => $value) {
+    $options[$key] = $value[0];
+  }
+
+  $form = form_select(NULL, 'operation', 0, $options, NULL, ($disabled ? 'disabled="disabled"' : ''));
+  $form .= form_submit(t('Update'), 'op', ($disabled ? array('disabled' => 'disabled') : array()));
+
+  $output .= form_group(t('Update options'), "<div class=\"container-inline\">$form</div>");
+
+  $destination = drupal_get_destination();
+  while ($file = db_fetch_object($result)) {
+    $rows[] = array(
+      form_checkbox(NULL, 'files]['. $file->fid, 1, 0),
+      l($file->filename, file_create_url(($file->fid ? $file->filepath : file_create_filename($file->filename, file_create_path())))),
+      ($file->status) ? l($file->title, "node/$file->nid") : $file->title,
+      format_size($file->filesize),
+      t('delete')
+    );
+  }
+
+  if ($pager = theme('pager', NULL, 50, 0, tablesort_pager())) {
+    $rows[] = array(array('data' => $pager, 'colspan' => '5'));
+  }
+
+  if (!$rows) {
+    $rows[] = array(array('data' => t('No uploaded files available.'), 'colspan' => '5'));
+  }
+  $output .= theme('table', $header, $rows);
+  print theme('page', form($output, 'post', url('upload')));
+}
+
+function upload_settings() {
   system_settings_save();
 
   $group .= form_textfield(t('Maximum total file size'), 'upload_maxsize_total', variable_get('upload_maxsize_total', 0), 10, 10, t('The maximum size of a file a user can upload in megabytes. Enter 0 for unlimited.'));
@@ -287,7 +496,7 @@ function upload_nodeapi(&$node, $op, $ar
       break;
 
     case 'delete':
-      upload_delete($node);
+      upload_delete('node', $node);
       break;
     case 'search result':
       return $node->files ? format_plural(count($node->files), '1 attachment', '%count attachments') : null;
@@ -341,8 +550,7 @@ function upload_save($node) {
     else {
       // Remove or update existing files:
       if ($node->remove[$key]) {
-        file_delete($file->filepath);
-        db_query("DELETE FROM {files} WHERE fid = %d", $key);
+        upload_delete('files', array($file));
       }
       if ($file->list != $node->list[$key]) {
         db_query("UPDATE {files} SET list = %d WHERE fid = %d", $node->list[$key], $key);
@@ -352,12 +560,25 @@ function upload_save($node) {
   return;
 }
 
-function upload_delete($node) {
-  $node->files = upload_load($node);
-  foreach ($node->files as $file) {
-    file_delete($file->filepath);
+function upload_delete($op, $arg) {
+  switch($op) {
+    case 'node':
+      $node = $arg;
+      $node->files = upload_load($node);
+      foreach ($node->files as $file) {
+        file_delete($file->filepath);
+      }
+      db_query("DELETE FROM {files} WHERE nid = %d", $node->nid);
+      break;
+    case 'files':
+      foreach ($arg as $fid => $value) {
+        db_query("SELECT filepath FROM {files} WHERE fid = %d", $fid);
+        $file = db_fetch_object($result);
+        file_delete($file->filepath);
+        db_query("DELETE FROM {files} WHERE fid = %d", $fid);
+      }
+      break;
   }
-  db_query("DELETE FROM {files} WHERE nid = %d", $node->nid);
 }
 
 function upload_form($node) {
