Index: joomla.install
===================================================================
RCS file: joomla.install
diff -N joomla.install
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ joomla.install	12 Jun 2009 11:40:55 -0000
@@ -0,0 +1,72 @@
+<?php
+// $Id$
+
+/**
+ * Implementation of hook_install().
+ */
+function joomla_install() {
+  // Create tables.
+  drupal_install_schema('joomla');
+}
+
+/**
+ * Implementation of hook_uninstall().
+ */
+function joomla_uninstall() {
+  // Remove tables.
+  drupal_uninstall_schema('joomla');
+
+  vaiable_del('joomla_database');
+  vaiable_del('joomla_delay_row');
+  vaiable_del('joomla_delay_sec');
+  vaiable_del('joomla_img_folder');
+  vaiable_del('joomla_input_format');
+  vaiable_del('joomla_path');
+  vaiable_del('joomla_prefix');
+  vaiable_del('joomla_update_duplicate');
+}
+
+/**
+ * Implementation of hook_schema().
+ */
+function joomla_schema() {
+  $schema['joomla_users'] = array(
+  'description' => 'Stores the original Joomla user ID and password and links to the {users} table',
+    'fields' => array(
+      'uid' => array(
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => 0,
+        'description' => "The users {users}.uid.",
+      ),
+      'juid' => array(
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => 0,
+        'description' => "The users id from the Joomla database.",
+      ),
+      'password' => array(
+        'type' => 'varchar',
+        'length' => 100,
+        'not null' => TRUE,
+        'default' => '',
+        'description' => "The users original Joomla password.",
+      ),
+      'converted' => array(
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => 0,
+        'description' => "Boolean value storing whether or not the users Joomla password has been converted to an entry in the {users}.pass table.",
+      ),
+    ),
+    'primary key' => array('uid'),
+    'unique keys' => array(
+      'juid' => array('juid'),
+    ),
+  );
+
+  return $schema;
+}
--- joomla.module.486080-1	2009-06-11 23:13:24.000000000 +1200
+++ joomla.module	2009-06-12 23:23:47.000000000 +1200
@@ -209,44 +209,99 @@ function joomla_import($import_type) {  
 		$data_fid = db_fetch_object($results_fid);
 		$fid      = $data_fid->fid;
 		
-		//Check Users
+		  //Check Users
 				        
-        $i  = 0;
-        
-        $results_user = db_query("SELECT * FROM %s ORDER BY id", $table_user);
+      $users_total = 0;
+      $users_updated = 0;
+      $users_new = 0;
+      $users_failed =  0;
+
+      $results_user = db_query("SELECT * FROM %s ORDER BY id", $table_user);
         
-        while ( $data = db_fetch_object($results_user) ) {
-          $i++;
-          $id       = $data->id;
-	      $username = $data->username;
-	      $realname	= addslashes($data->name);
-	      $email    = $data->email;
-	      $status	  = !$data->block;
-	      $registerdate =  strtotime($data->registerDate); 
-	      $lastvisitdate = strtotime($data->lastvisitDate);
+      while ( $data = db_fetch_object($results_user) ) {
+        $users_total++;
 	      
-		  $results_check_user = db_query("SELECT uid,name FROM {users} WHERE name='%s'", $username);
-          $data_user = db_fetch_object($results_check_user);
-          $uid = $data_user->uid;
+        $uid = db_result(db_query("SELECT uid FROM {joomla_users} WHERE juid = %d", $data->id));
           
-          $rec_status = 'Exist';
-          if (!$data_user) {
-            $rec_status = 'New';
-            
-            $sql_uid = " SELECT uid FROM {users} ORDER BY uid DESC LIMIT 1";
-		    $results_last_uid = db_query($sql_uid); 
-		    $data_last_uid = db_fetch_object($results_last_uid);
-		    $last_uid = $data_last_uid->uid;
-		    $new_uid = $data_last_uid->uid + 1;
-	        
-		    db_query("INSERT INTO {users} (uid,name,mail,status,created,access,language,timezone) values (%d,'%s','%s',%d,%d,%d,'en',0)", $new_uid, $username, $email, $status, $registerdate, $lastvisitdate);
-		  } 
-		  
-		  //Check and Update Realname
-		  $results_profile_values = db_query("SELECT COUNT(*) FROM {profile_values} WHERE fid=%d AND uid=%d", $fid, $uid);
-		  if (db_result($results_profile_values) == 0) {
-		    db_query("INSERT INTO {profile_values} (fid,uid,value) VALUES (%d,%d,'%s')", $fid, $uid, $realname); 
-		  }
+        // Check if the user has selected to update previously imported users
+        if ($uid && !$joomla_update_duplicate) {
+          continue;
+        }
+
+        $user = new stdClass();
+
+        // Set uid if we are updating an existing record
+        if ($uid) {
+          $user->uid = $uid;
+        }
+        $user->name = $data->username;
+        $user->mail = $data->email;
+        $user->status = !$data->block;
+        $user->created = strtotime($data->registerDate);
+        $user->access = strtotime($data->lastvisitDate);
+
+        /**
+         * Older versions of Joomla used an unsalted MD5 password hash.  If this
+         * is the case we can use this hash as the Drupal password.
+         */
+        if (strlen($data->password) == 32) {
+          $user->pass = $data->password;
+        }
+
+        $res = FALSE;
+        if (!$uid) {
+          $res = drupal_write_record('users', $user);
+        }
+        elseif ($joomla_update_duplicate) {
+          $res = drupal_write_record('users', $user, 'uid');
+        }
+
+        if ($res) {
+          // Write into the joomla -> drupal user mapping table
+          $joomla_user = new stdClass();
+          $joomla_user->uid = $user->uid;
+          $joomla_user->juid = $data->id;
+          $joomla_user->password = $data->password;
+
+          // If this is set, than we can consider the users password converted
+          if (!empty($user->pass)) {
+            $joomla_user->converted = 1;
+          }
+
+          if ($uid) {
+            drupal_write_record('joomla_users', $joomla_user, 'uid');
+          }
+          else {
+            drupal_write_record('joomla_users', $joomla_user);
+          }
+
+          //Check and Update Realname
+          $profile_value = new stdClass();
+          $profile_value->fid = $fid;
+          $profile_value->uid = $user->uid;
+          $profile_value->value = $data->realname;
+
+          if ($uid) {
+            drupal_write_record('profile_values', $profile_value, array('fid', 'uid'));
+          }
+          else {
+            drupal_write_record('profile_values', $profile_value);
+          }
+        }
+
+        switch ($res) {
+          case SAVED_NEW:
+            $users_new++;
+            break;
+
+          case SAVED_UPDATED;
+            $users_updated++;
+            break;
+
+          default:
+            $users_failed++;
+        }
+      } 
 		  
           //delay
           if ($i % $joomla_delay_row ==0 ) {sleep($joomla_delay_sec);}
@@ -260,9 +315,8 @@ function joomla_import($import_type) {  
           //print theme('maintenance_page', $output, FALSE);
           
           
-        }
-        return "Total imported users: ". $i;
-        break;
+      return sprintf("Processed %d users (%d new, %d updated, %d errors)", $users_total, $users_new, $users_updated, $users_failed);
+      break;
       
       case 'section':
         $output  = "";
@@ -469,4 +523,68 @@ function replace_image_link($text_source
   return $text_result;		
 }
 
-?>
+function joomla_form_alter(&$form, $form_state, $form_id) {
+  if ($form_id == 'user_login' || $form_id == 'user_login_block') {
+    if (isset($form_state['post']['name'])) {
+      $last_validator = array_pop($form['#validate']);
+      $form['#validate'][] = 'joomla_login_validate';
+      $form['#validate'][] = $last_validator;
+    }
+  }
+}
+
+function joomla_login_validate($form, &$form_state) {
+  joomla_authenticate($form_state['values']);
+}
+
+function joomla_authenticate($form_values = array()) {
+  global $user;
+
+  if (!empty($user->uid)) {
+    // User has already sucessfully authenticated
+    return;
+  }
+
+  if (form_get_errors() || empty($form_values['name']) || empty($form_values['pass'])) {
+    return;
+  }
+
+  $account = user_load(array('name' => $form_values['name'], 'status' => 1));
+
+  // The user doesn't exist
+  if (!$account) {
+    return;
+  }
+
+  // See if the user has a password record from Joomla import
+  $joomla_user = db_fetch_object(db_query('SELECT * FROM {joomla_users} WHERE uid = %d', $account->uid));
+  if (!$joomla_user) {
+    return;
+  }
+
+  /**
+   * If the password doesn't contain a colon, it is an unsalted password.
+   * It will have been inserted into the drupal users table during the
+   * import, and to get here the Drupal login must have already failed
+   * against it, so nothing left to do
+   */
+  list($password, $salt) = explode(':', $joomla_user->password, 2);
+  if(!$salt) {
+    return;
+  }
+
+  // Check the salt + supplied password against the md5sum
+  if (md5($form_values['pass'] . $salt) == $password) {
+    $user = $account;
+    watchdog('joomla', 'Converting password for user @name (Joomla id @juid)', array('@name' => $user->name, '@juid' => $joomla_user->juid));
+
+    // Update the users Drupal password
+    user_save($user, array('pass' => $form_values['pass']));
+
+    $joomla_user->converted = 1;
+    drupal_write_record('joomla_users', $joomla_user, array('uid'));
+
+    user_authenticate_finalize($form_values);
+    return $user;
+  }
+}
