Index: invite.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/invite/Attic/invite.module,v
retrieving revision 1.10.2.18
diff -u -r1.10.2.18 invite.module
--- invite.module	18 Feb 2007 22:03:07 -0000	1.10.2.18
+++ invite.module	18 Feb 2007 23:25:55 -0000
@@ -46,50 +46,41 @@
   return array('send invitations');
 } 
 
-/*
- * Implementation of hook_settings
- * Drupal 5 does away with hook_settings()
- */
 function _invite_settings() {
-  // Build an array of all roles
-  $result = db_query('SELECT * FROM {role}');
-  while ($t = db_fetch_object($result)) {
-    $t->rid != 1 && $target_roles[$t->rid] = $t->name;
-  }
+  $target_roles = $roles = user_roles();
+  unset($target_roles[DRUPAL_ANONYMOUS_RID]);
 
   $form['user_settings'] = array(
     '#type' => 'fieldset',
     '#title' => t('User settings'),
   );
 
-  // configure settings for the new members
-  $roles = user_roles();
+  // settings for new members
   $form['user_settings']['invite_target_role_default'] = array(
     '#type' => 'select',
     '#title' => t('Target role (default)'),
-    '#default_value' => variable_get('invite_target_role_default', '2'),
-    '#options' => ($target_roles ? $target_roles : array('-1'=>t('(Please add a target role.)'))),
-    '#description' => t('Choose the role that invited users will be added to. For example, <em>Member</em>.'),
+    '#default_value' => variable_get('invite_target_role_default', DRUPAL_AUTHENTICATED_RID),
+    '#options' => ($target_roles ? $target_roles : array('-1' => t('(Please add a target role.)'))),
+    '#description' => t('Choose the role that invited users will be added to. For example, <em>authenticated user</em>.'),
   );
   
-  foreach ($roles as $key => $role) {
+  foreach ($roles as $role) {
     $role_no_space = str_replace(' ', '_', $role);
     $form['user_settings']['invite_target_role_'. $role_no_space] = array(
       '#type' => 'select',
       '#title' => t('Target role for %role', array('%role' => $role)),
-      '#default_value' => variable_get('invite_target_role_'. $role_no_space, '2'),
-      '#options' => ($target_roles ? $target_roles : array('-1'=>t('(Please add a target role.)'))),
+      '#default_value' => variable_get('invite_target_role_'. $role_no_space, DRUPAL_AUTHENTICATED_RID),
+      '#options' => ($target_roles ? $target_roles : array('-1' => t('(Please add a target role.)'))),
       '#description' => t('Choose the role that invited users will be added to if invited by someone who has the %role role.', array('%role' => $role)),
     );
   }
 
   $form['user_settings']['invite_expiry'] = array(
     '#type' => 'select',
-    '#title' => t('Invitation Expiry'),
+    '#title' => t('Invitation expiry'),
     '#default_value' => variable_get('invite_expiry', 30),
     '#options' => drupal_map_assoc(array(5, 10, 15, 20, 25, 30, 45, 60)),
-    '#description' => t('Set the expiry period for user invitations, in days'),
-    '#extra' => $extra = 0,
+    '#description' => t('Set the expiry period for user invitations, in days.'),
     '#multiple' => FALSE,
     '#required' => TRUE,
   );  
@@ -97,7 +88,7 @@
     '#type' => 'checkbox',
     '#title' => t('Allow deletion of joined users'),
     '#default_value' => variable_get('invite_allow_join_delete', 0),
-    '#description' => t('After an invitee has registered, this option allows a site administrator the option to delete the invitations marked as joined. Useful for users who delete their account to be re-invited or for users who change their email address')
+    '#description' => t('After an invitee has registered, this option allows users to delete invitations marked as <em>Joined</em>. Useful to prevent users from deleting their account to be re-invited.')
   );
 
   $form['user_roles'] = array(
@@ -112,26 +103,26 @@
       '#type' => 'select',
       '#title' => t($role),
       '#default_value' => variable_get('invite_maxnum_'. $role_no_space, 0),
-      '#options' => array(0 => t('unlimited'), 5 => 5, 10 => 10, 20 => 20, 50 =>50, 100 => 100, 300 =>300, 500 => 500, 1000 => 1000),
-      '#extra' => $extra = 0,
+      '#options' => array(0 => t('unlimited'), 5 => 5, 10 => 10, 20 => 20, 50 => 50, 100 => 100, 300 => 300, 500 => 500, 1000 => 1000),
+      '#description' => t('Allows to limit the total number of invitations a user can send who has the %role role.', array('%role' => $role)),
       '#multiple' => FALSE,
       '#required' => TRUE,
     );
   }
   
+  // email settings
   $form['email_settings'] = array(
     '#type' => 'fieldset',
     '#title' => t('Email settings'),
   );
 
-  // configure settings for the email
   $form['email_settings']['invite_subject'] = array(
     '#type' => 'textfield',
     '#title' => t('Subject'),
-    '#default_value' => variable_get('invite_subject',t("You've been invited")),
+    '#default_value' => variable_get('invite_subject', t("You've been invited")),
     '#size' => 20,
     '#maxlength' => 64,
-    '#description' => t('Type the subject of the invitation email'),
+    '#description' => t('Type the subject of the invitation email.'),
     '#attributes' => $attributes = NULL,
     '#required' => $required = FALSE,
   );
@@ -141,10 +132,9 @@
     '#title' => t('Default mail template'),
     '#default_value' => invite_get_mail_template(),
     '#required' => TRUE,
-    '#description' => t('Use the following placeholders; @site, @homepage, @join_link, @message, @inviter'),
+    '#description' => t('Use the following placeholders; @site, @homepage, @join_link, @message, @inviter.'),
   );
 
-  // configure settings for the email
   $form['email_settings']['invite_use_users_email'] = array(
     '#type' => 'radios',
     '#title' => t('From: email address'),
@@ -161,7 +151,7 @@
     '#default_value' => variable_get('invite_use_users_email_replyto', 0),
   );
 
-
+  // invite page customization settings
   $form['invite_page'] = array(
     '#type' => 'fieldset',
     '#title' => t('Invite page cutomization'),
@@ -171,11 +161,10 @@
     '#type' => 'textfield', 
     '#title' => t('Invite page title'), 
     '#default_value' => variable_get('invite_page_title', t('Invite your friends and colleagues')), 
-    '#description' => t('The title of the page where users invite friends'),
+    '#description' => t('The title of the page where users invite friends.'),
     '#required' => TRUE
   );
 
-
   $form['invite_page']['invite_help_text'] = array(
     '#type' => 'textarea',
     '#title' => t('Invite help text'),
@@ -188,9 +177,10 @@
    </p>
    <p>At any time, you may delete either 'Pending' or 'Expired' invitations. 'Joined' invitation cannot be deleted and count permanently toward your invitation allotment.</p>")), 
     '#required' => TRUE,
-    '#description' => t('Customize the text that appears above the email form on the invite page for users'),
+    '#description' => t('Customize the text that appears above the email form on the invite page for users.'),
   );
 
+  // advanced settings
   $form['advanced'] = array(
     '#type' => 'fieldset',
     '#title' => t('Advanced settings'),
@@ -203,17 +193,16 @@
     '#type' => 'textfield', 
     '#title' => t('Manually set the <em>From</em> address'), 
     '#default_value' => variable_get('invite_manual_from', variable_get('site_mail', ini_get('sendmail_from'))), 
-    '#description' => t('The email address the email is sent from')
+    '#description' => t('The email address the email is sent from.')
   );
 
   $form['advanced']['invite_manual_reply_to'] = array(
     '#type' => 'textfield', 
     '#title' => t('Manually set the <em>Reply</em> address'), 
     '#default_value' => variable_get('invite_manual_reply_to', variable_get('site_mail', ini_get('sendmail_from'))), 
-    '#description' => t('The email address you want recipients to reply to')
+    '#description' => t('The email address you want recipients to reply to.')
   );
 
-
   return system_settings_form($form);
 }
 
@@ -250,41 +239,39 @@
 }
  
 /**
- * Implementation of hook_form_alter()
+ * Implementation of hook_form_alter().
  */
-
 function invite_form_alter($form_id, &$form) {
-  global $form_values;
   switch ($form_id) {
     case 'user_admin_settings':
       $form['registration']['user_register']['#options']['inviteonly'] = t('New user registration by invitation only.');
       break;
+
     case 'user_register': 
-      $user_admin = user_access('administer users');
-      $invite_only = (variable_get('user_register',1) == 'inviteonly');
+      $valid_invite = FALSE;
       if ($code = arg(2)) {
-        $invite = _invite_fetch_invite($code);
-        if ($invite->count > 0) {
-          $valid_invite = TRUE;
+        if ($invite = _invite_fetch_invite($code)) {
+          $valid_invite = (!$invite->expired);
           $form['invite_code'] = array(
             '#type' => 'value',
             '#value' => $code,
           );
-          $form['invite_referrer'] = array(
-            '#type' => 'value',
-            '#value' => $invite->referrer,
-          );
         }
       }
 
-      if ((!$user_admin) && $invite_only) {
+      $invite_only = (variable_get('user_register', 1) == 'inviteonly');
+      if ($invite_only && !user_access('administer users')) {
         if (!$valid_invite) {
-          // Redirect to the standard login form if in invite only mode and a valid invite is not present
-          drupal_set_message(t('Sorry, new user registration by invite only.'));
-          drupal_goto('user/');
+          if ($invite->expired) {
+            drupal_set_message(t('Sorry, this invitation code has expired.'));
+          }
+          else {
+            // Redirect to the standard login form if in invite only mode and a valid invite is not present
+            drupal_set_message(t('Sorry, new user registration by invite only.'));
+          }
+          drupal_goto('user');
         }
-
-        if (isset($form['#submit']['user_register_submit'])) {
+        else if (isset($form['#submit']['user_register_submit'])) {
           // If we are in invite only mode, hijack the usual user registration submission
           $form['#submit'] = array('invite_register_submit' => array());
         }
@@ -293,7 +280,7 @@
 
     case 'user_login_block':
       // Remove temptation for non members to try and register
-      if (variable_get('user_register',1) == 'inviteonly') {
+      if (variable_get('user_register', 1) == 'inviteonly') {
         $new_items = array();
         $new_items[] = l(t('Request new password'), 'user/password', array('title' => t('Request new password via e-mail.')));
         $form['links']['#value'] = theme('item_list', $new_items);
@@ -302,59 +289,55 @@
   } 
 }
 
-/*
-* function invite_register_submit($form_id, $form_values)
-*
-* Purpose : perform invite validation on user registration submission
-* 
-* Description : checks for a valid invitation before passing control back to the
-*               core user registration. If the invitation is invalid, the user is
-*               informed, watchdog notified and user registration terminated.
-*/
-
+/**
+ * Perform invite validation on user registration submission for invite-only
+ * sites.
+ * Checks for a valid invitation before passing control back to the core user
+ * registration.
+ */
 function invite_register_submit($form_id, $form_values) {
-  // Don't need to check for invite only mode as invite_form_alter has already done that for us
-  $invite = _invite_fetch_invite($form_values['invite_code']);
-  if ($invite->count > 0) {
-    return user_register_submit($form_id, $form_values);
-  } else {
+  // Don't need to check for invite-only mode as invite_form_alter has already done that for us
+  if ($invite = _invite_fetch_invite($form_values['invite_code'])) {
+    if (!$invite->expired) {
+      return user_register_submit($form_id, $form_values);
+    }
+    else {
+      drupal_set_message(t('Sorry, this invitation code has expired.'));
+    }
+  }
+  else {
     // Do some watchdog stuff
     drupal_set_message(t('You have not been invited to join this site.'));
-    watchdog('invite', 'Uninvited user registration attempt', $link = NULL);
+    watchdog('invite', t('Uninvited user registration attempt.'), WATCHDOG_WARNING);
   }
+  return 'user';
 }
 
-
-/*
-* Implementation of hook_user
-*
-* Types : login / view  - checks for user perm then does drupal_set_message 
-*                         if a users invitee has joined the site
-*         register - displays the registration code fields
-*         validate - checks against the {invite} table if the code and email are valid.  
-*                    If the fields are left blank they are ignored, and the default register events are processed  
-*         insert - on successful insert, the user status is set active and the role is escalated
-*/
- 
-function invite_user($op, &$edit, &$user, $category = NULL) { 
+/**
+ * Implementation of hook_user().
+ */
+function invite_user($op, &$edit, &$account, $category = NULL) { 
   switch ($op) {
     case 'insert':
-      $result = db_query("SELECT * FROM {invite} WHERE reg_code = '%s'", $edit['invite_code']);
-      if ($registration = db_fetch_object($result)) {
-        $targetrole = variable_get('invite_target_role', '2');
-        _invite_role_escalate($user);
-
-        /*
-        ** if they sign up as a different email to the one sent to them, they do 
-        ** not get "joined" properly in the invitee's invite screen.
-        ** this bit fixes that
-        */
-        
-        _invite_set_timestamp($edit['mail'], $user->uid, $edit['invite_code']);
-        _invite_unblock($user->uid);
-      } 
-      else {
-        watchdog('invite', 'User '. check_plain($user->name) .' registration code failed', $link = NULL);
+      if (isset($edit['invite_code'])) {
+        if ($invite = _invite_fetch_invite($edit['invite_code'])) {
+          if (!$invite->expired) {
+            // Update invitation status
+            _invite_set_timestamp($edit['mail'], $account->uid, $edit['invite_code']);
+
+            // Escalate user role
+            $referrer = user_load(array('uid' => $invite->referrer));
+            _invite_role_escalate($account, $referrer);
+
+            // Activate user account for invite-only sites
+            if (variable_get('user_register', 1) == 'inviteonly') {
+              db_query("UPDATE {users} SET status = 1 WHERE uid = %d", $account->uid);
+            }
+          }
+        } 
+        else {
+          watchdog('invite', t('Registration code failed for %name %email.', array('%name' => $account->name, '%email' => '<'. $account->mail .'>')), WATCHDOG_NOTICE, l(t('view'), 'user/'. $account->uid));
+        }
       }
       break;
   }   
@@ -562,20 +545,16 @@
   return $default_max;
 }
 
-function _invite_role_escalate($invitee) {
-  $inviter_uid = db_result(db_query("SELECT uid FROM {invite} WHERE mid = %d", $user->uid));
-  if ($inviter = user_load(array('uid' => $inviter_uid))) {
-    $roles = user_roles();
-    $targets = array();
-    foreach ($inviter->roles as $key => $role) {
-      $role_no_space = str_replace(' ', '_', $role);
-      if (($target = variable_get('invite_target_role_'. $role_no_space, DRUPAL_AUTHENTICATED_RID)) != DRUPAL_AUTHENTICATED_RID) {
-        $targets[] = $target;
-      }
+function _invite_role_escalate($invitee, $inviter) {
+  $targets = array();
+  foreach ($inviter->roles as $role) {
+    $role_no_space = str_replace(' ', '_', $role);
+    if (($target = variable_get('invite_target_role_'. $role_no_space, DRUPAL_AUTHENTICATED_RID)) != DRUPAL_AUTHENTICATED_RID) {
+      $targets[$target] = $target;
     }
   }
-  if (($target_role_default = variable_get('invite_target_role_default', DRUPAL_AUTHENTICATED_RID)) != DRUPAL_AUTHENTICATED_RID) {
-    $targets[] = $target_role_default;
+  if (($target_default = variable_get('invite_target_role_default', DRUPAL_AUTHENTICATED_RID)) != DRUPAL_AUTHENTICATED_RID) {
+    $targets[$target] = $target_default;
   }
   foreach ($targets as $target) {
     db_lock_table('users_roles');
@@ -601,7 +580,7 @@
 
 function _invite_create_regcode(){
   do {
-    $reg_code = substr(md5((string)rand(). date('YmdHis', time())), 0, 8);
+    $reg_code = user_password(8);
     $r = db_query('SELECT COUNT(*) FROM {invite} WHERE reg_code = "%s"', $reg_code);
   } while ((int)db_result($r) > 0);
   return $reg_code;
@@ -670,17 +649,14 @@
   return variable_get('invite_default_mail_template', $template);
 }
 
-function _invite_unblock($uid) {
- 
-   if (is_numeric($uid)) {
-     db_query("UPDATE {users} SET status = 1 WHERE uid = %d", $uid);
-     return TRUE;
-   }
- 
-   return FALSE;
-}
-
-function _invite_fetch_invite($invite_code) {
-  return db_fetch_object(db_query('SELECT COUNT(reg_code) AS count, uid AS referrer FROM {invite} WHERE reg_code = "%s" AND timestamp = 0 GROUP BY referrer', $invite_code));
+/**
+ * Securely check if a valid invitation exists.
+ * @param $code
+ *   An invitation code.
+ * @return
+ *   A database result object.
+ */
+function _invite_fetch_invite($code) {
+  return db_fetch_object(db_query("SELECT uid AS referrer, (expiry < %d) AS expired FROM {invite} WHERE reg_code = '%s' AND timestamp = 0", time(), $code));
 }
 
