Index: node_images.css
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/node_images/node_images.css,v
retrieving revision 1.1
diff -u -r1.1 node_images.css
--- node_images.css	19 Nov 2006 13:36:17 -0000	1.1
+++ node_images.css	1 Jan 2008 17:27:54 -0000
@@ -1,29 +1,47 @@
-#slideshow-table table {
+.node_images_slideshow {
   margin: 0;
   border: 0;
 }
-#slideshow-table td {
-  vertical-align: top;
-  padding-right: 10px;
+.node_images_slideshow .large {
   text-align: center;
-  vertical-align: top;
+  float: left;
+  width: 450px;
 }
-#slideshow-table .header {
+.node_images_slideshow .header {
   margin-bottom: 5px;
 }
-#slideshow-table p.description {
+.node_images_slideshow p.description {
   margin-top: 5px;
+  font-weight: bold;
 }
-#slideshow-table img.slideshow-thumb {
+.node_images_slideshow .thumbs {
+  float: left;
+  margin: 0 0 0 20px;
+  min-width: 150px;
+  height: 400px;
+  overflow-x: hidden;
+  overflow-y: auto;
+}
+.node_images_slideshow .thumbs .thumb {
+  text-align: center;
+  margin: 0 10px 10px 0;
+  float: left;
+  min-height: 145px;
+}
+.node_images_slideshow .thumbs img.slideshow-thumb {
   border: 0;
+  padding: 1px;
+  border: 2px solid #ddd;
 }
-#slideshow-table img.active {
+.node_images_slideshow .thumbs img.active {
   border: 2px solid #888;
 }
-#slideshow-table .thumb-description {
+.node_images_slideshow .thumbs .thumb-description {
   width: 120px;
   white-space: wrap;
   margin-bottom: 5px;
+  line-height: 1.2em;
+  font-size: .75em;
 }
 .polaroid {
   padding: 15px 15px 55px 15px;
Index: node_images.info
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/node_images/node_images.info,v
retrieving revision 1.1.6.3
diff -u -r1.1.6.3 node_images.info
--- node_images.info	7 Oct 2007 17:18:23 -0000	1.1.6.3
+++ node_images.info	1 Jan 2008 23:07:36 -0000
@@ -1,4 +1,6 @@
 ; $Id: node_images.info,v 1.1.6.3 2007/10/07 17:18:23 stefano73 Exp $
 name = Node images
 description = Allows users to upload images and associate them to nodes.
-dependencies = upload
\ No newline at end of file
+dependencies = upload
+package = Image
+version = "5.x-1.x-dev"
\ No newline at end of file
Index: node_images.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/node_images/node_images.module,v
retrieving revision 1.7.4.3
diff -u -r1.7.4.3 node_images.module
--- node_images.module	7 Oct 2007 17:18:23 -0000	1.7.4.3
+++ node_images.module	1 Jan 2008 23:07:54 -0000
@@ -19,6 +19,8 @@
  * Implementation of hook_menu().
  */
 function node_images_menu($may_cache) {
+  global $user;
+
   $items = array();
   $access = user_access('create node images');
   $admin = user_access('administer site configuration');
@@ -41,12 +43,14 @@
     if (arg(0) == 'node' && is_numeric(arg(1))) {
       $node = node_load(arg(1));
       if ($node->nid && variable_get('node_images_position_'.$node->type, 'hide') != 'hide') {
-        $items[] = array(
+        $may_add = array_intersect(array_keys($user->roles), variable_get('node_images_roles_add_'.$node->type, array()));
+
+	$items[] = array(
           'path' => 'node/' . arg(1) . '/images',
           'title' => t('Images'),
           'callback' => '_node_images_edit_form',
 	  'callback arguments' => array($node),
-          'access' => $access && node_access('update', $node),
+          'access' => $access && (node_access('update', $node) || !empty($may_add)),
           'type' => MENU_LOCAL_TASK,
           'weight' => 2
         );
@@ -123,6 +127,20 @@
       '#options' => array('thumbs' => t('Thumbnails'), 'fullsize' => t('Full size images')),
       '#description' => t('Image format in node body.'),
     );
+    
+    // Role-based settings for image insertion
+    $result = db_query('SELECT rid, name FROM {role} ORDER BY name');
+    $role_options = array();
+    while ($role = db_fetch_object($result)) {
+      $role_options[$role->rid] = $role->name;
+    }
+    $form['node_images']['node_images_roles_add'] = array(
+      '#type' => 'checkboxes',
+      '#title' => t('Allow specific roles to add images to any node'),
+      '#default_value' => variable_get('node_images_roles_add_'.$type, array()),
+      '#options' => $role_options,
+      '#description' =>  t('Users having the selected role(s) will be able to add images to any existing node, even if they\'re not the node owner. If you select no roles, only node owner will be able to add images.'),
+    );
 
     $form['submit']['#weight'] = 30;
     $form['delete']['#weight'] = 31;
@@ -210,16 +228,18 @@
  * Implementation of hook_link().
  */
 function node_images_link($type, $node = null, $teaser = false) {
+  global $user;
   $links = array();
 
   if ($type == 'node' && $node->nid && variable_get('node_images_position_'.$node->type, 'hide') != 'hide') {
-    if (node_access('update', $node) && user_access('create node images')) {
+    $may_add = array_intersect(array_keys($user->roles), variable_get('node_images_roles_add_'.$node->type, array()));
+    if (user_access('create node images') || !empty($may_add)) {
       $links['node_images_edit'] = array(
         'title' => t('Edit node images'),
         'href' => "node/$node->nid/images",
       );
     }
-    if (count($node->node_images) && variable_get('node_images_gallery_link_'.$node->type, TRUE)) {
+    if (arg(2) != 'image_gallery' && $node->content['node_images'] && variable_get('node_images_gallery_link_'.$node->type, TRUE)) {
       $links['node_images_gallery'] = array(
         'title' => t('Open the image gallery'),
         'href' => "node/$node->nid/image_gallery",
@@ -273,6 +293,42 @@
   }
 }
 
+/**
+ * Implementation of hook_block().
+ */
+function node_images_block($op = 'list', $delta = 0, $edit = array()) {
+  if ($op == 'list') {
+     $blocks[0]['info'] = t('Node images');
+     return $blocks;
+  }
+  else if ($op == 'configure' && $delta == 0) {
+    $form['node_images_block_count'] = array(
+      '#type' => 'select',
+      '#title' => t('Number of images to display'),
+      '#default_value' => variable_get('node_images_block_count', 3),
+      '#options' => drupal_map_assoc(array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)),
+    );
+    return $form;
+  }
+  else if ($op == 'view') {
+    $block = array();
+
+    switch ($delta) {
+      case 0:
+        // Show latest images added to the current node.
+        if (arg(0) == 'node' && is_numeric(arg(1)) && !arg(2)) {
+	  $node = node_load(arg(1));
+	  if (!$node->node_images) return;
+	  krsort($node->node_images);
+	  $count = variable_get('node_images_block_count', 3);
+	  $block['subject'] = t('Images');
+          $block['content'] = theme('node_images_view', $node, TRUE, FALSE, TRUE, $count);
+        }
+        return $block;
+    }
+  }
+}
+
 
 /************************************************************
  * Node edit functions
@@ -308,8 +364,7 @@
 }
 
 function _node_images_edit_form_upload($node) {
-  $path = file_directory_path().'/'.variable_get('node_images_path', 'node_images');
-  _node_images_check_directory(NULL, $path);
+  _node_images_check_directory(NULL, $user, $node);
   $extensions = variable_get('node_images_extensions', 'jpg jpeg gif png');
 
   drupal_add_js('misc/progress.js');
@@ -384,16 +439,29 @@
 
   while ($image = db_fetch_object($result)) {
     $images[$image->id] = $image;
-    $form['rows'][$image->id]['description'] = array(
-      '#type' => 'textfield',
-      '#default_value' => $image->description,
-      '#size' => 30,
-      '#maxlength' => 255,
-    );
-    $form['rows'][$image->id]['weight'] = array(
-      '#type' => 'weight',
-      '#default_value' => $image->weight,
-    );
+    // Only node owner or image owner can edit image properties
+    if (node_access('update', $node) || $image->uid == $user->uid) {
+      $form['rows'][$image->id]['description'] = array(
+        '#type' => 'textfield',
+        '#default_value' => $image->description,
+        '#size' => 30,
+        '#maxlength' => 255,
+      );
+      $form['rows'][$image->id]['weight'] = array(
+        '#type' => 'weight',
+        '#default_value' => $image->weight,
+      );
+    }
+    else {
+      $form['rows'][$image->id]['description'] = array(
+        '#type' => 'item',
+        '#value' => $image->description,
+      );
+      $form['rows'][$image->id]['weight'] = array(
+        '#type' => 'item',
+        '#value' => $image->weight,
+      );
+    }
 
     // images can be deleted only by users having delete access or users who uploaded the images
     $disabled = (!$delete_access && $user->uid != $image->uid);
@@ -448,7 +516,7 @@
 function _node_images_list_submit($form_id, $form_values) {
   global $user;
   $node = node_load($form_values['nid']);
-  if (!node_access('update', $node)) return;
+  $update_access = node_access('update', $node);
   $delete_access = node_access('delete', $node);
 
   foreach($form_values['rows'] as $id => $edit) {
@@ -465,9 +533,13 @@
       db_query('DELETE FROM {node_images} WHERE id=%d AND nid=%d', $id, $node->nid);
     }
     else {
+      $sql = 'UPDATE {node_images} SET description="%s", weight=%d WHERE id=%d AND nid=%d';
+      // If user has no update access to the node, must be the image owner
+      if (!$update_access) {
+        $sql .= sprintf(' AND uid=%d', $user->uid);
+      }
       // update image data
-      db_query('UPDATE {node_images} SET description="%s", weight=%d WHERE id=%d AND nid=%d',
-        $edit['description'], $edit['weight'], $id, $node->nid);
+      db_query($sql, $edit['description'], $edit['weight'], $id, $node->nid);
     }
   }
   drupal_set_message(t('The changes have been saved.'));
@@ -492,7 +564,7 @@
       form_set_error('upload', t('The uploaded file !name is not a valid image.', array('!name' => theme('placeholder', $file->filename))));
       return FALSE;
     }
-    
+
     //Munge the filename as needed for security purposes.
     $file->filename = upload_munge_filename($file->filename, NULL, 0);
 
@@ -538,7 +610,7 @@
     if (!isset($node->files[$fid])) return FALSE;
 
     // Normalize filename and check description
-    $dest = _node_images_get_directory();
+    $dest = _node_images_get_directory($user, $node);
     if (trim($edit['description']) == '') {
       $edit['description'] = basename($file->filename);
     }
@@ -571,7 +643,7 @@
 /**
  * Show node images in the node view.
  */
-function theme_node_images_view($node, $teaser, $page, $format = NULL) {
+function theme_node_images_view($node, $teaser, $page, $block = FALSE, $count = NULL, $format = NULL) {
   if (arg(2) == 'image_gallery' || empty($node->node_images)) return;
 
   $output = '';
@@ -579,8 +651,10 @@
 
   // set maximum number of images for teaser/body
   $view = ($teaser ? 'teaser' : 'body');
-  $count = variable_get('node_images_'.$view.'_images_'.$node->type, 2);
-  if (isset($count) && $count === 0) return;
+  if (!$count) {
+    $count = variable_get('node_images_'.$view.'_images_'.$node->type, 2);
+  }
+  if (isset($count) && $count == '0') return;
   if (!$format) {
     $format = variable_get('node_images_'.$view.'_format_'.$node->type, 'thumbs');
   }
@@ -609,6 +683,11 @@
     }
     if ($count>0 && ++$i >= $count) break;
   }
+
+  if ($block && $count < count($node->node_images)) {
+    $output .= '<div class="node_images_block_link">'.l(t('View all images'), 'node/'.$node->nid.'/image_gallery').'</div>';
+  }
+
   return $output;
 }
 
@@ -677,13 +756,11 @@
     );
   }
 
-  list($width, $height) = explode('x', variable_get('upload_max_resolution', 0));
-
-  $output = '<table id="slideshow-table"><tr>';
-  $output .= '<td>'.drupal_render($slideshow).'</td>';
-  $output .= '<td>'.theme('node_images_gallery_thumbs', $thumbs).'</td>';
-  $output .= '</tr></table>';
-  $output .= '<hr />'.node_view($node);
+  $output = '<div class="node_images_slideshow">';
+  $output .= '<div class="large">'.drupal_render($slideshow).'</div>';
+  $output .= '<div class="thumbs">'.theme('node_images_gallery_thumbs', $thumbs).'</div>';
+  $output .= '</div>';
+  $output .= '<hr style="clear:both;" />'.node_view($node);
 
   $title = t('Photo gallery for %title', array('%title' => $node->title));
   drupal_set_title($title);
@@ -706,20 +783,12 @@
 }
 
 function theme_node_images_gallery_thumbs($thumbs, $cols = 2) {
-  $count = count($thumbs);
-  $output = '<table id="thumbs-table">';
-
-  $i = 0;
+  $output = '';
   foreach($thumbs as $id => $thumb) {
-    if ($i % $cols == 0) $output .= '<tr>';
     $description = '<div class="thumb-description">'.truncate_utf8($thumb['title'], 40, FALSE, TRUE).'</div>';
-    $output .= '<td>'.l('<img src="'.$thumb['src'].'" class="slideshow-thumb" id="thumb-'.$id.'" />', $_GET['q'],
-      array('title' => $thumb['title'], 'rel' => 'nofollow'), 'page='.$id, NULL, FALSE, TRUE).$description.'</td>';
-    if ($i % $cols == $cols - 1 || $n >= $count) $output .= "</tr>";
-    $i++;
+    $output .= '<div class="thumb">'.l('<img src="'.$thumb['src'].'" class="slideshow-thumb" id="thumb-'.$id.'" />', $_GET['q'],
+      array('title' => $thumb['title'], 'rel' => 'nofollow'), 'page='.$id, NULL, FALSE, TRUE).$description.'</div>';
   }
-
-  $output .= '</table>';
   return $output;
 }
 
@@ -739,7 +808,7 @@
     '#title' => t('Node images path'),
     '#default_value' => variable_get('node_images_path', 'node_images'),
     '#maxlength' => 255,
-    '#description' => t('Subdirectory in the directory %dir where the node images will be stored. This directory has to exist and be writable by Drupal. You can use the following variables: %uid, %username', array('%dir' => file_directory_path() .'/')),
+    '#description' => t('Subdirectory in the directory %dir where the node images will be stored. This directory has to exist and be writable by Drupal. You can use the following variables: %uid, %username, %nid', array('%dir' => file_directory_path() .'/')),
     '#after_build' => array('_node_images_check_directory'),
   );
   $form['node_images_large_resolution'] = array(
@@ -814,14 +883,19 @@
  * @param $form_element
  *   The form element containing the name of the directory to check.
  */
- function _node_images_check_directory($form_element = NULL, $path = '') {
+ function _node_images_check_directory($form_element = NULL, $u = NULL, $node = NULL) {
   global $user;
-  $variables = array('%uid' => $user->uid, '%username' => $user->name);
+  if (!$u) $u = $user;
+  $nid = ($node && $node->nid ? $node->nid : 0);
+
+  $variables = array('%uid' => $u->uid, '%username' => $u->name, '%nid' => $nid);
+  $path = file_directory_path().'/';
   if ($form_element) {
-    $path = file_directory_path().'/'.strtr($form_element['#value'], $variables);
+    $path .= strtr($form_element['#value'], $variables);
     _node_images_mkdir_recursive($path, FILE_CREATE_DIRECTORY, $form_element['#parents'][0]);
     return $form_element;
   }
+  $path .= variable_get('node_images_path', 'node_images');
   $path = strtr($path, $variables);
   _node_images_mkdir_recursive($path, FILE_CREATE_DIRECTORY, $form_element['#parents'][0]);
 }
@@ -841,10 +915,9 @@
 /**
  * Return the destination directory.
  */
-function _node_images_get_directory() {
-  global $user;
+function _node_images_get_directory($user, $node) {
   $path = file_directory_path().'/'.variable_get('node_images_path', 'node_images');
-  return strtr($path, array('%uid' => $user->uid, '%username' => $user->name));
+  return strtr($path, array('%uid' => $user->uid, '%username' => $user->name, '%nid' => $node->nid));
 }
 
 /**
