Index: flag.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/flag/Attic/flag.module,v
retrieving revision 1.11.2.65
diff -u -r1.11.2.65 flag.module
--- flag.module	22 Feb 2009 03:15:52 -0000	1.11.2.65
+++ flag.module	23 Feb 2009 00:35:14 -0000
@@ -83,6 +83,10 @@
   if (module_exists('token')) {
     include_once $path .'/includes/flag.token.inc';
   }
+  if (module_exists('session_api')) {
+    // Set the anonymous user SID immediately, in case the user logs in.
+    flag_set_sid();
+  }
 }
 
 /**
@@ -139,11 +143,6 @@
   }
   global $user;
 
-  // Anonymous users can't create flags with this system.
-  if (!$user->uid) {
-    return;
-  }
-
   // Get all possible flags for this content-type.
   $flags = flag_get_flags($type);
 
@@ -242,14 +241,8 @@
       );
     }
   }
-  elseif (isset($form['type']) && isset($form['#node'])
-      && ($form_id == $form['type']['#value'] .'_node_form')) {
-    if (!$user->uid) {
-      return;
-    }
-
+  elseif (isset($form['type']) && isset($form['#node']) && ($form_id == $form['type']['#value'] .'_node_form')) {
     $nid = !empty($form['nid']['#value']) ? $form['nid']['#value'] : NULL;
-
     $flags = flag_get_flags('node', $form['type']['#value'], $user);
 
     // Filter out flags which need to be included on the node form.
@@ -345,6 +338,16 @@
  */
 function flag_user($op, &$edit, &$account, $category = NULL) {
   switch ($op) {
+    case 'login':
+      // Migrate anonymous flags to this user's account.
+      if (module_exists('session_api')) {
+        // @ symbol suppresses errors if the user reflags a piece of content
+        // they have already flagged as a logged-in user.
+        @db_query("UPDATE {flag_content} SET uid = %d, sid = 0 WHERE uid = 0 AND sid = %d", $account->uid, flag_get_sid(0));
+        // Delete any remaining flags this user had as an anonymous user.
+        db_query("DELETE FROM {flag_content} WHERE uid = 0 AND sid = %d", flag_get_sid());
+      }
+      break;
     case 'delete':
       // Remove flags by this user.
       db_query("DELETE FROM {flag_content} WHERE uid = %d", $account->uid);
@@ -678,14 +681,21 @@
   $form['roles'] = array(
     '#type' => 'checkboxes',
     '#title' => t('Roles that may use this flag'),
-    '#options' => user_roles(TRUE),
+    '#options' => user_roles(!module_exists('session_api')),
     '#default_value' => $flag->roles,
     '#required' => TRUE,
-    '#description' => t('Checking <em>authenticated user</em> will allow all logged-in users to flag content with this flag. Anonymous users may not flag content.'),
+    '#description' => t('Checking <em>authenticated user</em> will allow all logged-in users to flag content with this flag.'),
     '#weight' => 5,
     '#access' => empty($flag->locked['roles']),
   );
 
+  if (module_exists('session_api')) {
+    $form['roles']['#description'] .= ' ' . t('Support for anonymous users is being provided by <a href="http://drupal.org/project/session_api">Session API</a>.');
+  }
+  else {
+    $form['roles']['#description'] .= ' ' . t('Anonymous users may flag content if the <a href="http://drupal.org/project/session_api">Session API</a> module is installed.');
+  }
+
   // Disabled access breaks checkboxes unless #value is hard coded.
   if (!empty($flag->locked['roles'])) {
     $form['roles']['#value'] = $flag->roles;
@@ -1361,6 +1371,9 @@
  * @param $uid
  *   Optional. The user ID whose flags we're checking. If none given, the
  *   current user will be used.
+ * @param $sid
+ *   Optional. The user SID (proved by Session API) whose flags we're checking.
+ *   If none given, the current user will be used. SID is 0 for logged in users.
  * @param $reset
  *   Reset the internal cache and execute the SQL query another time.
  *
@@ -1372,7 +1385,7 @@
  *   [nid] => [name] => Object from above.
  *
  */
-function flag_get_user_flags($content_type, $content_id = NULL, $uid = NULL, $reset = FALSE) {
+function flag_get_user_flags($content_type, $content_id = NULL, $uid = NULL, $sid = NULL, $reset = FALSE) {
   static $flagged_content;
 
   if ($reset) {
@@ -1383,29 +1396,30 @@
   }
 
   $uid = !isset($uid) ? $GLOBALS['user']->uid : $uid;
+  $sid = !isset($sid) ? flag_get_sid($uid) : $sid;
 
   if (isset($content_id)) {
     if (!isset($flagged_content[$uid][$content_type][$content_id])) {
       $flag_names = _flag_get_flag_names();
-      $flagged_content[$uid][$content_type][$content_id] = array();
-      $result = db_query("SELECT * FROM {flag_content} WHERE content_type = '%s' AND content_id = %d AND (uid = %d OR uid = 0)", $content_type, $content_id, $uid);
+      $flagged_content[$uid][$sid][$content_type][$content_id] = array();
+      $result = db_query("SELECT * FROM {flag_content} WHERE content_type = '%s' AND content_id = %d AND (uid = %d OR uid = 0) AND sid = %s", $content_type, $content_id, $uid, $sid);
       while ($flag_content = db_fetch_object($result)) {
-        $flagged_content[$uid][$content_type][$content_id][$flag_names[$flag_content->fid]] = $flag_content;
+        $flagged_content[$uid][$sid][$content_type][$content_id][$flag_names[$flag_content->fid]] = $flag_content;
       }
     }
-    return $flagged_content[$uid][$content_type][$content_id];
+    return $flagged_content[$uid][$sid][$content_type][$content_id];
   }
 
   else {
-    if (!isset($flagged_content[$uid]['all'][$content_type])) {
+    if (!isset($flagged_content[$uid][$sid]['all'][$content_type])) {
       $flag_names = _flag_get_flag_names();
-      $flagged_content[$uid]['all'][$content_type] = TRUE;
-      $result = db_query("SELECT * FROM {flag_content} WHERE content_type = '%s' AND (uid = %d OR uid = 0)", $content_type, $uid);
+      $flagged_content[$uid][$sid]['all'][$content_type] = TRUE;
+      $result = db_query("SELECT * FROM {flag_content} WHERE content_type = '%s' AND (uid = %d OR uid = 0) AND sid = %s", $content_type, $uid, $sid);
       while ($flag_content = db_fetch_object($result)) {
-        $flagged_content[$uid][$content_type]['all'][$flag_names[$flag_content->fid]][$flag_content->content_id] = $flag_content;
+        $flagged_content[$uid][$sid][$content_type]['all'][$flag_names[$flag_content->fid]][$flag_content->content_id] = $flag_content;
       }
     }
-    return $flagged_content[$uid][$content_type]['all'];
+    return $flagged_content[$uid][$sid][$content_type]['all'];
   }
 
 }
@@ -1493,3 +1507,35 @@
 function flag_check_token($token, $seed) {
   return drupal_get_token($seed) == $token;
 }
+
+/**
+ * Set the Session ID for a user. Utilizes the Session API module.
+ *
+ * This function is only called in flag_init(), to set the current user's
+ * SID in case the user logs in during this request.
+ */
+function flag_set_sid($uid = NULL) {
+  static $sids = array();
+
+  if (!isset($uid)) {
+    $uid = $GLOBALS['user']->uid;
+  }
+
+  if (!isset($sids[$uid])) {
+    if (module_exists('session_api') && session_api_available() && $uid == 0) {
+      $sids[$uid] = session_api_get_sid();
+    }
+    else {
+      $sids[$uid] = 0;
+    }
+  }
+
+  return $sids[$uid];
+}
+
+/**
+ * Get the Session ID for a user. Utilizes the Session API module.
+ */
+function flag_get_sid($uid = NULL) {
+  return flag_set_sid($uid);
+}
Index: flag.install
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/flag/Attic/flag.install,v
retrieving revision 1.2.2.28
diff -u -r1.2.2.28 flag.install
--- flag.install	20 Feb 2009 21:56:40 -0000	1.2.2.28
+++ flag.install	23 Feb 2009 00:35:13 -0000
@@ -198,6 +198,12 @@
         'not null' => TRUE,
         'default' => 0,
       ),
+      'sid' => array(
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => 0,
+      ),
       'timestamp' => array(
         'type' => 'int',
         'unsigned' => TRUE,
@@ -208,11 +214,11 @@
     ),
     'primary key' => array('fcid'),
     'unique keys' => array(
-      'fid_content_type_content_id_uid' => array('fid', 'content_type', 'content_id', 'uid'),
+      'fid_content_type_content_id_uid_sid' => array('fid', 'content_type', 'content_id', 'uid', 'sid'),
     ),
     'indexes' => array(
       'content_type_content_id' => array('content_type', 'content_id'),
-      'content_type_uid' => array('content_type', 'uid'),
+      'content_type_uid_sid' => array('content_type', 'uid', 'sid'),
     ),
   );
 
@@ -429,6 +435,27 @@
   return $ret;
 }
 
+/**
+ * Add the sid column and unique index on the flag_content table.
+ */
+function flag_update_6004() {
+  $ret = array();
+
+  // Drop the keys affected by the addition of the SID column.
+  db_drop_unique_key($ret, 'flag_content', 'fid_content_type_content_id_uid');
+  db_drop_index($ret, 'flag_content', 'content_type_uid');
+
+  // Add the column.
+  db_add_field($ret, 'flag_content', 'sid', array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0));
+
+  // Re-add the removed keys.
+  db_add_unique_key($ret, 'flag_content', 'fid_content_type_content_id_uid_sid', array('fid', 'content_type', 'content_id', 'uid', 'sid'));
+  db_add_index($ret, 'flag_content', 'content_type_uid_sid', array('content_type', 'uid', 'sid'));
+
+  return $ret;
+}
+
+
 // This is a replacement for update_sql(). The latter doesn't support placeholders.
 function _flag_update_sql($sql) {
   $args = func_get_args();
Index: flag.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/flag/Attic/flag.inc,v
retrieving revision 1.1.2.28
diff -u -r1.1.2.28 flag.inc
--- flag.inc	15 Feb 2009 21:14:21 -0000	1.1.2.28
+++ flag.inc	23 Feb 2009 00:35:13 -0000
@@ -344,6 +344,9 @@
     if (!isset($account)) {
       $account = $GLOBALS['user'];
     }
+    if ($account->uid == 0 && !module_exists('session_api')) {
+      return FALSE;
+    }
     $matched_roles = array_intersect($this->roles, array_keys($account->roles));
     return !empty($matched_roles) || empty($this->roles) || $account->uid == 1;
   }
@@ -371,15 +374,6 @@
       return FALSE;
     }
 
-    if (!$account->uid) {
-      // Anonymous users can't flag with this system. For now.
-      //
-      // @todo This is legacy code. $flag->user_access() should handle this.
-      // This will also make it posible to have flags that do support anonymous
-      // users.
-      return FALSE;
-    }
-
     if (!$skip_permission_check && !$this->user_access($account)) {
       // User has no permission to use this flag.
       return FALSE;
@@ -396,14 +390,15 @@
 
     // Perform the flagging or unflagging of this flag.
     $uid = $this->global ? 0 : $account->uid;
-    $flagged = $this->_is_flagged($content_id, $uid);
+    $sid = $this->global ? 0 : flag_get_sid($uid);
+    $flagged = $this->_is_flagged($content_id, $uid, $sid);
     if ($action == 'unflag' && $flagged) {
-      $this->_unflag($content_id, $uid);
+      $this->_unflag($content_id, $uid, $sid);
       // Let other modules perform actions.
       module_invoke_all('flag', 'unflag', $this, $content_id, $account);
     }
     elseif ($action == 'flag' && !$flagged) {
-      $this->_flag($content_id, $uid);
+      $this->_flag($content_id, $uid, $sid);
       // Let other modules perform actions.
       module_invoke_all('flag', 'flag', $this, $content_id, $account);
     }
@@ -421,10 +416,12 @@
    *   Optional. The user ID whose flags we're checking. If none given, the
    *   current user will be used.
    */
-  function is_flagged($content_id, $uid = NULL) {
-    $uid = !isset($uid) ? $GLOBALS['user']->uid : $uid;
+  function is_flagged($content_id, $uid = NULL, $sid = NULL) {
+    $uid = $this->global ? 0 : (!isset($uid) ? $GLOBALS['user']->uid : $uid);
+    $sid = $this->global ? 0 : (!isset($sid) ? flag_get_sid($uid) : $sid);
+
     // flag_get_user_flags() does caching.
-    $user_flags = flag_get_user_flags($this->content_type, $content_id, $uid);
+    $user_flags = flag_get_user_flags($this->content_type, $content_id, $uid, $sid);
     return isset($user_flags[$this->name]);
   }
 
@@ -440,8 +437,8 @@
    *
    * @private
    */
-  function _is_flagged($content_id, $uid) {
-    return db_result(db_query("SELECT fid FROM {flag_content} WHERE fid = %d AND uid = %d AND content_id = %d", $this->fid, $uid, $content_id));
+  function _is_flagged($content_id, $uid, $sid) { 
+    return db_result(db_query("SELECT fid FROM {flag_content} WHERE fid = %d AND uid = %d AND sid = %d AND content_id = %d", $this->fid, $uid, $sid, $content_id));
   }
 
   /**
@@ -452,8 +449,8 @@
    *
    * @private
    */
-  function _flag($content_id, $uid) {
-    db_query("INSERT INTO {flag_content} (fid, content_type, content_id, uid, timestamp) VALUES (%d, '%s', %d, %d, %d)", $this->fid, $this->content_type, $content_id, $uid, time());
+  function _flag($content_id, $uid, $sid) {
+    db_query("INSERT INTO {flag_content} (fid, content_type, content_id, uid, sid, timestamp) VALUES (%d, '%s', %d, %d, %d, %d)", $this->fid, $this->content_type, $content_id, $uid, $sid, time());
     $this->_update_count($content_id);
   }
 
@@ -465,8 +462,8 @@
    *
    * @private
    */
-  function _unflag($content_id, $uid) {
-    db_query("DELETE FROM {flag_content} WHERE fid = %d AND uid = %d AND content_id = %d", $this->fid, $uid, $content_id);
+  function _unflag($content_id, $uid, $sid) {
+    db_query("DELETE FROM {flag_content} WHERE fid = %d AND uid = %d AND sid = %d AND content_id = %d", $this->fid, $uid, $sid, $content_id);
     $this->_update_count($content_id);
   }
 
@@ -497,10 +494,10 @@
   /**
    * Returns the number of items a user has flagged.
    *
-   * For global flags, pass '0' as the user ID.
+   * For global flags, pass '0' as the user ID and session ID.
    */
-  function get_user_count($uid) {
-    return db_result(db_query('SELECT COUNT(*) FROM {flag_content} WHERE fid = %d AND uid = %d', $this->fid, $uid));
+  function get_user_count($uid, $sid) {
+    return db_result(db_query('SELECT COUNT(*) FROM {flag_content} WHERE fid = %d AND uid = %d AND sid = %d', $this->fid, $uid, $sid));
   }
 
   /**
@@ -1153,4 +1150,3 @@
     ? url($path, NULL, $fragment, $absolute)
     : url($path, array('absolute' => TRUE, 'fragment' => $fragment));
 }
-
Index: includes/flag_handler_relationships.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/flag/includes/Attic/flag_handler_relationships.inc,v
retrieving revision 1.1.2.8
diff -u -r1.1.2.8 flag_handler_relationships.inc
--- includes/flag_handler_relationships.inc	3 Dec 2008 14:10:00 -0000	1.1.2.8
+++ includes/flag_handler_relationships.inc	23 Feb 2009 00:35:14 -0000
@@ -75,6 +75,11 @@
       'value' => $flag->fid,
       'numeric' => TRUE,
     );
+    $this->definition['extra'][] = array(
+      'field' => 'sid',
+      'value' => flag_get_sid(),
+      'numeric' => TRUE,
+    );
     if ($this->options['user_scope'] == 'current' && !$flag->global) {
       $this->definition['extra'][] = array(
         'field' => 'uid',
Index: includes/flag_handler_field_ops.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/flag/includes/Attic/flag_handler_field_ops.inc,v
retrieving revision 1.1.2.5
diff -u -r1.1.2.5 flag_handler_field_ops.inc
--- includes/flag_handler_field_ops.inc	3 Dec 2008 14:10:00 -0000	1.1.2.5
+++ includes/flag_handler_field_ops.inc	23 Feb 2009 00:35:14 -0000
@@ -81,6 +81,11 @@
         'value' => '***CURRENT_USER***',
         'numeric' => TRUE,
       );
+      $join->extra[] = array(
+        'field' => 'sid',
+        'value' => flag_get_sid(),
+        'numeric' => TRUE,
+      );
     }
     $flag_table = $this->query->add_table('flag_content', $parent, $join);
     $this->aliases['is_flagged'] = $this->query->add_field($flag_table, 'content_id');
