diff -urpN node_images-5-x/inline_form.css node_images/inline_form.css
--- node_images-5-x/inline_form.css	1969-12-31 16:00:00.000000000 -0800
+++ node_images/inline_form.css	2008-04-20 11:46:20.000000000 -0700
@@ -0,0 +1,56 @@
+.node-images-form-thumbnail {
+  float: left;
+  margin-right: 15px;
+}
+
+
+.node-images-inline-insert div.size-select, .node-images-inline-insert div.align-select, .node-images-inline-insert div.caption-select  {
+  float: left;
+  padding: 5px;
+}
+
+.node-images-inline-insert div.caption-select div {
+  margin: 0;
+}
+
+.node_images_inline_submit {
+  margin: 5px 0;
+  clear: both;
+}
+
+.node_images_inline_submit a.insert-button {
+  border: 1px solid #666;
+  font-size: 1.2em;
+  padding: 3px;
+  background: #fcfcfc;
+}
+
+div.form-item img {
+  float: inherit;
+  position: relative;
+  top: 0;
+  vertical-align: top;
+}
+div.node-images-inline-image {
+  padding: 3px;
+  border: 1px solid #aaa;
+}
+
+div.node-images-inline-image.left {
+  float: left;
+  margin-right: 5px;
+}
+
+div.node-images-inline-image.right {
+  float: right;
+  margin-left: 5px;
+}
+
+.node_images, div.node-images-inline-image.clear {
+  float: none;
+  clear: both;
+}
+
+td.node-images-image-options {
+  width: 83%;
+}
\ No newline at end of file
diff -urpN node_images-5-x/inline_form.js node_images/inline_form.js
--- node_images-5-x/inline_form.js	1969-12-31 16:00:00.000000000 -0800
+++ node_images/inline_form.js	2008-04-20 13:03:52.000000000 -0700
@@ -0,0 +1,110 @@
+function node_images_insert_form(iid) {
+  form = document.getElementById('niif'+iid);
+  form.innerHTML = '<a href="#insert" id="I'+iid+'" onclick="buildInsertImage('+iid+')">Send to editor.</a>';
+}
+
+function sendToEditor(obj, text) { 
+  if(document.selection) { 
+    obj.focus(); 
+    var orig = obj.value.replace(/\r\n/g, "\n"); 
+    var range = document.selection.createRange(); 
+ 
+    if(range.parentElement() != obj) { 
+      return false; 
+    } 
+ 
+    range.text = text; 
+    var actual = tmp = obj.value.replace(/\r\n/g, "\n"); 
+    for(var diff = 0; diff < orig.length; diff++) { 
+      if(orig.charAt(diff) != actual.charAt(diff)) break; 
+    } 
+    for(var index = 0, start = 0;  
+      tmp.match(text)  
+      && (tmp = tmp.replace(text, ""))  
+      && index <= diff;  
+      index = start + text.length 
+    ) 
+    { 
+      start = actual.indexOf(text, index); 
+    } 
+  } else if(obj.selectionStart) { 
+    var start = obj.selectionStart; 
+    var end   = obj.selectionEnd; 
+
+    obj.value = obj.value.substr(0, start)  
+    + text  
+    + obj.value.substr(end, obj.value.length); 
+  } 
+
+  if(start != null) { 
+    setCaretTo(obj, start + text.length); 
+  } else { 
+    obj.value += text; 
+  } 
+} 
+
+function setCaretTo(obj, pos) { 
+  if(obj.createTextRange) { 
+    var range = obj.createTextRange(); 
+    range.move('character', pos); 
+    range.select(); 
+  } else if(obj.selectionStart) { 
+    obj.focus(); 
+    obj.setSelectionRange(pos, pos); 
+  } 
+}
+
+function buildInsertImage(iid) {
+  var TB = $("#TB_window").length;
+  if (TB == 1) {
+    var insertForm = '#TB_window #node-image-attachments';
+  }
+  else {
+    var insertForm = '#node-image-attachments';
+  }
+
+  imgFile = $(insertForm+' #edit-rows-'+iid+'-size-select').val();
+  align= $(insertForm+' #edit-rows-'+iid+'-align-select').val();
+  altText= $(insertForm+' #edit-rows-'+iid+'-meta-description').val();
+  captionText= $(insertForm+' #edit-rows-'+iid+'-meta-caption').val();
+  link = $(insertForm+' #edit-rows-'+iid+'-link-to').val();
+  cVal = $(insertForm+' #edit-rows-'+iid+'-caption-select-1').attr('checked');
+  editForm = document.getElementById('edit-body');
+    
+  var anchorOpen = '';
+  var anchorClose = '';
+  if (link != "") {
+    var linkClass = '';
+    if (link.substr(0,7) != 'http://') {
+      linkClass = 'thickbox';
+    }
+    anchorOpen = '<a href="'+link+'" class="node-images-link '+linkClass+'" title="'+captionText+'">';
+    anchorClose = '</a>';
+  }
+  
+  var captionDivo = '';
+  var captionDiv = '';
+  var imgAlign = 'class="'+align+'" ';
+  if (cVal == true) {
+    captionDivo = '<div class="node-images-inline-image '+align+'">';
+    captionDiv = '<div class="node-images-inline-caption">'+captionText+'</div></div>';
+    imgAlign = ''; 
+  }
+  
+  imgCode = captionDivo+anchorOpen+'<img '+imgAlign+'src="'+Drupal.settings.basePath+imgFile+'" id="'+iid+'" alt="'+altText+'" />'+anchorClose+captionDiv;
+  
+  //form = getElementById('body');
+  sendToEditor(editForm, imgCode);
+}
+
+function switchImageLink(name, optVal) {
+  var patt1 = /[0-9]+/g;
+  var iid = name.match(patt1);
+  $('#edit-rows-'+iid+'-link-to').val(optVal);
+}
+
+function nodeImagesBindEvents() {
+  Drupal.attachBehaviors();
+  $("#TB_window").find("a.insert-button").bind("click", function(e) {  buildInsertImage(this.id); });
+  $("input:radio.link-tos").bind("click", function(e) {  switchImageLink(this.name, this.value); });
+}
diff -urpN node_images-5-x/node_images.admin.inc node_images/node_images.admin.inc
--- node_images-5-x/node_images.admin.inc	1969-12-31 16:00:00.000000000 -0800
+++ node_images/node_images.admin.inc	2008-04-20 05:12:55.000000000 -0700
@@ -0,0 +1,65 @@
+<?php
+// $Id: node_images.admin.inc, Exp $
+
+/**
+ * Menu callback; admin settings page.
+ */
+function node_images_admin_settings() {
+  _node_images_check_settings();
+
+  $form['node_images_path'] = array(
+    '#type' => 'textfield',
+    '#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() .'/')),
+    '#after_build' => array('_node_images_check_directory'),
+  );
+  $form['node_images_large_resolution'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Resolution for large images'),
+    '#default_value' => variable_get('node_images_large_resolution', '400x300'),
+    '#size' => 19,
+    '#maxlength' => 9,
+    '#description' => t('The size for large images in the node gallery, expressed as WIDTHxHEIGHT (e.g. 400x300). If not set, the image will be resized to the maximum allowed resolution in the upload module settings.'),
+  );
+  $form['node_images_thumb_resolution'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Resolution for thumbnails'),
+    '#default_value' => variable_get('node_images_thumb_resolution', '100x100'),
+    '#size' => 15,
+    '#maxlength' => 7,
+    '#description' => t('The thumbnail size expressed as WIDTHxHEIGHT (e.g. 100x75).'),
+  );
+  $form['node_images_medium_resolution'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Resolution for medium sized images'),
+    '#default_value' => variable_get('node_images_medium_resolution', '250x250'),
+    '#size' => 15,
+    '#maxlength' => 7,
+    '#description' => t('The medium size is expressed as WIDTHxHEIGHT (e.g. 250x250).'),
+  );
+  $form['node_images_extensions'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Default permitted image extensions'),
+    '#default_value' => variable_get('node_images_extensions', 'jpg jpeg gif png gz zip'),
+    '#maxlength' => 255,
+    '#description' => t('Default image extensions that users can upload. Separate extensions with a space and do not include the leading dot.'),
+  );
+  $form['node_images_max_images'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Maximum number of images'),
+    '#default_value' => variable_get('node_images_max_images', 4),
+    '#size' => 6,
+    '#maxlength' => 2,
+    '#description' => t('The maximum number of images a user can upload for each node.'),
+  );
+  $form['node_images_md5name'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('MD5 filenames'),
+    '#description' => t('Override uploaded filenames with the MD5 hash of the file.'),
+    '#default_value' => variable_get('node_images_md5name', FALSE),
+  );
+
+  return system_settings_form($form);
+}
\ No newline at end of file
diff -urpN node_images-5-x/node_images.css node_images/node_images.css
--- node_images-5-x/node_images.css	2006-11-19 05:36:17.000000000 -0800
+++ node_images/node_images.css	2008-04-17 20:50:13.000000000 -0700
@@ -30,4 +30,5 @@
   border: 1px solid #000;
   background: #fff;
   text-align: center;
-}
\ No newline at end of file
+}
+
diff -urpN node_images-5-x/node_images.info node_images/node_images.info
--- node_images-5-x/node_images.info	2007-10-07 17:04:22.000000000 -0700
+++ node_images/node_images.info	2008-04-20 14:25:36.000000000 -0700
@@ -1,7 +1,10 @@
 ; $Id: node_images.info,v 1.4 2007/10/07 17:12:24 stefano73 Exp $
 name = Node images
 description = Allows users to upload images and associate them to nodes.
-dependencies = upload
+dependencies[] = upload
+dependencies[] = thickbox
+core = 6.x
+
 ; Information added by drupal.org packaging script on 2007-10-08
 version = "5.x-1.x-dev"
 project = "node_images"
diff -urpN node_images-5-x/node_images.install node_images/node_images.install
--- node_images-5-x/node_images.install	2007-03-29 07:42:51.000000000 -0700
+++ node_images/node_images.install	2008-04-20 13:54:11.000000000 -0700
@@ -2,50 +2,115 @@
 // $Id: node_images.install,v 1.4 2007/03/29 14:42:51 stefano73 Exp $
 
 /**
+ * Implementation of hook_schema
+ */
+function node_images_schema() {
+  $schema['node_images'] = array(
+    'fields' => array(
+      'id' => array(
+        'type' => 'serial',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+      ),
+      'nid' => array(
+        'type' => 'int',
+        'length' => '10',
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+      'uid' => array(
+        'type' => 'int',
+        'length' => '10',
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+      'filename' => array(
+        'type' => 'varchar',
+        'length' => '255',
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'filepath' => array(
+        'type' => 'varchar',
+        'length' => '255',
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'filemime' => array(
+        'type' => 'varchar',
+        'length' => '255',
+        'not null' => TRUE,
+      ),
+      'filesize' => array(
+        'type' => 'int',
+        'length' => '10',
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+      'mediumpath' => array(
+        'type' => 'varchar',
+        'length' => '255',
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'mediumsize' => array(
+        'type' => 'int',
+        'length' => '10',
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+      'thumbpath' => array(
+        'type' => 'varchar',
+        'length' => '255',
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'thumbsize' => array(
+        'type' => 'int',
+        'length' => '10',
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+      'status' => array(
+        'type' => 'int',
+        'size' => 'tiny',
+        'length' => '1',
+        'not null' => TRUE,
+        'default' => 1,
+      ),
+      'weight' => array(
+        'type' => 'int',
+        'size' => 'tiny',
+        'length' => '1',
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+      'description' => array(
+        'type' => 'varchar',
+        'length' => '255',
+        'not null' => FALSE,
+      ),
+      'caption' => array(
+        'type' => 'varchar',
+        'length' => '255',
+        'not null' => FALSE,
+      ),
+    ),
+    'indexes' => array(
+      'uid' => array('uid'),
+      'nid' => array('nid'),
+      'status' => array('status'),
+    ),
+    'primary key' => array('id'),
+  );
+  return $schema;
+}
+
+/**
  * Implementation of hook_install().
  */
 function node_images_install() {
-  switch ($GLOBALS['db_type']) {
-    case 'mysql':
-    case 'mysqli':
-      db_query("CREATE TABLE {node_images} (
-	id int(10) unsigned NOT NULL auto_increment,
-	nid int(10) unsigned NOT NULL default '0',
-	uid int(10) unsigned NOT NULL default '0',
-	filename varchar(255) NOT NULL default '',
-	filepath varchar(255) NOT NULL default '',
-	filemime varchar(255) NOT NULL default '',
-	filesize int(10) unsigned NOT NULL default '0',
-	thumbpath varchar(255) NOT NULL default '',
-	thumbsize int(10) unsigned NOT NULL default '0',
-	status tinyint(1) unsigned NOT NULL default '1',
-	weight tinyint(1) NOT NULL default '0',
-	description varchar(255) default NULL,
-	PRIMARY KEY  (id),
-	KEY uid (uid),
-	KEY nid_status (nid,status)
-      ) /*!40100 DEFAULT CHARACTER SET UTF8 */ ");
-      break;
-
-    case 'pgsql':
-      db_query("CREATE TABLE {node_images} (
-        id SERIAL PRIMARY KEY,
-        nid integer NOT NULL default '0',
-        uid integer NOT NULL default '0',
-        filename varchar(255) NOT NULL default '',
-        filepath varchar(255) NOT NULL default '',
-        filemime varchar(255) NOT NULL default '',
-        filesize integer NOT NULL default '0',
-        thumbpath varchar(255) NOT NULL default '',
-        thumbsize integer NOT NULL default '0',
-        status smallint NOT NULL default '1',
-        weight smallint NOT NULL default '0',
-        description varchar(255) default NULL
-      )");
-      db_query("CREATE INDEX {node_images}_uid ON {node_images} (uid)");
-      db_query("CREATE INDEX {node_images}_nid_status ON {node_images} (nid,status)");
-      break;
-  }
+  drupal_install_schema('node_images');
 }
 
 function node_images_update_1() {
diff -urpN node_images-5-x/node_images.module node_images/node_images.module
--- node_images-5-x/node_images.module	2007-10-07 10:12:24.000000000 -0700
+++ node_images/node_images.module	2008-04-20 13:43:07.000000000 -0700
@@ -18,57 +18,139 @@ function node_images_perm() {
 /**
  * Implementation of hook_menu().
  */
-function node_images_menu($may_cache) {
+function node_images_menu() {
+  global $user;
   $items = array();
   $access = user_access('create node images');
   $admin = user_access('administer site configuration');
 
-  if ($may_cache) {
-    $items[] = array('path' => 'admin/settings/node_images',
-      'title' => t('Node images'),
-      'description' => t('Control how to upload node images.'),
-      'callback' => 'drupal_get_form',
-      'callback arguments' => array('node_images_admin_settings'),
-      'access' => $admin
-    );
-    $items[] = array(
-      'path' => 'node_images/js',
-      'callback' => '_node_images_js',
-      'access' => $access,
-      'type' => MENU_CALLBACK
-    );
-  } else {
-    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(
-          'path' => 'node/' . arg(1) . '/images',
-          'title' => t('Images'),
-          'callback' => '_node_images_edit_form',
-	  'callback arguments' => array($node),
-          'access' => $access && node_access('update', $node),
-          'type' => MENU_LOCAL_TASK,
-          'weight' => 2
-        );
-        $items[] = array(
-          'path' => 'node/' . arg(1) . '/image_gallery',
-          'title' => t('Gallery'),
-          'callback' => '_node_images_gallery',
-	  'callback arguments' => array($node),
-          'access' => node_access('view', $node),
-          'type' => MENU_CALLBACK
-        );
-      }
-    }
+  $items['admin/settings/node_images'] = array(
+    'title' => t('Node images'),
+    'description' => t('Control how to upload node images.'),
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('node_images_admin_settings'),
+    'access arguments' => array('administer site configuration'),
+    'file' => 'node_images.admin.inc',
+  );
+  $items['node_images/js'] = array(
+    'page callback' => 'node_images_js',
+    'access arguments' => array('create node images'),
+    'file' => 'node_images.pages.inc',
+    'type' => MENU_CALLBACK
+  );
+  $items['node_images_save/js'] = array(
+    'page callback' => 'node_images_save_js',
+    'access arguments' => array('create node images'),
+    'file' => 'node_images.pages.inc',
+    'type' => MENU_CALLBACK
+  );
+  $items['node_images/%node'] = array(
+    'title' => t('Images'),
+    'page callback' => 'node_images_ajax_inline',
+    'page arguments' => array(1),
+    'access arguments' => array('user_access', $user),
+    //'access arguments' => array('create node images', 'update'),
+    'type' => MENU_CALLBACK,
+  );
+  
+  
+  $items['node/%node/images'] = array(
+    'title' => t('Images'),
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('_node_images_edit_form', 1),
+    'access arguments' => array('user_access', $user),
+    //'access arguments' => array('create node images', 'update'),
+    'type' => MENU_LOCAL_TASK,
+    'weight' => 2
+  );
+  $items['node/%node/image_gallery'] = array(
+    'title' => t('Gallery'),
+    'page callback' => '_node_images_gallery',
+    'page arguments' => array(1),
+    'access arguments' => array('view'),
+    'file' => 'node_images.pages.inc',
+    'type' => MENU_CALLBACK
+  );
+  return $items;
+}
+
+/**
+ * Checks if the upload.module is enabled, and the existence of an image toolkit.
+ *
+ * @param $form_element
+ *   The form element containing the name of the directory to check.
+ */
+function _node_images_check_settings() {
+  // Make sure upload module is enabled
+  if (!module_exists('upload')) {
+    drupal_set_message(t('node_images.module require upload.module to be enabled.'), 'error');
   }
 
-  return $items;
+  // Make sure we've got a working toolkit
+  if (!image_get_toolkit()) {
+    drupal_set_message(t('Make sure you have a working image toolkit installed and enabled, for more information see: %settings', array('%settings' => l(t('the settings page'), 'admin/settings/image-toolkit'))), 'error');
+  }
+}
+
+/**
+ * Returns a form for uploading and inserting images on a node edit page
+ */
+function node_images_ajax_inline($node) {
+  $form_state = array();
+  $output = '<script type="text/javascript">$(function() { jQuery.extend(Drupal.settings, { "ahah": { "attach-button": { "url": "/node_images/js", "event": "mousedown", "keypress": true, "wrapper": "node-images-attach-wrapper", "selector": "#attach-button", "effect": "fade", "method": "replace", "progress": { "type": "bar", "message": "Please wait..." }, "button": { "attach": "Upload" } }, "save-button": { "url": "/node_images_save/js", "event": "mousedown", "keypress": true, "wrapper": "save-status", "selector": "#save-button", "effect": "fade", "method": "replace", "progress": { "type": "bar", "message": "Saving changes..." }, "button": { "save": "Save Changes" } } } }); });</script>';
+  $output .= '<div id="node-images-attach-wrapper">'. drupal_get_form('_node_images_edit_form', $node) .'</div>';  
+  //$output .= node_images_inline_scripts();
+  $output .= '<script type="text/javascript">$(function() { nodeImagesBindEvents(); $("#TB_window").ajaxSuccess(function(evt, request, settings) { nodeImagesBindEvents(); } ); });</script>';
+  exit($output);
+}
+
+function node_images_inline_scripts() {
+  $output .= '<script type="text/javascript">$(function() { Drupal.attachBehaviors(); });</script>';
+  $output .= '<script type="text/javascript">$(function() { $("#TB_window").find("a.insert-button").bind("click", function(e) {  buildInsertImage(this.id); } ); })</script>';
+  $output .= '<script type="text/javascript">$(function() { $("input:radio.link-tos").bind("click", function(e) {  switchImageLink(this.name, this.value); } ); })</script>';
+  $output .= '<script type="text/javascript">$(function() { $("#TB_window").ajaxSuccess(function(evt, request, settings) { nodeImagesBindEvents(); } ); })</script>';
+  return $output;
+}
+
+/**
+ * Implementation of hook_theme()
+ */
+function node_images_theme() {
+  return array(
+    'node_images_view' => array(
+      'arguments' => array('node' => NULL, 'teaser' => NULL, 'page' => NULL, 'format' => NULL),
+    ),
+    'node_images_list' => array(
+      'arguments' => array('form' => NULL),
+    ),
+    'node_images_list_inline' => array(
+      'arguments' => array('form' => NULL),
+    ),
+    'node_images_gallery' => array(
+      'arguments' => array('element' => NULL),
+    ),
+    'node_images_gallery_thumbs' => array(
+      'arguments' => array('thumbs' => NULL, 'cols' => '2'),
+    ),
+    'node_images_inline_image_form' => array(
+      'arguments' => array('image_id' => NULL, 'image_name' => NULL, 'image_thumbnail' => NULL, 'image_size' => NULL, 'image_width' => NULL, 'image_height' => NULL, 'image_path' => NULL, 'size_select' => NULL, 'align_select' => NULL, 'caption_select' => NULL, 'description' => NULL),
+    ),
+    'node_images_inline_insert_form' => array(
+      'arguments' => array('image_id' => NULL),
+    ),
+    'node_images_slideshow' => array(
+      'arguments' => array('nid' => NULL, 'slides' => ''),
+    ),
+    'node_images_slides' => array(
+      'arguments' => array('image' => NULL),
+    ),
+  );
 }
 
 /**
  * implementation of hook_form_alter()
  */
-function node_images_form_alter($form_id, &$form) {
+function node_images_form_alter($form, &$form_state, $form_id) {
   $type = $form['#node_type']->type;
   if ($form_id == 'node_type_form' && isset($form['identity']['type'])) {
     // radio button in the node's content type configuration page
@@ -76,27 +158,28 @@ function node_images_form_alter($form_id
     $form['node_images'] = array(
       '#type' => 'fieldset',
       '#title' => t('Node images'),
+      '#tree' => FALSE,
       '#collapsible' => TRUE,
     );
     $form['node_images']['node_images_position'] = array(
       '#type' => 'radios',
       '#title' => t('Position'),
-      '#default_value' => variable_get('node_images_position_'.$type, 'hide'),
+      '#default_value' => variable_get('node_images_position_'. $type, 'hide'),
       '#options' => array('hide' => t('Do not show'), 'above' => t('Show above node body'), 'below' => t('Show below node body'), 
-	 'node_template' => t('Manually set in node template by variable $node->node_images')),
+      'node_template' => t('Manually set in node template by variable $node->node_images')),
       '#description' => t('The position of images in the node view.'),
     );
     $form['node_images']['node_images_gallery_link'] = array(
       '#type' => 'radios',
       '#title' => t('Link to image gallery'),
-      '#default_value' => variable_get('node_images_gallery_link_'.$type, TRUE),
+      '#default_value' => variable_get('node_images_gallery_link_'. $type, TRUE),
       '#options' => array(t('Do not show'), t('Show')),
       '#description' => t('Choose whether to show or not the link to the image gallery.'),
     );
     $form['node_images']['node_images_teaser_images'] = array(
       '#type' => 'textfield',
       '#title' => t('Number of images in node teaser'),
-      '#default_value' => variable_get('node_images_teaser_images_'.$type, 2),
+      '#default_value' => variable_get('node_images_teaser_images_'. $type, 2),
       '#size' => 5,
       '#maxlength' => 2,
       '#description' => t('The maximum number of images to show in the node teaser. 0 will not show images. Leave blank to show all images.'),
@@ -106,20 +189,20 @@ function node_images_form_alter($form_id
       '#title' => t('Number of images in node body'),
       '#size' => 5,
       '#maxlength' => 2,
-      '#default_value' => variable_get('node_images_body_images_'.$type, NULL),
+      '#default_value' => variable_get('node_images_body_images_'. $type, NULL),
       '#description' => t('The maximum number of images to show in the node body. 0 will not show images. Leave blank to show all images.'),
     );
     $form['node_images']['node_images_teaser_format'] = array(
       '#type' => 'radios',
       '#title' => t('Image format in node teaser'),
-      '#default_value' => variable_get('node_images_teaser_format_'.$type, 'thumbs'),
+      '#default_value' => variable_get('node_images_teaser_format_'. $type, 'thumbs'),
       '#options' => array('thumbs' => t('Thumbnails'), 'fullsize' => t('Full size images')),
       '#description' => t('Image format in node teaser.'),
     );
     $form['node_images']['node_images_body_format'] = array(
       '#type' => 'radios',
       '#title' => t('Image format in node body'),
-      '#default_value' => variable_get('node_images_body_format_'.$type, 'thumbs'),
+      '#default_value' => variable_get('node_images_body_format_'. $type, 'thumbs'),
       '#options' => array('thumbs' => t('Thumbnails'), 'fullsize' => t('Full size images')),
       '#description' => t('Image format in node body.'),
     );
@@ -128,6 +211,17 @@ function node_images_form_alter($form_id
     $form['delete']['#weight'] = 31;
     $form['reset']['#weight'] = 32;
   }
+  elseif (isset($form['type']) && isset($form['#node']) && isset($form['#node']->nid) ) {
+    $node = $form['#node'];
+
+    $form['body']['body_filter']['insert_node_image'] = array(
+      '#type' => 'item',
+      '#weight' => 7,
+      '#value' => '<a href="/node_images/'. $node->nid .'?height=550&width=550" class="thickbox">Insert Images</a>',
+    );
+    drupal_add_js('modules/node_images/inline_form.js');
+    drupal_add_css('modules/node_images/inline_form.css');
+  }
 }
 
 /**
@@ -135,8 +229,9 @@ function node_images_form_alter($form_id
  */
 function node_images_nodeapi(&$node, $op, $teaser, $page) {
   // test if images are allowed for this node
+  /*
   if ($op == 'load' || $op == 'view') {
-    if (variable_get('node_images_position_'.$node->type, 'hide') == 'hide') return;
+    if (variable_get('node_images_position_'. $node->type, 'hide') == 'hide') return;
 
     // fire an additional hook for the specific node type
     // i.e. node images might be a pro feature, so only subscribed users can view them
@@ -144,6 +239,7 @@ function node_images_nodeapi(&$node, $op
     $show = module_invoke($node->type, 'node_images', $op, $node);
     if ($show === FALSE) return;
   }
+  */
 
   switch ($op) {
     case 'load':
@@ -156,9 +252,9 @@ function node_images_nodeapi(&$node, $op
 
     case 'insert':
       if (user_access('create node images') && node_access('update', $node) &&
-        variable_get('node_images_position_'.$node->type, 'hide') != 'hide') {
+        variable_get('node_images_position_'. $node->type, 'hide') != 'hide') {
           drupal_set_message(t('Click the <strong>!images</strong> tab to add images to this node.',
-            array('!images' => l(t('images'), 'node/'.$node->nid.'/images'))));
+            array('!images' => l(t('images'), 'node/'. $node->nid .'/images'))));
       }
       break;
 
@@ -167,17 +263,27 @@ function node_images_nodeapi(&$node, $op
       $sql = db_query('SELECT filepath, thumbpath FROM {node_images} WHERE nid=%d', $node->nid);
       while ($r = db_fetch_object($sql)) {
         file_delete($r->filepath);
-	file_delete($r->thumbpath);
+        file_delete($r->thumbpath);
       }
       // Delete all images associated with the node
       db_query('DELETE FROM {node_images} WHERE nid=%d', $node->nid);
       break;
 
     case 'view':
-      if (empty($node->node_images)) return;
-
+      if (empty($node->node_images) || $teaser) {
+        if ($node->format == 2) {
+          _node_images_slideshow_process_text($node, $teaser, $page, array('noslides' => TRUE));  
+        }
+        return;
+      } 
+      else {
+        if ($node->format == 2) {
+          _node_images_slideshow_process_text($node, $teaser, $page, array('noslides' => FALSE));
+        }
+      }
+      drupal_add_css('modules/node_images/inline_form.css');
       // search for a themed view for the current node type
-      $nodetype_function = 'theme_'.$node->type.'_node_images_view';
+      $nodetype_function = 'theme_'. $node->type .'_node_images_view';
       if (function_exists($nodetype_function)) {
         $output = $nodetype_function($node, $teaser, $page);
       }
@@ -187,14 +293,14 @@ function node_images_nodeapi(&$node, $op
       }
       $node->node_images = $output;
 
-      $output = '<div class="node_images">'.$output.'</div>';
-      $position = variable_get('node_images_position_'.$node->type, 'hide');
+      $output = '<div class="node_images">'. $output .'</div>';
+      $position = variable_get('node_images_position_'. $node->type, 'hide');
       switch ($position) {
         case 'node_template':
-	case 'hide':
+        case 'hide':
           break;
 
-	case 'above':
+        case 'above':
           $node->content['node_images'] = array('#value' => $output, '#weight' => -1);
           break;
 
@@ -207,19 +313,123 @@ function node_images_nodeapi(&$node, $op
 }
 
 /**
+ * The main function to display a slideshow.
+ */
+function _node_images_slideshow_process_text(&$node, $teaser, $page, $params) {
+  // Search for Slideshow Creator tags on the text.
+  if ($page) {
+    $content = $node->content['body']['#value'];
+  }
+  if ($teaser || $params['noslides'] == TRUE) {
+    $node->content['body']['#value'] = _node_images_strip_markup($node->content['body']['#value']);
+    return $node;
+  }
+  $max_slides = count($node->node_images);
+  if (count($max_slides) < 1) return $node;  
+  $i = 1;
+  foreach ($node->node_images as $key => $image) {
+    $images[$i] = $image;
+    $i++;
+  }
+  
+  if (preg_match_all('/\[slides: ?\[[0-9|,|\-|all]+?\] ?\(?[A-Za-z0-9|,|:]+?\)?\]/i', $content, $matches, PREG_SET_ORDER)) {
+    jquery_plugin_add('cycle');
+    $show_count = 1;
+    foreach ($matches as $match) {
+      $match_str = $match['0'];
+      preg_match('/\(([A-Za-z0-9]+:[A-Za-z0-9]+,?)+\)?/i', $match['0'], $attributes);
+      $attributes = str_replace(array('(',')'), array('',''), $attributes['0']);
+      $attributes = explode(',', $attributes);
+      if (count($attributes) > 0) {
+        foreach ($attributes as $key => $value) {
+          $args = explode(':', $value); 
+          $settings[strtolower($args['0'])] = $args['1'];
+        }
+      }
+      $fx = isset($settings['fx']) ? $settings['fx'] : 'fade';
+      $speed = isset($settings['speed']) ? $settings['speed'] : 3000;
+      $timeout = isset($settings['timeout']) ? $settings['timeout'] : 2000;
+        
+      drupal_add_js('if (Drupal.jsEnabled) { $(document).ready(function() { $("#node-images-slides-'. $node->nid .'-'. $show_count .'").cycle({ fx: "'. $fx .'", speed: '. $speed .', timeout: '. $timeout .' }); }); }', 'inline');
+      $match = str_replace(array('[', 'slides:', ' ', ']'), array('','','',''), preg_replace('/\(([A-Za-z0-9]+:[A-Za-z0-9]+,?)+\)?/i', '', $match));
+      $match = explode(',', $match['0']);
+
+      if ($match['0'] == 'all') {
+        $count = 1;
+        foreach ($node->node_images as $key => $image) {
+          $output .= theme('node_images_slides', $images[$count]);
+          $count++;
+        }
+      }
+      else {
+        foreach ($match as $key => $value) {
+          if (preg_match_all('/[0-9]+\-[0-9]+/i', $value, $range, PREG_SET_ORDER)) {
+            $temp = explode('-', $range['0']['0']);
+            if ($temp['0'] < $temp['1']) {
+              $end = $temp['1'] + 1;
+              for ($i = $temp['0']; $i < $end; $i++) {
+                if ($i <= $max_slides) {
+                  $output .= theme('node_images_slides', $images[$i]);
+                }
+              }
+            }
+          }
+          else {
+            if (ctype_digit($value) && $value <= $max_slides) {
+              $output .= theme('node_images_slides', $images[$value]);
+            }
+          }
+        }
+      }
+      //$slideshows[] = theme('node_images_slideshow', $node->nid, $output, $show_count);
+      $content = str_replace($match_str, theme('node_images_slideshow', $node->nid, $output, $show_count), $content);
+      $show_count++;
+    }
+    //$i = 0;
+    //$output = preg_replace_callback('/\[slides:(.+)?\]/i', '_node_images_replace_markup', $content);
+        
+    //$node->content['body']['#value'] = preg_replace('/\[slides:(.+)?\]/i', $slideshow, $content);
+    $node->content['body']['#value'] = $content;
+  }
+}
+
+/**
+ * Strip slides markup
+ */
+function _node_images_strip_markup($text) {
+  return preg_replace('/\[slides: ?\[[0-9|,|\-|all]+?\] ?\(?[A-Za-z0-9|,|:]+?\)?\]/i', '', $text);
+}
+
+function theme_node_images_slides($image) {
+  $output = '';
+  $output .= '<div class="node-images-slide"><div class="inner"><div class="content">';
+  $output .= '<div class="node-image">'. theme('image', $image->filepath) .'</div>';
+  $output .= '<div class="caption">'. check_plain($image->description) .'</div>';
+  $output .= '</div></div></div>';
+  return $output; 
+}
+
+/**
+ * Wrap slides for display
+ */
+function theme_node_images_slideshow($nid, $slides, $show_count) {
+  return '<div class="node-images-slides-wrapper"><div id="node-images-slides-'. $nid .'-'. $show_count .'" class="node-images-slides">'. $slides .'</div></div>';
+}
+
+/**
  * Implementation of hook_link().
  */
 function node_images_link($type, $node = null, $teaser = false) {
   $links = array();
 
-  if ($type == 'node' && $node->nid && variable_get('node_images_position_'.$node->type, 'hide') != 'hide') {
+  if ($type == 'node' && $node->nid && variable_get('node_images_position_'. $node->type, 'hide') != 'hide') {
     if (node_access('update', $node) && user_access('create node images')) {
       $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 (count($node->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",
@@ -258,7 +468,7 @@ function node_images_file_download($file
       }
       else {
         $name = mime_header_encode($file->filename);
-	$size = $file->filesize;
+        $size = $file->filesize;
       }
       $type = mime_header_encode($file->filemime);
       return array(
@@ -273,6 +483,17 @@ function node_images_file_download($file
   }
 }
 
+function _node_images_form_format($a2) {
+  switch ($a2) {
+    case 'edit':
+      return 'inline';
+    case 'images':
+      return 'tab';
+    default:   
+      return 'inline';
+  }
+}
+
 
 /************************************************************
  * Node edit functions
@@ -286,57 +507,141 @@ function node_images_file_download($file
  * @return
  *    the node images page.
  */
-function _node_images_edit_form($node) {
+function _node_images_edit_form($form_state, $node) {
   global $user;
-  $output = '<div id="attach-wrapper">';
-
   // Generate image list
-  $sql = db_query('SELECT * FROM {node_images} WHERE nid=%d ORDER BY weight', $node->nid);
-  if (db_num_rows($sql)>0) $output .= drupal_get_form('_node_images_list', $node, $sql);
-
-  // test if this node can accept new images
-  // i.e. there might be limits to the number of uploaded images for certain node types or user roles
-  // if the hook is not present in the node type module, upload is enabled by default
+ // return (array)$node;
+  if (isset($form_state['storage']['mode'])) {
+    $form_format = $form_state['storage']['mode'];
+    unset($form_state['storage']['mode']);
+  }
+  else {
+    $form_format = _node_images_form_format(arg(2));
+  }
+   
+  $form = array();
+  if ($form_format == 'inline') {
+    //$form_state['storage']['mode'] = 'inline';
+    $description = t('Images can be inserted into the body text. Choose the formatting options you would like and click on the "Send to editor" button to insert the image.');
+    drupal_add_js('modules/node_images/inline_form.js');
+  }
+  else {
+    //$form_state['storage']['mode'] = 'tab';
+    $description = t('Edit node_images with this form');
+  }
+  
+  $rebuilt = $form_state['storage']['rebuilt'];
+  unset($form_state['storage']['rebuilt']);
+  if ($form_format == 'tab') {
+    $form['node_images'] = array(
+      '#type' => 'fieldset',
+      '#title' => t('Node Images'),
+      '#collapsible' => TRUE,
+      '#collapsed' => isset($node->edit) ? TRUE: FALSE,
+      '#description' => $description,
+    );
+    if (!$rebuilt) {
+      $form['#prefix'] = '<div id="node-images-attach-wrapper">';
+      $form['#suffix'] = '</div>';
+    }
+  }
+    
+  if ( empty($node->edit) && !isset($node->node_images)) {
+    $images = array();
+    $result = db_query('SELECT * FROM {node_images} WHERE nid = %d ORDER BY weight', $node->nid);
+    while ($image = db_fetch_object($result)) {
+      $images[$image->id] = $image;
+    }
+  } 
+  else {
+    $images = $node->node_images;
+  } 
+  $form['node_images']['node_images'] =  _node_images_list($form_state, $node, $images, $form_format);
+ 
+  if ($form_format == 'tab') {
+    $current_page =  url('node/'. $node->nid .'/images');
+    $form['node_images']['node_images']['save'] = array(
+      '#type' => 'submit',
+      '#action' => $current_page,
+      '#submit' => array('_node_images_list_submit'),
+      '#value' => t('Save changes'),
+    );
+    $form['node_images']['node_images']['mode'] = array(
+      '#type' => 'hidden',
+      '#value' => 'tab',
+    );
+    $form['node_images']['current_page'] = array(
+      '#type' => 'hidden',
+      '#value' => $current_page,
+    );
+  } 
+  else if ($form_format == 'inline') {
+    $current_page =  url('node/'. $node->nid);
+    $form['node_images']['node_images']['save'] = array(
+      '#type' => 'submit',
+      '#suffix' => '<div class="clear-block" id="save-status"></div>',
+      '#name' => 'save-changes',
+      '#value' => t('Save changes'),
+      '#ahah' => array(
+        'path' => 'node_images_save/js',
+        'wrapper' => 'node-images-attach-wrapper',
+        'method' => 'replace',
+        'effect' => 'fade',
+        'progress' => array('type' => 'bar', 'message' => t('Saving changes...')),
+      ),
+      '#id' => 'save-button',
+    );
+    $form['node_images']['node_images']['mode'] = array(
+      '#type' => 'hidden',
+      '#value' => 'inline',
+    );
+    $form['node_images']['current_page'] = array(
+      '#type' => 'hidden',
+      '#value' => $current_page,
+    );
+  }
+ 
+  $form['node_images']['nid'] = array(
+    '#type' => 'hidden',
+    '#value' => $node->nid,
+  );
+  
   $upload = module_invoke($node->type, 'node_images', 'upload', $node);
   if ($upload !== FALSE) {
-    $output .= drupal_get_form('_node_images_edit_form_upload', $node);
+ // if ($upload !== FALSE && $form_format == 'tab') {
+    $form['node_images']['new'] = drupal_retrieve_form('_node_images_edit_form_upload', $form_state, $node);
   }
-  $output .= '</div>';
-
-  drupal_set_title(check_plain($node->title));
-  return $output;
+  $form['#action'] = url('node/'. $node->nid .'/images');
+  return $form;
 }
 
-function _node_images_edit_form_upload($node) {
-  $path = file_directory_path().'/'.variable_get('node_images_path', 'node_images');
+function _node_images_edit_form_upload($form_state, $node) {
+  $path = file_directory_path() .'/'. variable_get('node_images_path', 'node_images');
   _node_images_check_directory(NULL, $path);
-  $extensions = variable_get('node_images_extensions', 'jpg jpeg gif png');
-
-  drupal_add_js('misc/progress.js');
-  drupal_add_js('misc/upload.js');
-  
+  $extensions = variable_get('node_images_extensions', 'jpg jpeg gif png zip gz');
   // Generate upload form
-  $form['new'] = array(
-    '#type'=>'fieldset',
-    '#title'=>t('Upload a new image'),
+  $form = array(
+    '#type' => 'fieldset',
+    '#weight' => 5,
+    '#title' => t('Upload a new image'),
   );
-  $form['new']['description'] = array(
+  $form['description'] = array(
     '#type' => 'textfield',
     '#title' => t('Description'),
-    '#size' => 50,
+    '#size' => 40,
     '#maxlength' => 255,
     '#default_value' => $edit['new']['description'],
     '#description' => t('Enter a description for the new image, max 255 chars.'),
     '#prefix' => '<div style="float:left; margin-right:20px;">',
     '#suffix' => '</div>',
   );
-  $form['new']['weight'] = array(
+  $form['weight'] = array(
     '#type' => 'weight',
     '#title' => t('Weight'),
     '#prefix' => '<div style="float:left; margin-right:20px;">',
     '#suffix' => '</div><div style="clear:both; height:0.1em;"></div>',
   );
-  $form['new']['upload'] = array(
+  $form['node_image_upload'] = array(
     '#type' => 'file',
     '#title' => t('Image file'),
     '#size' => 50,
@@ -344,24 +649,20 @@ function _node_images_edit_form_upload($
     '#prefix' => '<div style="clear:both;"></div><div id="attach-hide" style="clear:both;">',
     '#suffix' => '</div>',
   );
-  $form['new']['submit'] = array(
-    '#type' => 'button',
+  $form['submit'] = array(
+    '#type' => 'submit',
     '#value' => t('Upload'),
-    '#name'=> 'submit',
+    '#name' => 'attach',
+    '#ahah' => array(
+      'path' => 'node_images/js',
+      'wrapper' => 'node-images-attach-wrapper',
+      'method' => 'replace',
+      'effect' => 'fade',
+      'progress' => array('type' => 'bar', 'message' => t('Please wait...')),
+    ),
     '#id' => 'attach-button',
   );
-  // The class "upload" triggers the js upload behaviour.
-  $form['attach-url'] = array(
-    '#type' => 'hidden',
-    '#value' => url('node_images/js', NULL, NULL, TRUE),
-    '#attributes' => array('class' => 'upload'),
-  );
-  // Needed for JS
-  $form['nid'] = array(
-    '#type' => 'hidden',
-    '#value' => $node->nid,
-  );
-
+  
   $form['#attributes']['enctype'] = 'multipart/form-data';
   return $form;
 }
@@ -376,98 +677,219 @@ function _node_images_edit_form_upload($
  * @return
  *    a form representing the image list.
  */
-function _node_images_list($node, $result) {
+function _node_images_list($form_state, $node, $images = NULL, $form_format = 'tab') {
   global $user;
-  $images = array();
+  
   $form['rows'] = array('#tree' => TRUE);
   $delete_access = node_access('delete', $node);
 
-  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,
-    );
-
-    // images can be deleted only by users having delete access or users who uploaded the images
-    $disabled = (!$delete_access && $user->uid != $image->uid);
-    $form['rows'][$image->id]['delete'] = array('#type' => 'checkbox', '#disabled' => $disabled);
+  if (count($images) > 0) {
+    foreach($images as $id => $image) {
+      $disabled = (!$delete_access && $user->uid != $image->uid);
+      $form['rows'][$image->id] = _node_images_image_form($image, $disabled);
+      if($form_format == 'inline') {       
+        $form['rows'][$image->id] += _node_images_inline_form($image);           
+      }
+      // images can be deleted only by users having delete access or users who uploaded the images
+      $form['rows'][$image->id]['delete'] = array('#type' => 'checkbox', '#disabled' => $disabled);
+    }
   }
 
   $form['nid'] = array('#type' => 'value', '#value' => $node->nid);
-  $form['save'] = array(
-    '#type' => 'submit',
-    '#value' => t('Save changes'),
-  );
-  $form['images'] = array(
-    '#type' => 'value',
-    '#value' => $images,
-  );
-  $form['#theme'] = 'node_images_list';
 
+  $theme = $form_format == 'inline' ? 'node_images_list_inline' : 'node_images_list';
+  $form['rows']['#theme'] = $theme;
+  
   // action must be set, otherwise it will be replaced by "node_images/js" (current $_GET['q'] on JS uploads)
-  $form['#action'] = url('node/'.$node->nid.'/images');
+  $form['#action'] = url('node/'. $node->nid .'/images');
 
   return $form;
 }
 
 /**
- * Theme node images list.
+ * Return an image form element
  */
-function theme_node_images_list($form) {
-  $header = array(t('Thumbnail'), t('Description').' / '.t('Path'), t('Size'), t('Weight'), t('Delete'));
+function _node_images_image_form($image, $disabled = NULL) {
+  global $user;
   
-  $rows = array();
-  foreach($form['images']['#value'] as $id=>$image) {
-    $row = array();
-    $row[] = '<img src="'.file_create_url($image->thumbpath).'" vspace="5" />';
-    $row[] = drupal_render($form['rows'][$image->id]['description']).$image->filepath;
-    $row[] = array('data' => format_size($image->filesize), 'style' => 'white-space: nowrap');
-    $row[] = drupal_render($form['rows'][$image->id]['weight']);
-    $row[] = array('data' => drupal_render($form['rows'][$image->id]['delete']), 'align' => 'center');
-    $rows[] = $row;
+  $form = array();
+  if (is_null($disabled)) {
+    $disabled = (!$delete_access && $user->uid != $image->uid);
   }
+  $description = ($image->description == '') ? $image->filename : $image->description;
+  $form['thumbnail'] = array('#type' => 'item', '#value' => '<img src="'. file_create_url($image->thumbpath) .'" vspace="5" />');
+  $form['meta'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Metadata'),
+    '#collapsible' => TRUE,
+    '#collapsed' => TRUE,
+  );
+  $form['meta']['filename'] = array(
+    '#type' => 'textfield', 
+    '#title' => t('Name'), 
+    '#default_value' => $image->filename,
+    '#desciption' => t("Title of this image"), 
+    '#size' => 50, 
+    '#maxlength' => 255
+  );
+  $form['meta']['description'] = array(
+    '#type' => 'textfield', 
+    '#title' => t('Description'), 
+    '#default_value' => $image->description,
+    '#description' => t("Alternate text to describe the image"), 
+    '#size' => 50, 
+    '#maxlength' => 255
+  );
+  $form['meta']['caption'] = array(
+    '#type' => 'textfield', 
+    '#title' => t('Caption'), 
+    '#default_value' => $image->caption,
+    '#description' => t("Optional text to accompany this image."),  
+    '#size' => 50, 
+    '#maxlength' => 255
+  );
+  $form['meta']['path'] = array('#type' => 'item', '#title' => t('File Path'), '#value' => $image->filepath);
+  $form['size'] = array('#type' => 'item', '#value' => format_size($image->filesize));
+  $form['weight'] = array('#type' => 'weight', '#default_value' => $image->weight);
+  $form['delete'] = array('#type' => 'checkbox', '#disabled' => $disabled);
+  return $form;
+}
 
-  $output = '<fieldset><legend>'.t('Uploaded images').'</legend>';
-  $output .= theme('table', $header, $rows);
+/**
+ * Adds the image insert forms to a node/edit page
+ */
+function _node_images_inline_form($image) {
+  $form = array();
+  //$form['inline_filename'] = array('#type' => 'item', '#value' => $image->filename);
+  $form['size_select'] = array(
+    '#type' => 'select',
+    '#title' => t('Image size'),
+    '#default_value' => $image->mediumpath,
+    '#options' => array($image->filepath => t('Original'), $image->mediumpath => t('Medium'), $image->thumbpath => t('Thumbnail')),
+  );
+  $form['align_select'] = array(
+    '#type' => 'select',
+    '#title' => t('Align'),
+    '#default_values' => 'left',
+    '#options' => array('left' => t('Left'), 'right' => t('Right'), 'clear' => t('Clear')),           
+  );
+  $form['link_to'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Link to URL'),
+    '#description' => t("Enter a URL you would like to from this image or select from an option below"),
+  );
+  $form['links'] = array(
+    '#type' => 'radios',
+    '#default_value' => '',
+    '#options' => array('' => t('None'), base_path() . $image->filepath => t('Original Image')),
+    '#attributes' => array('class' => 'link-tos'),
+    '#name' => $image->id,
+  );
+  $form['caption_select'] = array(
+    '#type' => 'checkboxes',
+    '#title' => t('Include Caption?'),
+    '#options' => array('1' => t('Yes')),
+    '#description' => t('(If selected, this will insert the description below the image as a caption.)')
+  );
+  return $form;
+}
+
+
+/**
+ * Theme node images list.
+ */
+function theme_node_images_list(&$form) {
+  $header = array('', t('Thumbnail'), t('Description'), t('Size'), t('Weight'), t('Delete'));
+  drupal_add_tabledrag('node-image-attachments', 'order', 'sibling', 'upload-weight');
+   
+  foreach (element_children($form) as $key) {
+    if (is_numeric($key)) {
+      $form[$key]['id']['#attributes']['class'] = 'upload-weight-'.$key;
+      $row = array();
+      $row[] = '';
+      $row[] = drupal_render($form[$key]['thumbnail']);
+      $row[] = drupal_render($form[$key]['meta']);
+      $row[] = drupal_render($form[$key]['size']);
+      if (isset($form[$key]['weight'])) {
+        $form[$key]['weight']['#attributes']['class'] = 'upload-weight';
+        $row[] = drupal_render($form[$key]['weight']);
+      }
+      $row[] = drupal_render($form[$key]['delete']);
+      $rows[] = array('data' => $row, 'class' => 'draggable');
+    }
+  }
+  $output = theme('table', $header, $rows, array('id' => 'node-image-attachments'));
   $output .= drupal_render($form);
-  $output .= '</fieldset>';
+  return $output;
+}
+
+/**
+ * Theme node images list for inline placement
+ */ 
+function theme_node_images_list_inline(&$form) {
+  $header = array(t('Uploaded Images'), t('File Information'));
+  drupal_add_css('modules/node_images/inline_form.css');
   
+  foreach (element_children($form) as $key) {
+     $form[$key]['file_info'] = image_get_info($form[$key]['meta']['path']['#value']);
+     $row = array();
+     $row[] = drupal_render($form[$key]['thumbnail']);
+     $row[] = array('data' => theme_node_images_inline_image_form($key, $form[$key]), 'class' => 'node-images-image-options');
+     $rows[] = array('data' => $row);
+     // discard data that we didn't use for this form
+     unset($form[$key]);
+  }
+  $output = theme('table', $header, $rows, array('id' => 'node-image-attachments'));
+  $output .= drupal_render($form);
+  return $output;
+}
+function theme_node_images_inline_image_form($image_id, $form_item) {
+  $output = '<div id="node_images_inline_image '. $image_id .'"><div class="node_images image_information">';
+  $output .= '<fieldset class="collapsible collapsed"><legend>'. t("Show Options") .'</legend>';
+  $output .= '<div class="node-images-size">'. t("File Size: ") . $form_item['size']['#value'] .'</div>';
+  $output .= '<div class="node-images-dimensions">'. t("Original Dimensions: ") . $form_item['file_info']['width'] .'x'. $form_item['file_info']['height'] .'</div>';
+  $output .= '<div class="node-images-inline-insert">';
+  $output .= drupal_render($form_item['meta']['filename']);
+  $output .= drupal_render($form_item['meta']['description']);
+  $output .= drupal_render($form_item['meta']['caption']);
+  $output .= drupal_render($form_item['link_to']);
+  $output .= drupal_render($form_item['links']);
+  //$output .= '<div class="link-options"><a class="none link-button" id="'. $image_id .'-link-none" name="">None</a><a class="original link-button" id="'. $image_id .'-link-original" name="'. $form_item['meta']['path'] .'">Original</a></div>';
+  $output .= '<div class="size-select">'. drupal_render($form_item['size_select']) .'</div>';
+  $output .= '<div class="align-select">'.drupal_render($form_item['align_select']) .'</div>';
+  $output .= '<div class="caption-select">'. drupal_render($form_item['caption_select']).'</div>';
+  $output .= '<div id="niif' . $image_id .'" class="node_images_inline_submit"><a id="'. $image_id .'" class="insert-button">Send to Editor</a></div>';
+  $output .= '</div></fieldset>';
+  $output .= '</div></div>';
   return $output;
 }
 
 /**
  * Process result from node images list.
  */
-function _node_images_list_submit($form_id, $form_values) {
+function _node_images_list_submit($form, $form_state) {
+  
   global $user;
-  $node = node_load($form_values['nid']);
+  $node = node_load($form_state['values']['nid']);
   if (!node_access('update', $node)) return;
   $delete_access = node_access('delete', $node);
 
-  foreach($form_values['rows'] as $id => $edit) {
+  foreach ($form_state['values']['rows'] as $id => $edit) {
     if ($edit['delete']) {
-      $r = db_fetch_object(db_query('SELECT filepath, thumbpath, uid FROM {node_images} WHERE id=%d AND nid=%d',
-        $id, $node->nid));
+      $r = db_fetch_object(db_query('SELECT filepath, thumbpath, uid FROM {node_images} WHERE id=%d AND nid=%d', $id, $node->nid));
 
       // if user has no delete access to the node, he can delete his own images only
       if (!$delete_access && $user->uid != $r->uid) continue;
       
       // delete selected image
       file_delete($r->filepath);
+      file_delete($r->mediumpath);
       file_delete($r->thumbpath);
       db_query('DELETE FROM {node_images} WHERE id=%d AND nid=%d', $id, $node->nid);
     }
     else {
       // 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("UPDATE {node_images} SET filename='%s', description='%s', caption='%s', weight=%d WHERE id=%d AND nid=%d", $edit['meta']['filename'], $edit['meta']['description'], $edit['meta']['caption'], $edit['weight'], $id, $node->nid);
     }
   }
   drupal_set_message(t('The changes have been saved.'));
@@ -485,85 +907,253 @@ function _node_images_list_submit($form_
  */
 function _node_images_upload($edit, $node) {
   global $user;
-  if (($file = file_check_upload()) && user_access('create node images')) {
-    // The uploaded file must be an image
-    $info = image_get_info($file->filepath);
-    if (!$info) {
-      form_set_error('upload', t('The uploaded file !name is not a valid image.', array('!name' => theme('placeholder', $file->filename))));
-      return FALSE;
+  
+  if (user_access('create node images')) { 
+    $image_path = file_create_path(_node_images_get_directory());
+    $extensions = variable_get('node_images_extensions', 'jpg jpeg gif png zip gz');
+    $validators = array(
+      //'file_validate_is_image' => array(),
+      'file_validate_extensions' => array($extensions),
+    );
+  
+    if ($file = file_save_upload('node_image_upload', $validators, FALSE, FILE_EXISTS_RENAME)) {
+      // Validate max images for the current node
+      $sql = db_fetch_object(db_query('SELECT COUNT(*) AS count FROM {node_images} WHERE nid=%d', $node->nid));
+      $max = variable_get('node_images_max_images', 4);
+      $count = $sql->count;
+      if ($count >= $max) {
+        file_delete($file->filepath);
+        form_set_error('upload', t('The selected file !name can not be uploaded, because it exceeds the maximum limit of !max files.', array('!name' => theme('placeholder', $file->filename), '!max' => theme('placeholder', $max))), 'error');
+        return FALSE;
+      }
+      $file_info = image_get_info($file->filepath);
+      $extension = $file_info['extension'];
+      if(!$extension) {
+        $extension = $extension = substr(strrchr($file->filename, '.'), 0);
+      }
+      if ($extension == '.zip' || $extension == '.gz') {
+        $files = _node_images_process_archive($file, $edit, $extension);
+      } 
+      else {
+        $files = _node_images_process_image($file, $edit);
+      }
+      return $files;
     }
-    
-    //Munge the filename as needed for security purposes.
-    $file->filename = upload_munge_filename($file->filename, NULL, 0);
+  }
+}
+
+/**
+ * Helper Function For Saving Uploads: This function processes an archive file
+ */
+function _node_images_process_archive($file, $edit, $ext) {
+  global $user;
+  
+  $image_path = file_create_path(_node_images_get_directory());
+  $sub_dir = $edit['nid'];
+  $path = $image_path .'/'. $sub_dir;
+  $tmp_path = $path .'/tmp';
+  $fpath = escapeshellcmd($file->filepath);
+  
+  // Check our directories
+  file_check_directory($path, 1, $sub_dir);
+  file_check_directory($tmp_path, 1, 'tmp');
+  
+  switch ($ext) {
+    case '.gz':
+      // untar and gzip stuff in dir
+      `tar xvzf $fpath --directory $tmp_path`;
+      file_delete($file->filepath);
+      break;
+    case '.zip':
+      // assume unzip file into dir
+      // `unzip /tmp/$f -d $image_dir`;
+      // More complex but more portable way of doing things
+      if (class_exists('ZipArchive')) {
+        $zip = new ZipArchive;
+        if ($zip->open($fpath) === TRUE) {
+          $zip->extractTo($tmp_path);
+          $zip->close();
+        } 
+        else {
+          form_set_error('image', t('The uploaded file was not a zip archive.'));
+        }
+      } 
+      else {
+        //drupal_set_message("php does not have built in zip support using system call to the unzip binary".'status');
+        `unzip $fpath -d $tmp_path`;
+      }
+      file_delete($file->filepath);
+      break;
+    default:
+      file_delete($file->filepath);
+      drupal_set_message('Not a valid archive file');
+      break;
+  }
+  // Our mask for image files when we scan our directories
+  //$mask = '.*\.(gif|GIF|Gif|jpg|JPG|Jpg|jpeg|JPEG|Jpeg|png|PNG|Png)';
+  $mask = '.*\.([gG][iI][fF]|[jJ][pP][eE]?[gG]|[pP][nN][gG])';
+  // We can't be certain of the unarchived directory name so we scan our node's directory
+  // and get an array of directories that are in there...
+  $node_image_directories = _node_images_get_archive_dirs($tmp_path);
+
+  // After we have our directories we scan for files
+  foreach ($node_image_directories as $key => $directory) {
+    $files = file_scan_directory($directory, $mask, array('.', '..', 'CVS', '__MACOSX'), 0, FALSE);
+    if (is_array($files)) {
+      foreach ($files as $key => $filetmp) {
+        // If the file is an image, we can go ahead and process it normally
+        if ($info = image_get_info($filetmp->filename)) {
+          $basename = basename($filetmp->filename);       
+          $filetmp->filepath = $filetmp->filename;
+          $filetmp->filename = $basename;
+          $filetmp->filemime = $info['mime_type'];
+          
+          if ($newfile = _node_images_process_image($filetmp, $edit, $path, $info) ) {
+            $newfiles[$newfile->id] = $newfile;
+          }
+        }
+      }
+    }
+    // Clean up zip file directories and Mac junk 
+    _node_images_rmdir($directory);
+  }
+  if (file_check_directory($tmp_path, FALSE)) {
+    _node_images_rmdir($tmp_path); 
+  }
+  return $newfiles;
+}
 
-    // Validate file extension
-    $extensions = variable_get('node_images_extensions', 'jpg jpeg gif png');
-    $regex = '/\.('. ereg_replace(' +', '|', preg_quote($extensions)) .')$/i';
-    if (!preg_match($regex, $file->filename)) {
-      form_set_error('upload', t('The selected file !name can not be uploaded, because it is only possible to attach files with the following extensions: !files-allowed.', array('!name' => theme('placeholder', $file->filename), '!files-allowed' => theme('placeholder', $extensions))));
-      return FALSE;
-    }
-
-    // Validate max images for the current node
-    $sql = db_query('SELECT * FROM {node_images} WHERE nid=%d', $node->nid);
-    $max = variable_get('node_images_max_images', 4);
-    $count = db_num_rows($sql);
-    if ($count >= $max) {
-      form_set_error('upload', t('The selected file !name can not be uploaded, because it exceeds the maximum limit of !max files.', array('!name' => theme('placeholder', $file->filename), '!max' => theme('placeholder', $max))), 'error');
-      return FALSE;
-    }
-
-    // Scale image to the maximum allowed resolution (default is 400x300)
-    // (if not set in the node_images admin settings, use the default upload max resolution
-    list($width, $height) = explode('x', variable_get('node_images_large_resolution', '400x300'));
-    if (!$width || !$height) {
-      list($width, $height) = explode('x', variable_get('upload_max_resolution', '400x300'));
-    }
-    if (!$width || !$height) {
-      list($width, $height) = explode('x', '400x300');
-    }
-    if ($width && $height) {
-      $result = image_scale($file->filepath, $file->filepath, $width, $height);
-      if ($result) {
-        $file->filesize = filesize($file->filepath);
-        drupal_set_message(t('The image was resized to fit within the maximum allowed resolution of %resolution pixels.',
-          array('%resolution' => $width.'x'.$height)));
+/**
+ * Clean up after unarchiving zips and stuff
+ */
+function _node_images_rmdir($dir) {
+  if (is_dir($dir) && $dir != '/') {
+    $dir = (substr($dir, -1) != '/') ? $dir .'/' : $dir;
+    $openDir = opendir($dir);
+    while($file = readdir($openDir)) {
+      if (!in_array($file, array('.', '..'))) {
+        if (!is_dir($dir.$file)) {
+          @unlink($dir.$file);
+        }
+        else {
+          _node_images_rmdir($dir.$file);
+        }
       }
     }
+    closedir($openDir);
+    @rmdir($dir);
+  }
+}
 
-    // Validation from upload.module
-    $fid = 'upload_'.$user->uid;
-    $node->files = array($fid => $file);
-    _upload_validate($node);
-    if (!isset($node->files[$fid])) return FALSE;
-
-    // Normalize filename and check description
-    $dest = _node_images_get_directory();
-    if (trim($edit['description']) == '') {
-      $edit['description'] = basename($file->filename);
-    }
-    if (variable_get('node_images_md5name', FALSE)) {
-      // set md5 file name
-      $extension = substr($file->filename, strrpos($file->filename, '.') + 1);
-      $file->filename = substr(md5($dest.'/'.$file->filename), 0, 16);
-      if ($extension) $file->filename .= '.'.$extension;
+/**
+ * return an array of directories to scan after we've unarchived our upload
+ */
+function _node_images_get_archive_dirs($dir) {
+  if (is_dir($dir)) {
+    $dir = (substr($dir, -1) != '/') ? $dir .'/' : $dir;
+    $openDir = opendir($dir);
+    while ($file = readdir($openDir)) {
+      if (!in_array($file, array('.', '..'))) {
+        if (is_dir($dir.$file)) {
+          // If this directory exists, go through it's contents and trash it; it's junk to us.
+          if ($file == '__MACOSX') {
+            foreach(glob($dir.$file.'/*') as $sf) {
+			  if (is_dir($sf) && !is_link($sf)) {
+				_node_images_rmdir($sf);
+			  } else {
+				unlink($sf);
+			  }  
+			}  
+			_node_images_rmdir($dir.$file);
+          }
+          else {
+            $dirs[] = $dir.$file;
+          }
+        }
+      }
     }
-    $file->filename = preg_replace('/ +/', '_', $file->filename);
+    closedir($openDir);
+  }
+  $dirs[] = $dir;
+  return $dirs;
+}
 
-    // Save uploaded image
-    if ($file = file_save_upload($file, $dest.'/'.strtolower($file->filename))) {
+/**
+ * Helper Function For Saving Uploads: This function processes a single file
+ */
+function _node_images_process_image($file, $edit = array(), $image_path = NULL, $file_info = NULL) {
+  global $user;
+  
+  if (is_null($file_info)) {
+    $file_info = image_get_info($file->filepath);
+  }
+  if (is_null($image_path)) {
+    $path = file_create_path(_node_images_get_directory());
+    if ($edit['nid']) {
+      $image_path = $path .'/'. $edit['nid'];
+    }
+    file_check_directory($image_path, 1, $edit['nid']);
+  }
+  if (trim($edit['description']) == '') {
+    $edit['description'] = basename($file->filename);
+  }
+  if (variable_get('node_images_md5name', FALSE)) {
+    // set md5 file name
+    $extension = $file_info['extension'];
+    $file->filename = substr(md5($dest .'/'. $file->filename), 0, 16);
+    if ($extension) {
+      $file->filename .= '.'. $extension;
+    }
+  }
+  
+  $file->filename = preg_replace('/ +/', '_', $file->filename);
+      
+  //Munge the filename as needed for security purposes.
+  $file->filename = file_munge_filename($file->filename, $extensions, 0);
+     
+  // Scale image to the maximum allowed resolution (default is 400x300)
+  // (if not set in the node_images admin settings, use the default upload max resolution
+  list($width, $height) = explode('x', variable_get('node_images_large_resolution', '400x300'));
+  if (!$width || !$height) {
+    list($width, $height) = explode('x', variable_get('upload_max_resolution', '400x300'));
+  }
+  if (!$width || !$height) {
+    list($width, $height) = explode('x', '400x300');
+  }
+  if ($width && $height) {
+    $result = image_scale($file->filepath, $file->filepath, $width, $height);
+    if ($result) {
+      //$file->filesize = filesize($file->filepath);
+       drupal_set_message(t('The image was resized to fit within the maximum allowed resolution of %resolution pixels.',
+         array('%resolution' => $width.'x'.$height)));
+       }
+    }
+      
+    // Save uploaded image 
+    if (file_move($file->filepath, $image_path .'/'. strtolower($file->filename), FILE_EXISTS_RENAME) ) {
       $thumb = _node_images_create_thumbnail($file->filepath);
+      $medium = _node_images_create_thumbnail($file->filepath, '_med', variable_get('node_images_medium_resolution', '250x250'));
+      
       $file->filesize = filesize($file->filepath);
-      db_query("INSERT INTO {node_images} (nid, uid, filename, filepath, filemime, filesize, thumbpath, thumbsize, weight, description)
-        VALUES (%d, %d, '%s', '%s', '%s', %d, '%s', %d, %d, '%s')",
-	$edit['nid'], $user->uid, $file->filename, $file->filepath, $file->filemime, $file->filesize,
-	$thumb->filepath, $thumb->filesize, $edit['weight'], $edit['description']);
-    }
-    return $file;
+      db_query("INSERT INTO {node_images} (nid, uid, filename, filepath, filemime, filesize, mediumpath, mediumsize, thumbpath, thumbsize, weight, description)
+        VALUES (%d, %d, '%s', '%s', '%s', %d, '%s', %d, '%s', %d, %d, '%s')",
+        $edit['nid'], $user->uid, $file->filename, $file->filepath, $file->filemime, $file->filesize, $medium->filepath, $medium->filesize, $thumb->filepath, $thumb->filesize, $edit['weight'], $edit['description']);
+      
+      // Append file object so we can rebuild our form properly.
+      //
+      $file->id = db_last_insert_id('node_images', 'id');
+      $file->thumbpath = $thumb->filepath;
+      $file->mediumpath =$medium->filepath;
+      $file->thumbsize = $thumb->filesize;
+      $file->uid = $user->uid;
+      $file->weight = $edit['weight'];
+      $file->description = $edit['description'];         
   }
+  return $file;
 }
 
 
+
 /************************************************************
  * Node view functions
  ************************************************************/
@@ -579,17 +1169,17 @@ function theme_node_images_view($node, $
 
   // set maximum number of images for teaser/body
   $view = ($teaser ? 'teaser' : 'body');
-  $count = variable_get('node_images_'.$view.'_images_'.$node->type, 2);
+  $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');
+    $format = variable_get('node_images_'. $view .'_format_'. $node->type, 'thumbs');
   }
 
-  foreach((array)$node->node_images as $id=>$image) {
+  foreach ((array)$node->node_images as $id => $image) {
     $description = check_plain($image->description);
     $pattern = '<img src="%path" alt="%description" />';
-    $thumb = strtr($pattern, array('%path'=>file_create_url($image->thumbpath), '%description'=>$description));
-    $fullsize = strtr($pattern, array('%path'=>file_create_url($image->filepath), '%description'=>$description));
+    $thumb = strtr($pattern, array('%path' => file_create_url($image->thumbpath), '%description' => $description));
+    $fullsize = strtr($pattern, array('%path' => file_create_url($image->filepath), '%description' => $description));
 
     if ($info = getimagesize($image->filepath)) {
       $width = $info[0] + 36;
@@ -601,207 +1191,17 @@ function theme_node_images_view($node, $
     }
 
     if ($format == 'thumbs') {
-      $output .= '<a href="javascript:void(0);" title="'.$description.'" onclick="window.open(\''.
-        file_create_url($image->filepath).'\', \'\', \'height='.$height.',width='.$width.'\');">'.$thumb.'</a> ';
+      $output .= '<a href="javascript:void(0);" title="'. $description .'" onclick="window.open(\''.
+        file_create_url($image->filepath) .'\', \'\', \'height='. $height .',width='. $width .'\');">'. $thumb .'</a> ';
     }
     else {
-      $output .= $fullsize.' ';
+      $output .= $fullsize .' ';
     }
     if ($count>0 && ++$i >= $count) break;
   }
   return $output;
 }
 
-
-/************************************************************
- * Gallery functions
- ************************************************************/
-
-function _node_images_gallery($node) {
-  if (empty($node->node_images)) {
-    drupal_set_message(t('No images uploaded for this content.'));
-    if (user_access('create node images') && node_access('update', $node)) {
-      $output = t('Click <a href="!url">here</a> to upload new images.', array('!url' => url('node/'.$node->nid.'/images')));
-    }
-    return '<p>'.$output.'</p>';
-  }
-  
-  $settings = array('images' => array());
-
-  $i = 1;
-  $thumbs = array();
-  foreach ($node->node_images as $id=>$image) {
-    $thumb_path = file_create_url($image->thumbpath);
-    $thumbs[$i] = array(
-      'src' => $thumb_path,
-      'title' => $image->description,
-    );
-
-    $path = $image->filepath;
-    $info = image_get_info($path);
-    $settings['images'][$i++] = array(
-      'src' => file_create_url($path),
-      'title' => $image->description,
-      'description' => $image->description,
-      'width' => $info['width'],
-      'height' => $info['height'],
-      'thumb' => $thumb_path,
-    );
-  }
-  $total = count($settings['images']);
-
-  if ($total > 0) {
-    $current = (int)$_GET['page'];
-    $current = ($current < 1 || $current > $total) ? 1 : $current;
-
-    $settings['current'] = $current;
-    $settings['total'] = $total;
-
-    $path = drupal_get_path('module', 'node_images');
-    drupal_add_js($path.'/node_images.js');
-    drupal_add_js(array('slideshow' => array($node->nid => $settings)), 'setting');
-    drupal_add_css($path.'/node_images.css');
-
-    $slideshow = array(
-      '#type' => 'node_images_gallery',
-      '#title' => $settings['images'][$current]['title'],
-      '#attributes' => array('class' => 'slideshow-'. $node->nid),
-      '#status' => array(
-        'current' => $current,
-        'total' => $total,
-        'previous' => $current < 1 ? $total : $current - 1,
-        'next' => $current >= $total ? 1 : $current + 1,
-      ),
-      '#image' => $settings['images'][$current],
-      '#weight' => -5,
-    );
-  }
-
-  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);
-
-  $title = t('Photo gallery for %title', array('%title' => $node->title));
-  drupal_set_title($title);
-  return $output;
-}
-
-function theme_node_images_gallery($element) {
-  $output = '<div'. drupal_attributes($element['#attributes']) .'>
-    <div class="header">
-      '. l(t('Previous'), $_GET['q'], array('class' => 'previous', 'rel' => 'nofollow'), 'page='. $element['#status']['previous']) .' |
-      '. t('Image !current of !total', array(
-        '!current' => '<span class="current">'. $element['#status']['current'] .'</span>',
-        '!total' => '<span class="total">'. $element['#status']['total'] .'</span>')) .' |
-      '. l(t('Next'), $_GET['q'], array('class' => 'next', 'rel' => 'nofollow'), 'page='. $element['#status']['next']) .'
-    </div>
-    <img src="'. url($element['#image']['src']) .'" class="polaroid" />
-    <p class="description">'. $element['#title'] .'</p>
-    </div>';
-  return $output;
-}
-
-function theme_node_images_gallery_thumbs($thumbs, $cols = 2) {
-  $count = count($thumbs);
-  $output = '<table id="thumbs-table">';
-
-  $i = 0;
-  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 .= '</table>';
-  return $output;
-}
-
-
-/************************************************************
- * Helper functions - admin settings
- ************************************************************/
-
-/**
- * Menu callback; admin settings page.
- */
-function node_images_admin_settings() {
-  _node_images_check_settings();
-
-  $form['node_images_path'] = array(
-    '#type' => 'textfield',
-    '#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() .'/')),
-    '#after_build' => array('_node_images_check_directory'),
-  );
-  $form['node_images_large_resolution'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Resolution for large images'),
-    '#default_value' => variable_get('node_images_large_resolution', '400x300'),
-    '#size' => 19,
-    '#maxlength' => 9,
-    '#description' => t('The size for large images in the node gallery, expressed as WIDTHxHEIGHT (e.g. 400x300). If not set, the image will be resized to the maximum allowed resolution in the upload module settings.'),
-  );
-  $form['node_images_thumb_resolution'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Resolution for thumbnails'),
-    '#default_value' => variable_get('node_images_thumb_resolution', '100x100'),
-    '#size' => 15,
-    '#maxlength' => 7,
-    '#description' => t('The thumbnail size expressed as WIDTHxHEIGHT (e.g. 100x75).'),
-  );
-  $form['node_images_extensions'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Default permitted image extensions'),
-    '#default_value' => variable_get('node_images_extensions', 'jpg jpeg gif png'),
-    '#maxlength' => 255,
-    '#description' => t('Default image extensions that users can upload. Separate extensions with a space and do not include the leading dot.'),
-  );
-  $form['node_images_max_images'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Maximum number of images'),
-    '#default_value' => variable_get('node_images_max_images', 4),
-    '#size' => 6,
-    '#maxlength' => 2,
-    '#description' => t('The maximum number of images a user can upload for each node.'),
-  );
-  $form['node_images_md5name'] = array(
-    '#type' => 'checkbox',
-    '#title'=> t('MD5 filenames'),
-    '#description' => t('Override uploaded filenames with the MD5 hash of the file.'),
-    '#default_value' => variable_get('node_images_md5name', FALSE),
-  );
-
-  return system_settings_form($form);
-}
-
-/**
- * Checks if the upload.module is enabled, and the existence of an image toolkit.
- *
- * @param $form_element
- *   The form element containing the name of the directory to check.
- */
-function _node_images_check_settings() {
-  // Make sure upload module is enabled
-  if (!module_exists('upload')) {
-    drupal_set_message(t('node_images.module require upload.module to be enabled.'), 'error');
-  }
-
-  // Make sure we've got a working toolkit
-  if (!image_get_toolkit()) {
-    drupal_set_message(t('Make sure you have a working image toolkit installed and enabled, for more information see: %settings', array('%settings' => l(t('the settings page'), 'admin/settings/image-toolkit'))), 'error');
-  }
-}
-
-
 /************************************************************
  * Helper functions - other
  ************************************************************/
@@ -818,7 +1218,7 @@ function _node_images_check_settings() {
   global $user;
   $variables = array('%uid' => $user->uid, '%username' => $user->name);
   if ($form_element) {
-    $path = file_directory_path().'/'.strtr($form_element['#value'], $variables);
+    $path = file_directory_path() .'/'. strtr($form_element['#value'], $variables);
     _node_images_mkdir_recursive($path, FILE_CREATE_DIRECTORY, $form_element['#parents'][0]);
     return $form_element;
   }
@@ -829,10 +1229,10 @@ function _node_images_check_settings() {
 function _node_images_mkdir_recursive($path, $mode, $form_item) {
   $folders = explode("/", $path);
   $dirs = array();
-  foreach($folders as $folder) {
+  foreach ($folders as $folder) {
     $dirs[] = $folder;
     $dir = implode('/', $dirs);
-    if (!file_check_directory($dir, $mode, $form_item)) {
+    if ($dir != 'sites' && $dir != 'sites/default' && !file_check_directory($dir, $mode, $form_item)) {
       mkdir($dir);
     }
   }
@@ -843,18 +1243,20 @@ function _node_images_mkdir_recursive($p
  */
 function _node_images_get_directory() {
   global $user;
-  $path = file_directory_path().'/'.variable_get('node_images_path', 'node_images');
+  $path = file_directory_path() .'/'. variable_get('node_images_path', 'node_images');
   return strtr($path, array('%uid' => $user->uid, '%username' => $user->name));
 }
 
 /**
  * Create the thumbnail for the uploaded image.
  */
-function _node_images_create_thumbnail($source, $suffix = '_tn') {
-  $size = variable_get('node_images_thumb_resolution', '100x100');
+function _node_images_create_thumbnail($source, $suffix = '_tn', $size = NULL, $path = NULL) {
+  if (is_null($size)) {
+    $size = variable_get('node_images_thumb_resolution', '100x100'); 
+  } 
   list($width, $height) = explode('x', $size);
   $dest = preg_replace('!(\.[^/.]+?)?$!', "$suffix\\1", $source, 1);
-    
+
   if ($size = @getimagesize($source)) {
     if (!image_scale($source, $dest, $width, $height)) {
       file_copy($source, $dest, FILE_EXISTS_REPLACE);
@@ -882,28 +1284,6 @@ function _node_images_space_used($uid) {
   return db_result(db_query('SELECT SUM(filesize+thumbsize) FROM {node_images} WHERE uid=%d', $uid));
 }
 
-/**
- * Menu-callback for JavaScript-based uploads.
- */
-function _node_images_js() {
-  $edit = $_POST;
-  if ($nid = $edit['nid']) {
-    $node = node_load($nid);
-    // upload image
-    _node_images_upload($edit, $node);
-    // generate node images edit page
-    $form = _node_images_edit_form($node);
-  } else {
-    drupal_set_message(t('Unable to attach images to the current node.'));
-  }
-  $output = theme('status_messages');
-  if ($form) $output .= $form;
-
-  // We send the updated file attachments form.
-  print drupal_to_js(array('status' => TRUE, 'data' => $output));
-  exit();
-}
-
 
 /************************************************************
  * Views API hooks
diff -urpN node_images-5-x/node_images.pages.inc node_images/node_images.pages.inc
--- node_images-5-x/node_images.pages.inc	1969-12-31 16:00:00.000000000 -0800
+++ node_images/node_images.pages.inc	2008-04-20 13:43:10.000000000 -0700
@@ -0,0 +1,240 @@
+<?php
+// $Id: node_images.pages.inc,v 1.28.2.1 2008/02/27 19:44:44 goba Exp $
+
+/**
+ * @file
+ * Page callbacks for node_images galleries
+ */
+
+
+/************************************************************
+ * Gallery functions
+ ************************************************************/
+
+function _node_images_gallery($node) {
+  if (empty($node->node_images)) {
+    drupal_set_message(t('No images uploaded for this content.'));
+    if (user_access('create node images') && node_access('update', $node)) {
+      $output = t('Click <a href="!url">here</a> to upload new images.', array('!url' => url('node/'. $node->nid .'/images')));
+    }
+    return '<p>'. $output .'</p>';
+  }
+  
+  $settings = array('images' => array());
+
+  $i = 1;
+  $thumbs = array();
+  foreach ($node->node_images as $id => $image) {
+    $thumb_path = file_create_url($image->thumbpath);
+    $thumbs[$i] = array(
+      'src' => $thumb_path,
+      'title' => $image->description,
+    );
+
+    $path = $image->filepath;
+    $info = image_get_info($path);
+    $settings['images'][$i++] = array(
+      'src' => file_create_url($path),
+      'title' => $image->description,
+      'description' => $image->description,
+      'width' => $info['width'],
+      'height' => $info['height'],
+      'thumb' => $thumb_path,
+    );
+  }
+
+  $total = count($settings['images']);
+
+  if ($total > 0) {
+    $current = (int)$_GET['page'];
+    $current = ($current < 1 || $current > $total) ? 1 : $current;
+
+    $settings['current'] = $current;
+    $settings['total'] = $total;
+
+    $path = drupal_get_path('module', 'node_images');
+    drupal_add_js($path .'/node_images.js');
+    drupal_add_js(array('slideshow' => array($node->nid => $settings)), 'setting');
+    drupal_add_css($path .'/node_images.css');
+
+    $slideshow = array(
+      '#type' => 'node_images_gallery',
+      '#title' => $settings['images'][$current]['title'],
+      '#attributes' => array('class' => 'slideshow-'. $node->nid),
+      '#status' => array(
+        'current' => $current,
+        'total' => $total,
+        'previous' => $current < 1 ? $total : $current - 1,
+        'next' => $current >= $total ? 1 : $current + 1,
+      ),
+      '#image' => $settings['images'][$current],
+      '#weight' => -5,
+    );
+  }
+
+  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);
+
+  $title = t('Photo gallery for %title', array('%title' => $node->title));
+  drupal_set_title($title);
+  return $output;
+}
+
+function theme_node_images_gallery($element) {
+  $query_previous = array(drupal_query_string_encode(array('page' => $element['#status']['previous']), array()));
+  $query_next = array(drupal_query_string_encode(array('page' => $element['#status']['next']), array()));
+  $output = '<div'. drupal_attributes($element['#attributes']) .'>
+    <div class="header">
+      '. l(t('Previous'), $_GET['q'], array( 'arrtibutes' => array('class' => 'previous', 'rel' => 'nofollow'), 'query' => count($query_previous) ? implode('&', $query_previous) : NULL)) .' |
+      '. t('Image !current of !total', array(
+        '!current' => '<span class="current">'. $element['#status']['current'] .'</span>',
+        '!total' => '<span class="total">'. $element['#status']['total'] .'</span>')) .' |
+      '. l(t('Next'), $_GET['q'], array(array('class' => 'next', 'rel' => 'nofollow'), 'query' => count($query_next) ? implode('&', $query_next) : NULL)) .'
+    </div>
+    <img src="'. url($element['#image']['src']) .'" class="polaroid" />
+    <p class="description">'. $element['#title'] .'</p>
+    </div>';
+  return $output;
+}
+
+function theme_node_images_gallery_thumbs($thumbs, $cols = 2) {
+  $count = count($thumbs);
+  $output = '<table id="thumbs-table">';
+  $i = 0;
+  foreach ($thumbs as $id => $thumb) {
+    $query = array(drupal_query_string_encode(array('page' => $id), array()));
+    $attributes = array('title' => $thumb['title'], 'rel' => 'nofollow');
+    $query_array = count($query) ? implode('&', $query) : NULL;
+    
+    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($attributes, 'query' => $query_array, 'html' => TRUE)) . $description .'</td>';
+    if ($i % $cols == $cols - 1 || $n >= $count) $output .= "</tr>";
+    $i++;
+  }
+
+  $output .= '</table>';
+  return $output;
+}
+
+/**
+ * Menu-callback for JavaScript-based uploads.
+ */
+function node_images_js() {
+  $GLOBALS['devel_shutdown'] = FALSE;
+  $edit = $_POST;
+  if (ctype_digit($edit['nid'])) {
+    $node = node_load($edit['nid']);
+    // upload image
+    if($file = _node_images_upload($edit, $node)) {
+      if (is_array($file)) {
+        //append $node->node_images with our new files
+        foreach ($file as $key => $newfile) {
+          $node->node_images[$key] = $newfile;
+        }        
+      } else {
+        //$form_element =  _node_images_image_form($file);
+        $node->node_images[$file->id] = $file;
+      }
+      
+      // Build the new form.
+      
+      $form_state = array('submitted' => FALSE);
+      $form_build_id = $_POST['form_build_id'];
+      $form_state['storage']['mode'] = $edit['mode'];
+      
+      $form = form_get_cache($form_build_id, $form_state);
+      $form = drupal_rebuild_form('_node_images_edit_form', $form_state, array($form_state, $node));
+      
+      // Rebuild our form_state
+      
+      foreach ($node->node_images as $id => $image) {
+        $form_state['values']['rows'][$id] = array(
+          'thumbnail' => $image->thumbpath,
+          'mediumpath' => $image->mediumpath,
+          'description' => $image->description,
+          'path' => $image->path,
+          'size' => $image->size,
+          'weight' => $image->weight,
+          'delete' => $image->delete,
+        );
+      }
+      
+      $form_state['values']['nid'] = $edit['nid'];
+      
+      form_set_cache($form_build_id, $form, $form_state);
+      $form += array(
+        '#post' => $_POST,
+        '#programmed' => FALSE,
+        '#parents' => array(),
+      );
+      drupal_alter('form', $form, array(), 'node_images_js');
+      $form = form_builder('_node_images_edit_form', $form, $form_state);
+      
+      if(isset($form['body_field']) && isset($form['node_images'])) {
+        //$form['node_images']['node_images'][$file->id] = $form_element;
+        $return_form = $form['node_images']['node_images'];
+        unset($form_state['storage'], $form_state['rebuild']);
+         
+      }
+      else {
+        //$form['node_images']['node_images'][$file->id] = $form_element;
+        $return_form = $form;
+      }      
+      
+      unset($return_form['#prefix'], $return_form['#suffix'], $return_form['node_images']['#prefix'], $return_form['node_images']['#suffix']);
+    }
+  } 
+  else {
+    drupal_set_message(t('Unable to attach images to the current node.'));
+  }
+  $output = theme('status_messages');
+  if ($return_form) {
+    $output .= drupal_render($return_form);
+  }
+
+  // We send the updated file attachments form.
+  print drupal_to_js(array('status' => TRUE, 'data' => $debug. $output));
+  exit;
+}
+
+/**
+ * Processes changes made in form produced by node_images_ajax_inline() and submitted via javascript
+ */
+function node_images_save_js() {
+  global $user;
+  $GLOBALS['devel_shutdown'] = FALSE;
+  
+  $edit = $_POST;
+  if (ctype_digit($edit['nid']) && user_access('create node images', $user)) {
+    foreach($edit['rows'] as $id => $image) {
+      db_query("UPDATE {node_images} SET filename='%s', description='%s', caption='%s' WHERE id=%d AND nid=%d", $image['meta']['filename'], $image['meta']['description'], $image['meta']['caption'], $id, $edit['nid']);
+    }
+    drupal_set_message('Changes saved.');
+  }
+  $node = node_load($edit['nid']);
+  
+  // Build the new form.
+      
+  $form_state = array('submitted' => FALSE);
+  $form_build_id = $_POST['form_build_id'];
+  $form_state['storage']['mode'] = $edit['mode'];
+      
+  $form = form_get_cache($form_build_id, $form_state);
+  $form = drupal_rebuild_form('_node_images_edit_form', $form_state, array($form_state, $node));
+  $form_state['values']['nid'] = $edit['nid'];
+      
+  form_set_cache($form_build_id, $form, $form_state);
+
+  $output = theme('status_messages');
+
+ // We send the updated file attachments form.
+  print drupal_to_js(array('status' => TRUE, 'data' => $debug. $output));
+  exit;
+}
