? .DS_Store
? token-in-core.kpf
? token-in-core.patch
? modules/.DS_Store
? sites/all/.DS_Store
? sites/all/modules/.DS_Store
? sites/all/modules/tokin
? sites/default/files
? sites/default/settings.php
Index: includes/common.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/common.inc,v
retrieving revision 1.931
diff -u -p -r1.931 common.inc
--- includes/common.inc	8 Jul 2009 20:40:21 -0000	1.931
+++ includes/common.inc	10 Jul 2009 21:42:00 -0000
@@ -4790,3 +4790,133 @@ function _drupal_flush_css_js() {
   }
   variable_set('css_js_query_string', $new_character . substr($string_history, 0, 19));
 }
+
+/**
+ * Find all tokens in a given string and replace them with appropriate values.
+ *
+ * @param $text
+ *   The text containing replacable tokens.
+ * @param $data
+ *   An array of keyed objects. For simple replacement scenarios 'node', 'user',
+ *   and others are common keys, with an accompanying node or user object being
+ *   the value. Some tokens types, like 'site', do not require any explicit
+ *   information from $data and can be replaced even if $data is empty.
+ * @returns
+ *   Text with tokens replaced.
+ */
+function token_replace($text, array $data = array(), $safe_for_html = TRUE) {
+  $token_list = token_scan($text);
+  $replacements = token_generate($token_list, $data);
+  
+  $tokens = array_keys($replacements);
+  $values = array_values($replacements);
+  
+  return str_replace($tokens, $values, $text);
+}
+
+/**
+ * Build a list of all token-like patterns that appear in the text.
+ *
+ * @param $text
+ *   The text to be scanned for possible tokens.
+ * @returns
+ *   An associative array of discovered tokens, grouped by type.
+ */
+function token_scan($text) {  
+  preg_match_all('/\[(.*?)\:(.*?)\]/', $text, $matches);
+
+  $tokens = array();
+  
+  $raw = $matches[0];
+  $type = $matches[1];
+  $token = $matches[2];
+
+  for ($i = 0; $i < count($raw); $i++) {
+    $tokens[$type[$i]][$token[$i]] = $raw[$i];
+  }
+  
+  return $tokens;
+}
+
+/**
+ * Generate repalcement values for a list of tokens.
+ *
+ * @param $raw_tokens
+ *   A keyed array of tokens, and their original raw form in the source text.
+ * @param $data
+ *   An array of keyed objects. For simple replacement scenarios 'node', 'user',
+ *   and others are common keys, with an accompanying node or user object being
+ *   the value. Some tokens types, like 'site', do not require any explicit
+ *   information from $data and can be replaced even if $data is empty.
+ * @returns
+ *   An associative array of discovered tokens, grouped by type.
+ */
+function token_generate(array $raw_tokens, array $data = array(), $safe_for_html = TRUE) {
+  $results = array();
+  foreach ($raw_tokens as $type => $tokens) {
+    foreach (module_invoke_all('tokens', $type, $tokens, $data) as $original => $replacement) {
+      $results[$original] = $replacement;
+    }
+  }
+  return $results;
+}
+
+/**
+ * Given a list of tokens, return those that begin with a specific prefix.
+ *
+ * @param $tokens
+ *   A keyed array of tokens, and their original raw form in the source text.
+ * @param $prefix
+ *   A textual string to be matched at the beginning of the token.
+ * @param $delimiter
+ *   An optional string containing the character that separates the prefix from
+ *   the rest of the token. Defaults to ':'.
+ * @returns
+ *   An associative array of discovered tokens, with the prefix and delimiter
+ *   stripped from the key.
+ */
+function token_match_prefix(array $tokens, $prefix, $delimiter = ':') {
+  $results = array();
+  foreach ($tokens as $token => $raw) {
+    $parts = split($delimiter, $token, 2);
+    if (count($parts) == 2 && $parts[0] == $prefix) {
+      $results[$parts[1]] = $raw;
+    }
+  }
+  return $results;
+}
+
+/**
+ * Returns metadata describing supported tokens.
+ *
+ * The metadata array contains token type, name, and description data as well as
+ * an optional pointer indicating that the token chains to another set of tokens.
+ * For example:
+ *
+ *   $data['types']['node'] = array(
+ *     'name' => t('Nodes'),
+ *     'description' => t('Tokens related to node objects.'),
+ *   );
+ *   $data['tokens']['node']['title'] = array(
+ *     'name' => t('Title'),
+ *     'description' => t('The title of the current node.'),
+ *   );
+ *   $data['tokens']['node']['author'] = array(
+ *     'name' => t('Author'),
+ *     'description' => t('The author of the current node.'),
+ *     'references' => 'user',
+ *   );
+ *
+ * @param $reset
+ *   Rebuild the internal cache of Token metadata. Defaults to FALSE.
+ * @returns
+ *   An associative array of token information, grouped by token type.
+ */
+function token_info($reset = FALSE) {
+  $data = &drupal_static(__FUNCTION__, array(), $reset);
+  if (empty($data)) {
+    $data = module_invoke_all('token_info');
+    drupal_alter('token_info', $data);
+  }
+  return $data;
+}
\ No newline at end of file
Index: modules/comment/comment.info
===================================================================
RCS file: /cvs/drupal/drupal/modules/comment/comment.info,v
retrieving revision 1.10
diff -u -p -r1.10 comment.info
--- modules/comment/comment.info	8 Jun 2009 09:23:51 -0000	1.10
+++ modules/comment/comment.info	10 Jul 2009 21:42:00 -0000
@@ -10,3 +10,4 @@ files[] = comment.admin.inc
 files[] = comment.pages.inc
 files[] = comment.install
 files[] = comment.test
+files[] = comment.tokens.inc
\ No newline at end of file
Index: modules/comment/comment.tokens.inc
===================================================================
RCS file: modules/comment/comment.tokens.inc
diff -N modules/comment/comment.tokens.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/comment/comment.tokens.inc	10 Jul 2009 21:42:00 -0000
@@ -0,0 +1,142 @@
+<?php
+// $Id: comment.tokens.inc,v 1.6 2009/07/09 06:08:09 eaton Exp $
+
+function comment_tokens($type, $tokens, $data, $safe_for_html = TRUE) {
+  $replacements = array();
+
+  if ($type == 'comment' && !empty($data['comment'])) {
+    $comment = $data['comment'];
+
+    foreach($tokens as $name => $original) {
+      if ($name == 'cid') $replacements[$original] = $comment->cid;
+      elseif ($name == 'nid') $replacements[$original] = $comment->nid;
+      elseif ($name == 'uid') $replacements[$original] = $comment->uid;
+      elseif ($name == 'pid') $replacements[$original] = $comment->pid;
+      elseif ($name == 'hostname') $replacements[$original] = check_plain($comment->hostname);
+      elseif ($name == 'name') $replacements[$original] = check_plain($comment->name);
+      elseif ($name == 'mail') $replacements[$original] = check_plain($comment->mail);
+      elseif ($name == 'homepage') $replacements[$original] = check_url($comment->homepage);
+      elseif ($name == 'title') $replacements[$original] = check_plain($comment->subject);
+      elseif ($name == 'body') {
+        if ($safe_for_html) $replacements[$original] = check_markup($comment->comment, $comment->format);
+        else $replacements[$original] = $comment->comment;
+      }
+      elseif ($name == 'url') $replacements[$original] = url('comment/' . $comment->cid, array('fragment' => 'comment-' . $comment->cid));
+      elseif ($name == 'edit-url') $replacements[$original] = url('comment/edit/' . $comment->cid);
+      
+      // These tokens are default variations on the chained tokens handled below.
+      elseif ($name == 'author') {
+        $replacements[$original] = check_plain($comment->name);
+      }
+      elseif (($name == 'parent') && $parent = comment_load($comment->pid)) {
+        $replacements[$original] = check_plain($parent->subject);
+      }
+      elseif ($name == 'created') $replacements[$original] = date_format($comment->timestamp);
+      elseif ($name == 'node') {
+        $node = node_load($comment->nid);
+        $replacements[$original] = check_plain($node->title);
+      }
+    }
+    
+    if ($node_tokens = token_match_prefix($tokens, 'node')) {
+      $node = node_load($comment->nid);
+      $replacements += module_invoke_all('tokens', 'node', $node_tokens, array('node' => $node));
+    }
+
+    if ($date_tokens = token_match_prefix($tokens, 'created')) {
+      $replacements += module_invoke_all('tokens', 'date', $date_tokens, array('date' => $comment->timestamp));
+    }
+
+    if (($parent_tokens = token_match_prefix($tokens, 'parent')) && $parent = comment_load($comment->pid)) {
+      $replacements += module_invoke_all('tokens', 'comment', $parent_tokens, array('comment' => $parent));
+    }
+
+    if (($author_tokens = token_match_prefix($tokens, 'author')) && $account = user_load($comment->uid)) {
+      $replacements += module_invoke_all('tokens', 'user', $author_tokens, array('user' => $account));
+    }
+  }
+  elseif ($type == 'node' & !empty($data['node'])) {
+    $node = $data['node'];
+
+    foreach($tokens as $name => $original) {
+      if ($name == 'comment-count') $replacements[$original] = $node->comment_count;
+    }
+  }
+
+  return $replacements;
+}
+
+function comment_token_info() {
+  $data = array();
+
+  // Metadata for token types.
+  $data['types']['comment']['name'] = t('Comments');
+  $data['types']['comment']['description'] = t('Tokens for comments posted on the site.');
+
+
+  // Comment-related tokens for nodes
+  $data['tokens']['node']['comment-count']['name'] = t('Comment count');
+  $data['tokens']['node']['comment-count']['description'] = t('The number of comments posted on a node.');
+
+
+  // Basic ids and foreign keys for comments
+  $data['tokens']['comment']['cid']['name'] = t('Comment ID');
+  $data['tokens']['comment']['cid']['description'] = t('The unique ID of the comment.');
+
+  $data['tokens']['comment']['pid']['name'] = t('Parent ID');
+  $data['tokens']['comment']['pid']['description'] = t("The unique ID of the comment's parent, if comment threading is active.");
+
+  $data['tokens']['comment']['nid']['name'] = t('Node ID');
+  $data['tokens']['comment']['nid']['description'] = t('The unique ID of the node the comment was posted to.');
+
+  $data['tokens']['comment']['uid']['name'] = t('User ID');
+  $data['tokens']['comment']['uid']['description'] = t('The unique ID of the user who posted the comment.');
+
+
+  // Poster identity information for comments
+  $data['tokens']['comment']['hostname']['name'] = t('IP Address');
+  $data['tokens']['comment']['hostname']['description'] = t('The IP address of the computer the comment was posted from.');
+
+  $data['tokens']['comment']['name']['name'] = t('Name');
+  $data['tokens']['comment']['name']['description'] = t("The name left by the comment author.");
+
+  $data['tokens']['comment']['mail']['name'] = t('Email address');
+  $data['tokens']['comment']['mail']['description'] = t("The email address left by the comment author.");
+
+  $data['tokens']['comment']['homepage']['name'] = t('Home page');
+  $data['tokens']['comment']['homepage']['description'] = t("The home page URL left by the comment author.");
+  
+  
+  // Content tokens for the comment
+  $data['tokens']['comment']['title']['name'] = t('Title');
+  $data['tokens']['comment']['title']['description'] = t('The title of the comment.');
+  
+  $data['tokens']['comment']['body']['name'] = t('Content');
+  $data['tokens']['comment']['body']['description'] = t('The formatted content of the comment itself.');
+
+  $data['tokens']['comment']['url']['name'] = t('URL');
+  $data['tokens']['comment']['url']['description'] = t('The URL of the comment.');
+
+  $data['tokens']['comment']['edit-url']['name'] = t('Edit URL');
+  $data['tokens']['comment']['edit-url']['description'] = t("The URL of the comment's edit page.");
+
+
+  // Chained tokens for comments
+  $data['tokens']['comment']['created']['name'] = t('Date created');
+  $data['tokens']['comment']['created']['description'] = t('The date the comment was posted.');
+  $data['tokens']['comment']['created']['references'] = 'date';
+
+  $data['tokens']['comment']['parent']['name'] = t('Parent');
+  $data['tokens']['comment']['parent']['description'] = t("The comment's parent, if comment threading is active.");
+  $data['tokens']['comment']['parent']['references'] = 'comment';
+
+  $data['tokens']['comment']['node']['name'] = t('Node');
+  $data['tokens']['comment']['node']['description'] = t('The node the comment was posted to.');
+  $data['tokens']['comment']['node']['references'] = 'node';
+
+  $data['tokens']['comment']['author']['name'] = t('Author');
+  $data['tokens']['comment']['author']['description'] = t('The author of the comment, if they were logged in.');
+  $data['tokens']['comment']['author']['references'] = 'user';
+
+  return $data;
+}
\ No newline at end of file
Index: modules/node/node.info
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.info,v
retrieving revision 1.11
diff -u -p -r1.11 node.info
--- modules/node/node.info	8 Jun 2009 09:23:53 -0000	1.11
+++ modules/node/node.info	10 Jul 2009 21:42:00 -0000
@@ -10,4 +10,5 @@ files[] = node.admin.inc
 files[] = node.pages.inc
 files[] = node.install
 files[] = node.test
+files[] = node.tokens.inc
 required = TRUE
Index: modules/node/node.tokens.inc
===================================================================
RCS file: modules/node/node.tokens.inc
diff -N modules/node/node.tokens.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/node/node.tokens.inc	10 Jul 2009 21:42:00 -0000
@@ -0,0 +1,103 @@
+<?php
+// $Id: node.tokens.inc,v 1.8 2009/07/09 06:08:09 eaton Exp $
+
+function node_tokens($type, $tokens, $data, $safe_for_html = TRUE) {
+  $replacements = array();
+
+  if ($type == 'node' && !empty($data['node'])) {
+    $node = $data['node'];
+
+    foreach($tokens as $name => $original) {
+      if ($name == 'nid') $replacements[$original] = $node->nid;
+      elseif ($name == 'vid') $replacements[$original] = $node->vid;
+      elseif ($name == 'tnid') $replacements[$original] = $node->tnid;
+      elseif ($name == 'uid') $replacements[$original] = $node->uid;
+      elseif ($name == 'name') $replacements[$original] = check_plain($node->name);
+      elseif ($name == 'title') $replacements[$original] = check_plain($node->title);
+      elseif ($name == 'type') $replacements[$original] = $node->type;
+      elseif ($name == 'type-name') $replacements[$original] = node_get_types('name', $node->type);
+      elseif ($name == 'language') $replacements[$original] = filter_xss_admin($node->language);
+      elseif ($name == 'url') $replacements[$original] = url('node/' . $node->nid);
+      elseif ($name == 'edit-url') $replacements[$original] = url('node/' . $node->nid . '/edit');
+      
+      // These tokens are default variations on the chained tokens handled below.
+      elseif ($name == 'author') $replacements[$original] = check_plain($node->name);
+      elseif ($name == 'created') $replacements[$original] = format_date($node->created);
+      elseif ($name == 'changed') $replacements[$original] = format_date($node->changed);
+    }
+    
+    if ($author_tokens = token_match_prefix($tokens, 'author')) {
+      $author = user_load($node->uid);
+      $replacements += module_invoke_all('tokens', 'user', $author_tokens, array('user' => $author));
+    }
+
+    if ($created_tokens = token_match_prefix($tokens, 'created')) {
+      $replacements += module_invoke_all('tokens', 'date', $created_tokens, array('date' => $node->created));
+    }
+
+    if ($changed_tokens = token_match_prefix($tokens, 'changed')) {
+      $replacements += module_invoke_all('tokens', 'date', $changed_tokens, array('date' => $node->changed));
+    }
+  }
+  
+  return $replacements;
+}
+
+
+function node_token_info() {
+  $data = array();
+  
+  // Metadata for token types.
+  $data['types']['node']['name'] = t('Nodes');
+  $data['types']['node']['description'] = t('Tokens related to individual nodes.');
+
+  // Basic ids, foreign keys, and metadata for nodes
+  $data['tokens']['node']['nid']['name'] = t('Node ID');
+  $data['tokens']['node']['nid']['description'] = t('The unique ID of the node.');
+
+  $data['tokens']['node']['vid']['name'] = t('Revision ID');
+  $data['tokens']['node']['vid']['description'] = t("The unique ID of the node's latest revision.");
+
+  $data['tokens']['node']['tnid']['name'] = t('Translation set ID');
+  $data['tokens']['node']['tnid']['description'] = t('The unique ID of the original-language version of this node, if one exists.');
+
+  $data['tokens']['node']['uid']['name'] = t('User ID');
+  $data['tokens']['node']['uid']['description'] = t('The unique ID of the user who posted the node.');
+  
+  $data['tokens']['node']['type']['name'] = t('Content type');
+  $data['tokens']['node']['type']['description'] = t('The type of the node.');
+
+  $data['tokens']['node']['type-name']['name'] = t('Content type name');
+  $data['tokens']['node']['type-name']['description'] = t('The human-readable name of the node type.');
+
+  
+  
+  // Content tokens for the node
+  $data['tokens']['node']['title']['name'] = t('Title');
+  $data['tokens']['node']['title']['description'] = t('The title of the node.');
+
+  $data['tokens']['node']['language']['name'] = t('Language');
+  $data['tokens']['node']['language']['description'] = t('The language the node is written in.');
+
+  $data['tokens']['node']['url']['name'] = t('URL');
+  $data['tokens']['node']['url']['description'] = t('The URL of the node.');
+
+  $data['tokens']['node']['edit-url']['name'] = t('Edit URL');
+  $data['tokens']['node']['edit-url']['description'] = t("The URL of the node's edit page.");
+
+
+  // Chained tokens for nodes
+  $data['tokens']['node']['created']['name'] = t('Date created');
+  $data['tokens']['node']['created']['description'] = t('The date the node was posted.');
+  $data['tokens']['node']['created']['references'] = 'date';
+
+  $data['tokens']['node']['changed']['name'] = t('Date changed');
+  $data['tokens']['node']['changed']['description'] = t('The date the node was most recently updated.');
+  $data['tokens']['node']['changed']['references'] = 'date';
+
+  $data['tokens']['node']['author']['name'] = t('Author');
+  $data['tokens']['node']['author']['description'] = t('The author of the node.');
+  $data['tokens']['node']['author']['references'] = 'user';
+
+  return $data;
+}
\ No newline at end of file
Index: modules/poll/poll.info
===================================================================
RCS file: /cvs/drupal/drupal/modules/poll/poll.info,v
retrieving revision 1.9
diff -u -p -r1.9 poll.info
--- modules/poll/poll.info	8 Jun 2009 09:23:53 -0000	1.9
+++ modules/poll/poll.info	10 Jul 2009 21:42:00 -0000
@@ -8,3 +8,4 @@ files[] = poll.module
 files[] = poll.pages.inc
 files[] = poll.install
 files[] = poll.test
+files[] = poll.tokens.inc
\ No newline at end of file
Index: modules/poll/poll.tokens.inc
===================================================================
RCS file: modules/poll/poll.tokens.inc
diff -N modules/poll/poll.tokens.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/poll/poll.tokens.inc	10 Jul 2009 21:42:00 -0000
@@ -0,0 +1,32 @@
+<?php
+// $Id: poll.tokens.inc,v 1.1 2009/07/07 22:17:35 eaton Exp $
+
+function poll_tokens($type, $tokens, $data, $safe_for_html = TRUE) {
+  $replacements = array();
+
+  if ($type == 'node' && !empty($data['node']) && $data['node']->type == 'poll') {
+    $node = $data['node'];
+
+    $total_votes = 0;
+    $highest_votes = 0;
+    foreach ($node->choice as $choice) {
+      if ($choice['chvotes'] > $highest_votes) {
+        $winner = $choice;
+        $highest_votes = $choice['chvotes'];
+      }
+      $total_votes = $total_votes + $choice['chvotes'];
+    }
+    foreach($tokens as $name => $original) {
+      if ($name == 'poll-votes') $replacements[$original] = $total_votes;
+      elseif ($name == 'poll-winner' && isset($winner)) $replacements[$original] = check_plain($winner['chtext']);
+      elseif ($name == 'poll-winner-votes' && isset($winner)) $replacements[$original] = $winner['chvotes'];
+      elseif ($name == 'poll-winner-percent' && isset($winner)) {
+        $percent = ($winner['chvotes'] / $total_votes) * 100;
+        $replacements[$original] = number_format($percent, 0);
+      }
+      elseif ($name == 'poll-duration') $replacements[$original] = format_interval($node->runtime, 1);
+    }
+  }
+
+  return $replacements;
+}
\ No newline at end of file
Index: modules/statistics/statistics.info
===================================================================
RCS file: /cvs/drupal/drupal/modules/statistics/statistics.info,v
retrieving revision 1.9
diff -u -p -r1.9 statistics.info
--- modules/statistics/statistics.info	8 Jun 2009 09:23:54 -0000	1.9
+++ modules/statistics/statistics.info	10 Jul 2009 21:42:00 -0000
@@ -9,3 +9,4 @@ files[] = statistics.admin.inc
 files[] = statistics.pages.inc
 files[] = statistics.install
 files[] = statistics.test
+files[] = statistics.tokens.inc
\ No newline at end of file
Index: modules/statistics/statistics.tokens.inc
===================================================================
RCS file: modules/statistics/statistics.tokens.inc
diff -N modules/statistics/statistics.tokens.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/statistics/statistics.tokens.inc	10 Jul 2009 21:42:00 -0000
@@ -0,0 +1,31 @@
+<?php
+// $Id: statistics.tokens.inc,v 1.3 2009/07/09 06:08:09 eaton Exp $
+
+// statistics_count_content_views
+
+function statistics_tokens($type, $tokens, $data, $safe_for_html = TRUE) {
+  $replacements = array();
+
+  if ($type == 'node' & !empty($data['node'])) {
+    $node = $data['node'];
+
+    foreach($tokens as $name => $original) {
+      if ($name == 'views') {
+        $statistics = statistics_get($node->nid);
+        $replacements[$original] = $statistics['totalviews'];
+      }
+    }
+  }
+
+  return $replacements;
+}
+
+
+function statistics_token_info() {
+  $data = array();
+
+  $data['tokens']['node']['views']['name'] = t('Number of views');
+  $data['tokens']['node']['views']['description'] = t('The number of visitors who have read the node.');
+
+  return $data;
+}
\ No newline at end of file
Index: modules/system/system.info
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.info,v
retrieving revision 1.14
diff -u -p -r1.14 system.info
--- modules/system/system.info	17 Jun 2009 10:46:49 -0000	1.14
+++ modules/system/system.info	10 Jul 2009 21:42:00 -0000
@@ -11,4 +11,5 @@ files[] = image.gd.inc
 files[] = system.install
 files[] = system.test
 files[] = system.tar.inc
+files[] = system.tokens.inc
 required = TRUE
Index: modules/system/system.tokens.inc
===================================================================
RCS file: modules/system/system.tokens.inc
diff -N modules/system/system.tokens.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/system/system.tokens.inc	10 Jul 2009 21:42:00 -0000
@@ -0,0 +1,176 @@
+<?php
+// $Id: system.tokens.inc,v 1.6 2009/07/09 06:08:09 eaton Exp $
+
+function system_tokens($type, $tokens, $data, $safe_for_html = TRUE) {
+  $replacements = array();
+  
+  if ($type == 'site') {
+    foreach($tokens as $name => $original) {
+      if ($name == 'name') $replacements[$original] = variable_get('site_name');
+      elseif ($name == 'slogan') $replacements[$original] = variable_get('site_slogan');
+      elseif ($name == 'mission') $replacements[$original] = variable_get('mission_statement');
+      elseif ($name == 'mail') $replacements[$original] = variable_get('site_mail');
+      elseif ($name == 'url') $replacements[$original] = url('front');
+      elseif ($name == 'login-url') $replacements[$original] = url('user');
+    }
+  }
+  
+  elseif ($type == 'date') {
+    if (empty($data['date'])) {
+      $date = REQUEST_TIME;
+    } else {
+      $date = $data['date'];
+    }
+
+    foreach($tokens as $name => $original) {
+      if ($name == 'small') $replacements[$original] = format_date($date, 'small');
+      elseif ($name == 'medium') $replacements[$original] = format_date($date, 'medium');
+      elseif ($name == 'large') $replacements[$original] = format_date($date, 'large');
+      elseif ($name == 'since') $replacements[$original] = format_interval((REQUEST_TIME - $date), 2);
+      elseif ($name == 'raw') $replacements[$original] = check_plain($date);
+    }
+
+    if ($created_tokens = token_match_prefix($tokens, 'custom')) {
+      foreach($created_tokens as $name => $original) {
+        $replacements[$original] = format_date($date, 'custom', $name);
+      }
+    }
+  }
+
+  elseif ($type == 'file' && !empty($data['file'])) {
+    $file = $data['file'];
+
+    foreach($tokens as $name => $original) {
+      if ($name == 'fid') $replacements[$original] = $file->fid;
+      elseif ($name == 'uid') $replacements[$original] = $file->uid;
+      elseif ($name == 'nid') $replacements[$original] = $file->nid;
+      elseif ($name == 'name') $replacements[$original] = check_plain($file->filename);
+      elseif ($name == 'description') $replacements[$original] = check_plain($file->description);
+      elseif ($name == 'path') $replacements[$original] = check_plain($file->filepath);
+      elseif ($name == 'mime') $replacements[$original] = check_plain($file->filemime);
+      elseif ($name == 'size') $replacements[$original] = format_size($file->filesize);
+      elseif ($name == 'url') $replacements[$original] = file_create_url($file->filepath);
+      
+      // These tokens are default variations on the chained tokens handled below.
+      elseif ($name == 'node') $replacements[$original] = $file->filepath;
+      elseif ($name == 'timestamp') $replacements[$original] = $file->filepath;
+      elseif ($name == 'owner') $replacements[$original] = $file->filepath;
+    }
+
+    if ($node_tokens = token_match_prefix($tokens, 'node')) {
+      $node = node_load($file->nid);
+      $replacements += module_invoke_all('tokens', 'node', $node_tokens, array('node' => $node));
+    }
+
+    if ($date_tokens = token_match_prefix($tokens, 'timestamp')) {
+      $replacements += module_invoke_all('tokens', 'date', $date_tokens, array('date' => $file->timestamp));
+    }
+
+    if (($owner_tokens = token_match_prefix($tokens, 'owner')) && $account = user_load($file->uid)) {
+      $replacements += module_invoke_all('tokens', 'user', $owner_tokens, array('user' => $account));
+    }
+  }
+
+  return $replacements;
+}
+
+
+
+function system_token_info() {
+  $data = array();
+
+  // Metadata for token types.
+  $data['types']['site']['name'] = t('Site information');
+  $data['types']['site']['description'] = t('Tokens for site-wide settings and other global information.');
+
+  $data['types']['date']['name'] = t('Dates');
+  $data['types']['date']['description'] = t('Tokens related to times and dates.');
+
+  $data['types']['file']['name'] = t('Files');
+  $data['types']['file']['description'] = t('Tokens related to uploaded files.');
+
+
+  // Sitewide variables and metadata.
+  $data['tokens']['site']['name']['name'] = t("Name");
+  $data['tokens']['site']['name']['description'] = t("The name of the site.");
+
+  $data['tokens']['site']['slogan']['name'] = t("Slogan");
+  $data['tokens']['site']['slogan']['description'] = t("The slogan of the site.");
+
+  $data['tokens']['site']['mission']['name'] = t("Mission");
+  $data['tokens']['site']['mission']['description'] = t("The optional 'mission' of the site.");
+
+  $data['tokens']['site']['mail']['name'] = t("Email");
+  $data['tokens']['site']['mail']['description'] = t("The administrative email address for the site.");
+
+  $data['tokens']['site']['url']['name'] = t("URL");
+  $data['tokens']['site']['url']['description'] = t("The URL of the site's front page.");
+
+  $data['tokens']['site']['login-url']['name'] = t("Login page");
+  $data['tokens']['site']['login-url']['description'] = t("The URL of the site's login page.");
+  
+
+  // Date formatting tokens.
+  $data['tokens']['date']['small']['name'] = t("Small format");
+  $data['tokens']['date']['small']['description'] = t("A date in 'small' format. (%date)", array('%date' => format_date(REQUEST_TIME, 'small')));
+
+  $data['tokens']['date']['medium']['name'] = t("Medium format");
+  $data['tokens']['date']['medium']['description'] = t("A date in 'medium' format. (%date)", array('%date' => format_date(REQUEST_TIME, 'medium')));
+
+  $data['tokens']['date']['large']['name'] = t("Large format");
+  $data['tokens']['date']['large']['description'] = t("A date in 'large' format. (%date)", array('%date' => format_date(REQUEST_TIME, 'large')));
+
+  $data['tokens']['date']['custom']['name'] = t("Custom format");
+  $data['tokens']['date']['custom']['description'] = t("A date in a custom format. See !php-date for details.", array('!php-date' => l(t('the PHP documentation'), 'http://php.net/manual/en/function.date.php')));
+
+  $data['tokens']['date']['since']['name'] = t("Time-since");
+  $data['tokens']['date']['since']['description'] = t("A data in 'time-since' format. (%date)", array('%date' => format_interval(REQUEST_TIME - 360, 2)));
+
+  $data['tokens']['date']['raw']['name'] = t("Raw timestamp");
+  $data['tokens']['date']['raw']['description'] = t("A date in UNIX timestamp format (%date)", array('%date' => REQUEST_TIME));
+
+
+  // File related tokens.
+  $data['tokens']['file']['fid']['name'] = t("File ID");
+  $data['tokens']['file']['fid']['description'] = t("The unique ID of the uploaded file.");
+  
+  $data['tokens']['file']['uid']['name'] = t("User ID");
+  $data['tokens']['file']['uid']['description'] = t("The unique ID of the user who owns the file.");
+
+  $data['tokens']['file']['nid']['name'] = t("Node ID");
+  $data['tokens']['file']['nid']['description'] = t("The unique ID of the node the file is attached to.");
+  
+  $data['tokens']['file']['name']['name'] = t("File name");
+  $data['tokens']['file']['name']['description'] = t("The name of the file on disk.");
+
+  $data['tokens']['file']['description']['name'] = t("Description");
+  $data['tokens']['file']['description']['description'] = t("An optional human-readable description of the file.");
+  
+  $data['tokens']['file']['path']['name'] = t("Path");
+  $data['tokens']['file']['path']['description'] = t("The location of the file on disk.");
+  
+  $data['tokens']['file']['mime']['name'] = t("MIME type");
+  $data['tokens']['file']['mime']['description'] = t("The MIME type of the file.");
+  
+  $data['tokens']['file']['size']['name'] = t("File size");
+  $data['tokens']['file']['size']['description'] = t("The size of the file, in kilobytes.");
+
+  $data['tokens']['file']['path']['name'] = t("URL");
+  $data['tokens']['file']['path']['description'] = t("The web-accessible URL for the file.");
+
+
+  // Chained tokens for files
+  $data['tokens']['file']['timestamp']['name'] = t('Timestamp');
+  $data['tokens']['file']['timestamp']['description'] = t('The date the file was most recently changed.');
+  $data['tokens']['file']['timestamp']['references'] = 'date';
+
+  $data['tokens']['file']['node']['name'] = t('Node');
+  $data['tokens']['file']['node']['description'] = t('The node the file is attached to.');
+  $data['tokens']['file']['node']['references'] = 'date';
+
+  $data['tokens']['file']['owner']['name'] = t('Owner');
+  $data['tokens']['file']['owner']['description'] = t('The user who originally uploaded the file.');
+  $data['tokens']['file']['owner']['references'] = 'user';
+
+  return $data;
+}
\ No newline at end of file
Index: modules/taxonomy/taxonomy.info
===================================================================
RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.info,v
retrieving revision 1.9
diff -u -p -r1.9 taxonomy.info
--- modules/taxonomy/taxonomy.info	8 Jun 2009 09:23:54 -0000	1.9
+++ modules/taxonomy/taxonomy.info	10 Jul 2009 21:42:00 -0000
@@ -9,3 +9,4 @@ files[] = taxonomy.admin.inc
 files[] = taxonomy.pages.inc
 files[] = taxonomy.install
 files[] = taxonomy.test
+files[] = taxonomy.tokens.inc
\ No newline at end of file
Index: modules/taxonomy/taxonomy.tokens.inc
===================================================================
RCS file: modules/taxonomy/taxonomy.tokens.inc
diff -N modules/taxonomy/taxonomy.tokens.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/taxonomy/taxonomy.tokens.inc	10 Jul 2009 21:42:00 -0000
@@ -0,0 +1,107 @@
+<?php
+// $Id: taxonomy.tokens.inc,v 1.5 2009/07/09 06:08:09 eaton Exp $
+
+function taxonomy_tokens($type, $tokens, $data, $safe_for_html = TRUE) {
+  $replacements = array();
+
+  if ($type == 'term' && !empty($data['term'])) {
+    $term = $data['term'];
+
+    foreach($tokens as $name => $original) {
+      if ($name == 'tid') $replacements[$original] = $term->tid;
+      elseif ($name == 'vid') $replacements[$original] = $term->vid;
+      elseif ($name == 'name') $replacements[$original] = check_plain($term->name);
+      elseif ($name == 'description') $replacements[$original] = check_plain($term->description);
+      elseif ($name == 'node-count') {
+        $sql = "SELECT COUNT (1) FROM {taxonomy_term_node} tn WHERE tn.tid = :tid";
+        $count = db_result(db_query($sql, array(':tid' => $term->tid)));
+        $replacements[$original] = check_plain($count);
+      }
+      elseif ($name == 'vocabulary') {
+        $vocabulary = taxonomy_vocabulary_load($term->vid);
+        $replacements[$original] = check_plain($vocabulary->name);
+      }
+    }
+    
+    if ($vocabulary_tokens = token_match_prefix($tokens, 'vocabulary')) {
+      $vocabulary = taxonomy_vocabulary_load($term->vid);
+      $replacements += module_invoke_all('tokens', 'vocabulary', $vocabulary_tokens, array('vocabulary' => $vocabulary));
+    }
+  }
+
+  elseif ($type == 'vocabulary' && !empty($data['vocabulary'])) {
+    $vocabulary = $data['vocabulary'];
+
+    foreach($tokens as $name => $original) {
+      if ($name == 'vid') $replacements[$original] = $vocabulary->vid;
+      elseif ($name == 'name') $replacements[$original] = check_plain($vocabulary->name);
+      elseif ($name == 'description') $replacements[$original] = check_plain($vocabulary->description);
+      elseif ($name == 'term-count') {
+        $sql = "SELECT COUNT (1) FROM {taxonomy_term_data} td WHERE td.vid = :vid";
+        $count = db_result(db_query($sql, array(':vid' => $vocabulary->vid)));
+        $replacements[$original] = check_plain($count);
+      }
+      elseif ($name == 'node-count') {
+        $sql = "SELECT COUNT (1) FROM {taxonomy_term_node} tn LEFT JOIN {taxonomy_term_data} td ON tn.tid = td.tid WHERE td.vid = :vid";
+        $count = db_result(db_query($sql, array(':vid' => $vocabulary->vid)));
+        $replacements[$original] = check_plain($count);
+      }
+    }
+  }
+
+  return $replacements;
+}
+
+
+function taxonomy_token_info() {
+  $data = array();
+
+  // Metadata for token types.
+  $data['types']['term']['name'] = t('Taxonomy terms');
+  $data['types']['term']['description'] = t('Tokens related to taxonomy terms.');
+
+  $data['types']['vocabulary']['name'] = t('Vocabularies');
+  $data['types']['vocabulary']['description'] = t('Tokens related to taxonomy vocabularies.');
+
+
+  // Taxonomy term related variables.
+  $data['tokens']['term']['tid']['name'] = t("Term ID");
+  $data['tokens']['term']['tid']['description'] = t("The unique ID of the taxonomy term.");
+
+  $data['tokens']['term']['vid']['name'] = t("Vocabulary ID");
+  $data['tokens']['term']['vid']['description'] = t("The unique ID of the vocabulary the term belongs to.");
+
+  $data['tokens']['term']['name']['name'] = t("Name");
+  $data['tokens']['term']['name']['description'] = t("The name of the taxonomy term.");
+
+  $data['tokens']['term']['description']['name'] = t("Description");
+  $data['tokens']['term']['description']['description'] = t("The optional description of the taxonomy term.");
+
+  $data['tokens']['term']['node-count']['name'] = t("Node count");
+  $data['tokens']['term']['node-count']['description'] = t("The number of nodes tagged with the taxonomy term.");
+
+
+  // Taxonomy vocabulary related variables.
+  $data['tokens']['vocabulary']['vid']['name'] = t("Vocabulary ID");
+  $data['tokens']['vocabulary']['vid']['description'] = t("The unique ID of the taxonomy vocabulary.");
+
+  $data['tokens']['vocabulary']['name']['name'] = t("Name");
+  $data['tokens']['vocabulary']['name']['description'] = t("The name of the taxonomy vocabulary.");
+
+  $data['tokens']['vocabulary']['description']['name'] = t("Description");
+  $data['tokens']['vocabulary']['description']['description'] = t("The optional description of the taxonomy vocabulary.");
+
+  $data['tokens']['vocabulary']['node-count']['name'] = t("Node count");
+  $data['tokens']['vocabulary']['node-count']['description'] = t("The number of nodes tagged with terms belonging to the taxonomy vocabulary.");
+
+  $data['tokens']['vocabulary']['term-count']['name'] = t("Node count");
+  $data['tokens']['vocabulary']['term-count']['description'] = t("The number of terms belonging to the taxonomy vocabulary.");
+
+
+  // Chained tokens for taxonomies
+  $data['tokens']['term']['vocabulary']['name'] = t('Vocabulary');
+  $data['tokens']['term']['vocabulary']['description'] = t('The vocabulary the taxonomy term belongs to.');
+  $data['tokens']['term']['vocabulary']['references'] = 'vocabulary';
+
+  return $data;
+}
\ No newline at end of file
Index: modules/upload/upload.info
===================================================================
RCS file: /cvs/drupal/drupal/modules/upload/upload.info,v
retrieving revision 1.9
diff -u -p -r1.9 upload.info
--- modules/upload/upload.info	8 Jun 2009 09:23:54 -0000	1.9
+++ modules/upload/upload.info	10 Jul 2009 21:42:00 -0000
@@ -8,3 +8,4 @@ files[] = upload.module
 files[] = upload.admin.inc
 files[] = upload.install
 files[] = upload.test
+files[] = upload.tokens.inc
\ No newline at end of file
Index: modules/upload/upload.tokens.inc
===================================================================
RCS file: modules/upload/upload.tokens.inc
diff -N modules/upload/upload.tokens.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/upload/upload.tokens.inc	10 Jul 2009 21:42:00 -0000
@@ -0,0 +1,34 @@
+<?php
+// $Id$
+
+function upload_tokens($type, $tokens, $data, $safe_for_html = TRUE) {
+  $replacements = array();
+
+  if ($type == 'node' && !empty($data['node'])) {
+    $node = $data['node'];
+    
+    foreach($tokens as $name => $original) {
+      if ($name == 'upload') {
+        $upload = array_shift($node->files);
+        $replacements[$original] = file_create_url($upload->filepath);
+      }
+    }
+
+    if (($upload_tokens = token_match_prefix($tokens, 'upload')) && !empty($node->files) && $upload = array_shift($node->files)) {
+      $replacements += module_invoke_all('tokens', 'file', $upload_tokens, array('file' => $upload));
+    }
+  }
+
+  return $replacements;
+}
+
+function upload_token_info() {
+  $data = array();
+
+  // Upload-related chained tokens for nodes
+  $data['tokens']['node']['upload']['name'] = t('File attachment');
+  $data['tokens']['node']['upload']['description'] = t('The first file attached to a node, if one exists.');
+  $data['tokens']['ndoe']['upload']['references'] = 'file';
+
+  return $data;
+}
\ No newline at end of file
Index: modules/user/user.info
===================================================================
RCS file: /cvs/drupal/drupal/modules/user/user.info,v
retrieving revision 1.11
diff -u -p -r1.11 user.info
--- modules/user/user.info	8 Jun 2009 09:23:55 -0000	1.11
+++ modules/user/user.info	10 Jul 2009 21:42:00 -0000
@@ -9,4 +9,5 @@ files[] = user.admin.inc
 files[] = user.pages.inc
 files[] = user.install
 files[] = user.test
+files[] = user.tokens.inc
 required = TRUE
Index: modules/user/user.tokens.inc
===================================================================
RCS file: modules/user/user.tokens.inc
diff -N modules/user/user.tokens.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/user/user.tokens.inc	10 Jul 2009 21:42:00 -0000
@@ -0,0 +1,76 @@
+<?php
+// $Id: user.tokens.inc,v 1.6 2009/07/09 06:08:09 eaton Exp $
+
+function user_tokens($type, $tokens, $data, $safe_for_html = TRUE) {
+  global $user;
+
+  $replacements = array();
+
+  if ($type == 'user') {
+    if (!empty($data['user'])) {
+      $account = $data['user'];
+    } else {
+      $account = $user;
+    }
+
+    foreach($tokens as $name => $original) {
+      if ($name == 'uid') $replacements[$original] = $account->uid;
+      elseif ($name == 'name') $replacements[$original] = check_plain($account->name);
+      elseif ($name == 'mail') $replacements[$original] = check_plain($account->mail);
+      elseif ($name == 'url') $replacements[$original] = url("user/$account->uid");
+      elseif ($name == 'edit-url') $replacements[$original] = url("user/$account->uid/edit");
+
+      // These tokens are default variations on the chained tokens handled below.
+      elseif ($name == 'last-login') $replacements[$original] = format_date($account->login);
+      elseif ($name == 'created') $replacements[$original] = format_date($account->created);
+    }
+    
+    if ($login_tokens = token_match_prefix($tokens, 'last-login')) {
+      $replacements += module_invoke_all('tokens', 'date', $login_tokens, array('date' => $account->login));
+    }
+
+    if ($registered_tokens = token_match_prefix($tokens, 'created')) {
+      $replacements += module_invoke_all('tokens', 'date', $registered_tokens, array('date' => $account->created));
+    }
+  }
+  
+  return $replacements;
+}
+
+
+function user_token_info() {
+  $data = array();
+
+  // Metadata for token types.
+  $data['types']['user']['name'] = t('Users');
+  $data['types']['user']['description'] = t('Tokens related to individual user accounts.');
+
+  // Basic data for users
+  $data['tokens']['user']['uid']['name'] = t('User ID');
+  $data['tokens']['user']['uid']['description'] = t('The unique ID of the user account.');
+
+  $data['tokens']['user']['name']['name'] = t('Name');
+  $data['tokens']['user']['name']['description'] = t("The login name of the user account.");
+
+  $data['tokens']['user']['mail']['name'] = t('Email');
+  $data['tokens']['user']['mail']['description'] = t('The email address of the user account.');
+
+  $data['tokens']['user']['url']['name'] = t('URL');
+  $data['tokens']['user']['url']['description'] = t('The url of the account profile page.');
+
+  $data['tokens']['user']['edit-url']['name'] = t('Edit URL');
+  $data['tokens']['user']['edit-url']['description'] = t('The url of the account edit page.');
+
+
+  // Chained tokens for users
+  $data['tokens']['user']['last-login']['name'] = t('Last login');
+  $data['tokens']['user']['last-login']['description'] = t('The date the user last logged in to the site.');
+  $data['tokens']['user']['last-login']['references'] = 'date';
+
+  $data['tokens']['user']['created']['name'] = t('Created');
+  $data['tokens']['user']['created']['description'] = t('The date the user account was created.');
+  $data['tokens']['user']['created']['references'] = 'date';
+
+
+  return $data;
+}
\ No newline at end of file
? sites/all/modules/token/.DS_Store
