Index: INSTALL.txt
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/project_issue/INSTALL.txt,v
retrieving revision 1.6
diff -u -p -r1.6 INSTALL.txt
--- INSTALL.txt	2 Nov 2007 01:47:16 -0000	1.6
+++ INSTALL.txt	12 Dec 2007 19:25:24 -0000
@@ -24,6 +24,12 @@ New Installation
 
 8. Grant the proper access to users under admin/user/access
 
+9. Enable the project issue to link filter in proper input formats at 
+   admin/settings/filters. If not all issues are public and cache is 
+   enabled, users may be able to see cached titles of project issues 
+   they should not have access to - in case of such conflict it is 
+   advised to disable the filter.
+
 
 --------------------------------------------------------------
 Upgrading
Index: README.txt
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/project_issue/README.txt,v
retrieving revision 1.3
diff -u -p -r1.3 README.txt
--- README.txt	7 Aug 2007 20:02:27 -0000	1.3
+++ README.txt	12 Dec 2007 19:25:24 -0000
@@ -1,6 +1,10 @@
 This module allows teams to track outstanding items which need
 resolution. It provides e-mail notifications to members about updates
 to items.  Similar to many issue tracking systems.
+The filter which automatically turns references to project issues into
+links conflicts with some access settings when cache is enabled. Users
+may be able to see cached titles of project issues they should not have
+access to - in case of such conflict it is advised not to enable the filter.
 
 For installation instructions, see INSTALL.txt.
 
Index: project_issue.css
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/project_issue/project_issue.css,v
retrieving revision 1.17
diff -u -p -r1.17 project_issue.css
--- project_issue.css	14 Nov 2007 05:57:42 -0000	1.17
+++ project_issue.css	12 Dec 2007 19:25:24 -0000
@@ -156,3 +156,12 @@ table.projects .project-project-links {
   text-align: right;
   color: #999;
 }
+
+/* Automatic issue links */
+.project-issue-status-2,
+.project-issue-status-3,
+.project-issue-status-5,
+.project-issue-status-6,
+.project-issue-status-7 {
+  text-decoration: line-through;
+}
Index: project_issue.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/project_issue/project_issue.module,v
retrieving revision 1.74
diff -u -p -r1.74 project_issue.module
--- project_issue.module	9 Dec 2007 03:17:19 -0000	1.74
+++ project_issue.module	12 Dec 2007 19:25:27 -0000
@@ -970,3 +970,144 @@ function project_issue_link_alter(&$node
     unset($links['comment_add']);
   }
 }
+
+
+/**
+ * @defgroup project_issue_filter Project Issue number to link filter
+ */
+
+/**
+ * Theme automatic Project Issue links
+ * @ingroup project_issue_filter
+ */
+function theme_project_issue_issue_link($node, $comment_id=0) {
+  if ($node->type == 'project_issue') {
+    $title = check_plain("#$node->nid: $node->title");
+    $path = "node/$node->nid";
+    $attributes = array('title' => project_issue_state($node->sid));
+    $fragment = null;
+    if($comment_id > 0) {
+      $title = check_plain("#$node->nid#comment-$comment_id: $node->title");
+      $fragment = "comment-$comment_id";
+    }
+    $output = "<span class=project-issue-status-$node->sid>";
+    $output .= l($title, $path, $attributes, null, $fragment);
+    $output .= '</span>';
+  }
+  else {
+    $output = "[#$node->nid]";
+  }
+  return $output;
+}
+
+/**
+ * Implementation of hook_form_filter_tips()
+ * @ingroup project_issue_filter
+ */
+function project_issue_filter_tips($delta, $format, $long = FALSE) {
+  if ($long) {
+    return t('References to project issues (in the form of [#1234] or [#1234#comment-1]) turn into links automatically, with the title of the issue appended. Statuses are shown on hover, issues with certain statuses are crossed out.');
+  }
+  else {
+    return t('Project issue numbers (ex. [#12345]) turn into links automatically.');
+  }
+}
+
+/**
+ * Implementation of hook_form_filter()
+ * @ingroup project_issue_filter
+ */
+function project_issue_filter($op, $delta = 0, $format = -1, $text = '') {
+  switch ($op) {
+    case 'list':
+      return array(0 => t('Project Issue to link filter'));
+    case 'description':
+      return t('Converts references to project issues (in the form of [#12345]) into links. Caching should be disabled if node access control modules are used.');
+    case 'no cache':
+      return FALSE;
+    case 'prepare':
+      return $text;
+    case 'process':
+      $regex = '(?<!\w)(\[#(\d+)(#comment-(\d+))?\])(?![^<]*<\/a>|([^<]|(<(?!code)))*<\/code>|([^<]|(<(?!pre)))*<\/pre>|\w)';
+      $offset = 0;
+      while(preg_match('/'.$regex.'/', $text, $preg_matches, PREG_OFFSET_CAPTURE, $offset)) {
+        $offset++;
+        $match = $preg_matches[1];
+        $nid = $preg_matches[2][0];
+        $comment_id=$preg_matches[4][0];
+        $node = node_load($nid);
+        if (is_object($node) && node_access('view', $node)) {
+          $link = theme_project_issue_issue_link($node, $comment_id);
+          $text = substr_replace($text, $link, $match[1], strlen($match[0]));
+          $offset = max($offset, $match[1]+strlen($link));
+        }
+        else {
+          $offset = max($offset, $match[1]+strlen($match[0]));
+        }
+      }
+      return $text;
+  }
+}
+
+/**
+ * Implementation of hook_requirements()
+ * @ingroup project_issue_filter
+ */
+function project_issue_requirements($phase) {
+  $requirements = array();
+  $input_formats = array();
+  if ($phase == 'runtime') {
+
+    $grants = module_implements('node_grants');
+    if (!empty($grants)) {
+      $conflict_grants = TRUE;
+    }
+    $allowed_roles = user_roles(FALSE, 'access project issues');
+    if (!isset($allowed_roles[DRUPAL_ANONYMOUS_RID])) {
+      $conflict_anonymous = TRUE;
+    }
+
+
+    foreach (filter_formats() as $format => $input_format) {
+      $filters = filter_list_format($format);
+      if (isset($filters['project_issue/0'])) {
+        if ($conflict_grants && filter_format_allowcache($format)) {
+          $requirements[] = array(
+            'title' => 'Project Issue to link filter',
+            'value' => t('Some module conflicts were detected.'),
+            'description' => t('%issuefilter conflicts with node access control modules, because caching is enabled. Users may be able to see cached titles of project issues they should not have access to. It is advised to disable the filter in !inputformat input format.', array('%issuefilter' => 'Project Issue to link filter', '!inputformat' => l($input_format->name, "admin/settings/filters/$format"))),
+            'severity' => REQUIREMENT_ERROR,
+          );
+        }
+
+        if ($conflict_anonymous && filter_format_allowcache($format)) {
+          $requirements[] = array(
+            'title' => 'Project Issue to link filter',
+            'value' => t('Some security conflicts were detected.'),
+            'description' => t('%issuefilter conflicts with access settings, because caching is enabled. Users who do not have access to some project issues may be able to see their cached titles. It is advised to disable the filter in !inputformat input format.', array('%issuefilter' => 'Project Issue to link filter', '!inputformat' => l($input_format->name, "admin/settings/filters/$format"))),
+            'severity' => REQUIREMENT_ERROR,
+          );
+        }
+
+        //Put up an error when some code escaping filter's weight is higher.
+        $low_filters = array('filter/0', 'filter/1', 'bbcode/0', 'codefilter/0', 'geshifilter/0');
+        foreach ($low_filters as $lfilter) {
+          if (isset($filters[$lfilter]) && $filters['project_issue/0']->weight <= $filters[$lfilter]->weight) {
+            $description_names['%issuefilter'] = $filters['project_issue/0']->name;
+            $description_names['%lowfilter']  = $filters[$lfilter]->name;
+            $requirements[] = array(
+              'title' => 'Project Issue to link filter',
+              'value' => t('Some filter conflicts were detected.'),
+              'description' => t('%issuefilter should come after %lowfilter to prevent loss of layout and highlighting.', $description_names)
+                 .' '.l(t('Please rearange the filters.'), "admin/settings/filters/$format/order"),
+              'severity' => REQUIREMENT_ERROR,
+            );
+          }
+        }
+
+      }
+    }
+
+  }
+  return $requirements;
+}
