]> git.ipfire.org Git - thirdparty/bugzilla.git/commitdiff
Bug 206037: [SECURITY] Fix escaping/quoting in edit*.cgi scripts - Patch by Frédéric...
authorlpsolit%gmail.com <>
Sun, 15 Oct 2006 03:30:53 +0000 (03:30 +0000)
committerlpsolit%gmail.com <>
Sun, 15 Oct 2006 03:30:53 +0000 (03:30 +0000)
36 files changed:
Bugzilla/Constants.pm
Bugzilla/Template.pm
Bugzilla/Util.pm
checksetup.pl
globals.pl
skins/standard/editusers.css
t/008filter.t
template/en/default/account/prefs/permissions.html.tmpl
template/en/default/account/prefs/settings.html.tmpl
template/en/default/admin/classifications/del.html.tmpl
template/en/default/admin/classifications/edit.html.tmpl
template/en/default/admin/classifications/reclassify.html.tmpl
template/en/default/admin/classifications/select.html.tmpl
template/en/default/admin/components/confirm-delete.html.tmpl
template/en/default/admin/components/updated.html.tmpl
template/en/default/admin/groups/delete.html.tmpl
template/en/default/admin/groups/edit.html.tmpl
template/en/default/admin/groups/list.html.tmpl
template/en/default/admin/keywords/list.html.tmpl
template/en/default/admin/products/confirm-delete.html.tmpl
template/en/default/admin/products/edit-common.html.tmpl
template/en/default/admin/products/edit.html.tmpl
template/en/default/admin/products/updated.html.tmpl
template/en/default/admin/settings/edit.html.tmpl
template/en/default/admin/table.html.tmpl
template/en/default/admin/users/edit.html.tmpl
template/en/default/admin/users/list.html.tmpl
template/en/default/bug/create/create.html.tmpl
template/en/default/bug/edit.html.tmpl
template/en/default/filterexceptions.pl
template/en/default/global/choose-classification.html.tmpl
template/en/default/global/choose-product.html.tmpl
template/en/default/list/edit-multiple.html.tmpl
template/en/default/list/list-simple.html.tmpl
template/en/default/reports/components.html.tmpl
template/en/default/reports/keywords.html.tmpl

index c0051873207fb3eef4b20d8fa801d3d07cde254e..9baebf065af8e301e654a94d3935a270a79d8925 100644 (file)
@@ -91,6 +91,8 @@ use base qw(Exporter);
     ADMIN_GROUP_NAME
 
     SENDMAIL_EXE
+
+    SAFE_PROTOCOLS
 );
 
 @Bugzilla::Constants::EXPORT_OK = qw(contenttypes);
@@ -243,4 +245,9 @@ use constant ADMIN_GROUP_NAME => 'admin';
 # Path to sendmail.exe (Windows only)
 use constant SENDMAIL_EXE => '/usr/lib/sendmail.exe';
 
+# Protocols which are considered as safe.
+use constant SAFE_PROTOCOLS => ('afs', 'cid', 'ftp', 'gopher', 'http', 'https',
+                                'irc', 'mid', 'news', 'nntp', 'prospero', 'telnet',
+                                'view-source', 'wais');
+
 1;
index a6cf8b6fbee84c002f283b936f84ebb8cbc604eb..cbefc93b71a7b34b0277e12e03053d3d96eb31e3 100644 (file)
@@ -498,7 +498,9 @@ sub create {
                 }
                 return $var;
             },
-            
+
+            html_light => \&Bugzilla::Util::html_light_quote,
+
             # iCalendar contentline filter
             ics => [ sub {
                          my ($context, @args) = @_;
index 3e3e3c1beb1921626a68a32db9b92e3cf51f46c0..8ac74a95fe1d150b713dd0828b69d42055417a83 100644 (file)
@@ -33,7 +33,7 @@ use base qw(Exporter);
 @Bugzilla::Util::EXPORT = qw(is_tainted trick_taint detaint_natural
                              detaint_signed
                              html_quote url_quote value_quote xml_quote
-                             css_class_quote
+                             css_class_quote html_light_quote
                              i_am_cgi correct_urlbase
                              lsearch max min
                              diff_arrays diff_strings
@@ -94,6 +94,93 @@ sub html_quote {
     return $var;
 }
 
+sub html_light_quote {
+    my ($text) = @_;
+
+    # List of allowed HTML elements having no attributes.
+    my @allow = qw(b strong em i u p br abbr acronym ins del cite code var
+                   dfn samp kbd big small sub sup tt dd dt dl ul li ol);
+
+    # Are HTML::Scrubber and HTML::Parser installed?
+    eval { require HTML::Scrubber;
+           require HTML::Parser;
+    };
+
+    # We need utf8_mode() from HTML::Parser 3.40 if running Perl >= 5.8.
+    if ($@ || ($] >= 5.008 && $HTML::Parser::VERSION < 3.40)) { # Package(s) not installed.
+        my $safe = join('|', @allow);
+        my $chr = chr(1);
+
+        # First, escape safe elements.
+        $text =~ s#<($safe)>#$chr$1$chr#go;
+        $text =~ s#</($safe)>#$chr/$1$chr#go;
+        # Now filter < and >.
+        $text =~ s#<#&lt;#g;
+        $text =~ s#>#&gt;#g;
+        # Restore safe elements.
+        $text =~ s#$chr/($safe)$chr#</$1>#go;
+        $text =~ s#$chr($safe)$chr#<$1>#go;
+        return $text;
+    }
+    else { # Packages installed.
+        # We can be less restrictive. We can accept elements with attributes.
+        push(@allow, qw(a blockquote q span));
+
+        # Allowed protocols.
+        my $safe_protocols = join('|', SAFE_PROTOCOLS);
+        my $protocol_regexp = qr{(^(?:$safe_protocols):|^[^:]+$)}i;
+
+        # Deny all elements and attributes unless explicitly authorized.
+        my @default = (0 => {
+                             id    => 1,
+                             name  => 1,
+                             class => 1,
+                             '*'   => 0, # Reject all other attributes.
+                            }
+                       );
+
+        # Specific rules for allowed elements. If no specific rule is set
+        # for a given element, then the default is used.
+        my @rules = (a => {
+                           href  => $protocol_regexp,
+                           title => 1,
+                           id    => 1,
+                           name  => 1,
+                           class => 1,
+                           '*'   => 0, # Reject all other attributes.
+                          },
+                     blockquote => {
+                                    cite => $protocol_regexp,
+                                    id    => 1,
+                                    name  => 1,
+                                    class => 1,
+                                    '*'  => 0, # Reject all other attributes.
+                                   },
+                     'q' => {
+                             cite => $protocol_regexp,
+                             id    => 1,
+                             name  => 1,
+                             class => 1,
+                             '*'  => 0, # Reject all other attributes.
+                          },
+                    );
+
+        my $scrubber = HTML::Scrubber->new(default => \@default,
+                                           allow   => \@allow,
+                                           rules   => \@rules,
+                                           comment => 0,
+                                           process => 0);
+
+        # Avoid filling the web server error log with Perl 5.8.x.
+        # In HTML::Scrubber 0.08, the HTML::Parser object is stored in
+        # the "_p" key, but this may change in future versions.
+        if ($] >= 5.008 && ref($scrubber->{_p}) eq 'HTML::Parser') {
+            $scrubber->{_p}->utf8_mode(1);
+        }
+        return $scrubber->scrub($text);
+    }
+}
+
 # This originally came from CGI.pm, by Lincoln D. Stein
 sub url_quote {
     my ($toencode) = (@_);
@@ -535,6 +622,12 @@ be done in the template where possible.
 Returns a value quoted for use in HTML, with &, E<lt>, E<gt>, and E<34> being
 replaced with their appropriate HTML entities.
 
+=item C<html_light_quote($val)>
+
+Returns a string where only explicitly allowed HTML elements and attributes
+are kept. All HTML elements and attributes not being in the whitelist are either
+escaped (if HTML::Scrubber is not installed) or removed.
+
 =item C<url_quote($val)>
 
 Quotes characters so that they may be included as part of a url.
index f7d3513e486872a71afd1cae215f0708d126886c..776d014389f83bc156c8a55899f78fecc8eeb29b 100755 (executable)
@@ -386,6 +386,8 @@ my $gdgraph     = have_vers("GD::Graph",0);
 my $gdtextalign = have_vers("GD::Text::Align",0);
 my $patchreader = have_vers("PatchReader","0.9.4");
 my $imagemagick = have_vers("Image::Magick",0);
+my $html_parser = have_vers("HTML::Parser", ($] >= 5.008) ? "3.40" : 0);
+my $scrubber    = have_vers("HTML::Scrubber", 0);
 
 print "\n" unless $silent;
 
@@ -436,6 +438,15 @@ if (!$patchreader && !$silent) {
     print "install the \nPatchReader module:\n";
     print "PatchReader: " . install_command("PatchReader") . "\n";
 }
+if ((!$scrubber || !$html_parser) && !$silent) {
+    print "If you want additional HTML tags within product and group ";
+    print "descriptions,\nyou should install:\n";
+    print "HTML::Scrubber: " . install_command("HTML::Scrubber") . "\n"
+        if !$scrubber;
+    print "HTML::Parser: " . install_command("HTML::Parser") . "\n"
+        if !$html_parser;
+    print "\n";
+}
 
 if (%missing) {
     print "\n\n";
index c490f6962a7b592e15ca4278939584baad72131d..e790cbb171b0584bc729162aa66f8714b18170b1 100644 (file)
@@ -518,7 +518,8 @@ sub quoteUrls {
     my $tmp;
 
     # non-mailto protocols
-    my $protocol_re = qr/(afs|cid|ftp|gopher|http|https|irc|mid|news|nntp|prospero|telnet|view-source|wais)/i;
+    my $safe_protocols = join('|', SAFE_PROTOCOLS);
+    my $protocol_re = qr/($safe_protocols)/i;
 
     $text =~ s~\b(${protocol_re}:  # The protocol:
                   [^\s<>\"]+       # Any non-whitespace
index a5bf4581fd6f08356b73977360a241c024e54850..55eb5c307f26d7f676be191046a7e9ce90036d1b 100644 (file)
@@ -50,3 +50,8 @@ table.groups td.checkbox {
     text-align: center;
     white-space: nowrap;
 }
+
+.missing {
+    color: red;
+    border-color: inherit;
+}
index 92d4de33a16a9b38a6cb9c8edd728e4e953debf7..cd351525acdd3d66e9d3147d0eb9268b1cf7eef4 100644 (file)
@@ -223,7 +223,7 @@ sub directive_ok {
     # Note: If a single directive prints two things, and only one is 
     # filtered, we may not catch that case.
     return 1 if $directive =~ /FILTER\ (html|csv|js|base64|url_quote|css_class_quote|
-                                        ics|quoteUrls|time|uri|xml|lower|
+                                        ics|quoteUrls|time|uri|xml|lower|html_light|
                                         obsolete|inactive|closed|unitconvert|
                                         none)\b/x;
 
index dd6e1785b9302cfdd6ac53b617fb5056a18a5d85..77dda1ce42ea1de0d91429b4f279faef9e177196 100644 (file)
@@ -42,8 +42,8 @@
         <table align="center">
           [% FOREACH bit_description = has_bits %]
             <tr>
-              <td>[% bit_description.name %]</td>
-              <td>[% bit_description.desc %]</td>
+              <td>[% bit_description.name FILTER html %]</td>
+              <td>[% bit_description.desc FILTER html_light %]</td>
             </tr>
           [% END %]
         </table>
@@ -63,8 +63,8 @@
           <table align="center">
           [% FOREACH bit_description = set_bits %]
             <tr>
-              <td>[% bit_description.name %]</td>
-              <td>[% bit_description.desc %]</td>
+              <td>[% bit_description.name FILTER html %]</td>
+              <td>[% bit_description.desc FILTER html_light %]</td>
             </tr>
           [% END %]
           </table>
index 3ef9a5852e33a64deb8e961c050bf33f6e3c0f5d..568dac0cbda935305f42f6d58b6768132bfaca48 100644 (file)
@@ -49,8 +49,8 @@
         </td>
         <td>
           [% IF settings.${name}.is_enabled %]
-            <select name="[% name %]" id="[% name %]">
-              <option value="[% default_name %]"
+            <select name="[% name FILTER html %]" id="[% name FILTER html %]">
+              <option value="[% default_name FILTER html %]"
                 [% ' selected="selected"' IF settings.${name}.is_default %]>
                 Site Default ([% setting_descs.${default_val} OR default_val FILTER html %])
               </option>
@@ -64,8 +64,8 @@
               [% END %]
             </select>
           [% ELSE %]
-            <select name="[% name %]" id="[% name %]" disabled="disabled">
-              <option value="[% default_name %]">
+            <select name="[% name FILTER html %]" id="[% name FILTER html %]" disabled="disabled">
+              <option value="[% default_name FILTER html %]">
                 Site Default ([% setting_descs.${default_val} OR default_val FILTER html %])
               </option>
             </select>
index c32e46b4df7f20a87db8b3297777d15df3069692..7f54a18ed875f02f86c4c39a2dee1bc2688b5e21 100644 (file)
@@ -36,7 +36,7 @@
   <td valign="top">Description:</td>
   <td valign="top">
     [% IF classification.description %]
-      [% classification.description FILTER none %]
+      [% classification.description FILTER html_light %]
     [% ELSE %]
       <font color="red">description missing</font>
     [% END %]
index 24ec9dacfccaf41cff3e748e5851cbeb9efa4592..60ece58b2ba29c6c7a4d1b590a867ccb0f4b72ef 100644 (file)
@@ -33,7 +33,7 @@
     <tr>
       <th align="right">Description:</th>
       <td><textarea rows=4 cols=64 name="description">
-            [% classification.description FILTER none %]</textarea>
+            [% classification.description FILTER html %]</textarea>
       </td>
     </tr>
     <tr valign=top>
@@ -49,7 +49,7 @@
                 <th align=right valign=top>[% product.name FILTER html %]</th>
                 <td valign=top>
                   [% IF product.description %]
-                    [% product.description FILTER none %]
+                    [% product.description FILTER html_light %]
                   [% ELSE %]
                     <font color="red">description missing</font>
                   [% END %]
index 127aeea877662d48e149e74138715326cb08ee67..b89f83d093f7b23eee840fdd881649d68ebb6e7b 100644 (file)
@@ -33,7 +33,7 @@
       <td valign="top">Description:</td>
       <td valign="top" colspan=3>
         [% IF classification.description %]
-          [% classification.description FILTER none %]
+          [% classification.description FILTER html_light %]
         [% ELSE %]
           <font color="red">description missing</font>
         [% END %]
index 789c40968bbe11401b49897ad856e11a6eb64afa..616f8445b2e5d22c3825844035337cdba0216224 100644 (file)
@@ -36,7 +36,7 @@
       <td valign="top"><a href="editclassifications.cgi?action=edit&amp;classification=[% cl.name FILTER url_quote %]"><b>[% cl.name FILTER html %]</b></a></td>
       <td valign="top"> 
       [% IF cl.description %]
-        [% cl.description %]
+        [% cl.description FILTER html_light %]
       [% ELSE %]
         <font color="red">none</font>
       [% END %]
index dabace15457e273d3195783e99b1bf9ec03092b7..16418843518e3fe320ec8641a06fa050e482111c 100644 (file)
@@ -44,7 +44,7 @@
 </tr>
 <tr>
   <td valign="top">Component Description:</td>
-  <td valign="top">[% comp.description FILTER html %]</td>
+  <td valign="top">[% comp.description FILTER html_light %]</td>
 </tr>
 <tr>
   <td valign="top">Default assignee:</td>
@@ -66,7 +66,7 @@
 </tr>
 <tr>
   <td valign="top">Product Description:</td>
-  <td valign="top">[% prod.description FILTER html %]</td>
+  <td valign="top">[% prod.description FILTER html_light %]</td>
 [% END %]
 
 [% IF Param('usetargetmilestone') %]
index b4c4fea3cf2db4e47a509eca2c63de60877710a6..e4501a850c80bef9f7dca45480411322f36fdc81 100644 (file)
@@ -48,7 +48,7 @@
   <table>
     <tr>
       <td>Updated description to:</td>
-      <td>'[% description FILTER html %]'</td>
+      <td>'[% description FILTER html_light %]'</td>
     </tr>
   </table>
 [% END %]
index d0f66f2ad4a0822dfcf8890da1e0f7d3cae3bdf7..f52ace03c1a6c791fc695e78bc20a87bf5ccbae0 100644 (file)
@@ -47,7 +47,7 @@
   <tr>
     <td>[% gid FILTER html %]</td>
     <td>[% name FILTER html %]</td>
-    <td>[% description FILTER html %]</td>
+    <td>[% description FILTER html_light %]</td>
   </tr>
 </table>
 
index 610d3102ef0da7a0f569b110f5fa9cc9522c6528..bb513cf12e66893ebc8e0b7ffe598c9807b72951 100644 (file)
             [% group.grpnam FILTER html %]
           </a>
         </td>
-        <td align="left" class="groupdesc">[% group.grpdesc FILTER html %]</td>
+        <td align="left" class="groupdesc">[% group.grpdesc FILTER html_light %]</td>
       </tr>
     [% END %]
   </table>
index 64e30f9e46802c0670824b7a4669e8491f56e388..e6d96b142d809e0a459f434933c8868300e4212e 100644 (file)
@@ -47,6 +47,7 @@
    }
    {name               => 'description'
     heading            => 'Description'
+    allow_html_content => 1
    }
    {name               => 'userregexp'
     heading            => 'User RegExp'
index 84eb6e9f19cd05f7bef67f4fc771f46c84474bdb..b0b9096186631a346a682a382d0971d64b7f4476 100755 (executable)
@@ -43,7 +43,8 @@
      },
      { 
        name => "description"
-       heading => "Description" 
+       heading => "Description"
+       allow_html_content => 1
      },
      { 
        name => "bug_count"
index 55fb49fb0951a72f8a86d3245d9847e719e915ea..23550f26d7a9ac9d6d3a5a517f8ec560c2176c1b 100644 (file)
@@ -56,7 +56,7 @@
       [%# descriptions are intentionally not filtered to allow html content %]
       <td>
         [% IF classification.description %]
-          [% classification.description FILTER none %]
+          [% classification.description FILTER html_light %]
         [% ELSE %]
           <span style="color: red">missing</span>
         [% END %]
@@ -78,7 +78,7 @@
     [%# descriptions are intentionally not filtered to allow html content %]
     <td valign="top">
       [% IF product.description %]
-        [% product.description FILTER none %]
+        [% product.description FILTER html_light %]
       [% ELSE %]
         <span style="color: red">missing</span>
       [% END %]
               [%# descriptions are intentionally not filtered to allow html content %]
               <td>
                 [% IF c.description %]
-                  [% c.description FILTER none %]
+                  [% c.description FILTER html_light %]
                 [% ELSE %]
                   <span style="color: red">missing</span>
                 [% END %]
index ec6477287022623496dcbb1a48e518d9f7c9b4d4..64dd960a5251b29ef0eac289069017bae7919fd8 100644 (file)
@@ -40,7 +40,7 @@
 <tr>
   <th align="right">Description:</th>
   <td><textarea rows="4" cols="64" wrap="virtual" name="description">
-        [% product.description FILTER none %]</textarea>
+        [% product.description FILTER html %]</textarea>
   </td>
 </tr>
 
index 4e8cc7b1955272bb70efc8bb2cc04d7137e56e1c..105ec6e7417b28d012b7a7fa6ce1e249204f2f2e 100644 (file)
@@ -50,7 +50,7 @@
           [% FOREACH component = product.components %]
             <b>[% component.name FILTER html %]:</b>&nbsp;
             [% IF component.description %]
-              [% component.description FILTER none %]
+              [% component.description FILTER html_light %]
             [% ELSE %]
               <font color="red">description missing</font>
             [% END %]
index e74720fed8f9d8df79da16ef6e930e813a156a73..8a0790d6ec70dcadde360406362a964767b5990c 100644 (file)
@@ -75,7 +75,7 @@
   <p>
     Updated description to:</p>
   </p>
-  <p style="margin: 1em 3em 1em 3em">[% product.description FILTER html %]</p>
+  <p style="margin: 1em 3em 1em 3em">[% product.description FILTER html_light %]</p>
   [% updated = 1 %]
 [% END %]
 
index b5377a2410b4a1fa26c10258da07fe3bcc5fa732..85663f19b13794b386978f4d828e9184be07e22a 100644 (file)
@@ -64,7 +64,7 @@ page, and the Default Value will automatically apply to everyone.
               [% setting_descs.$name OR name FILTER html %]
             </td>
             <td>
-              <select name="[% name %]" id="[% name %]">
+              <select name="[% name FILTER html %]" id="[% name FILTER html %]">
                 [% FOREACH x = settings.${name}.legal_values %]
                     <option value="[% x FILTER html %]"
                       [% " selected=\"selected\"" IF x == settings.${name}.default_value %]>
@@ -75,8 +75,8 @@ page, and the Default Value will automatically apply to everyone.
             </td>
             <td align="center">
               <input type="checkbox"
-                name="[% checkbox_name %]"
-                id="[% checkbox_name %]"
+                name="[% checkbox_name FILTER html %]"
+                id="[% checkbox_name FILTER html %]"
                 [% " checked=\"checked\"" IF settings.${name}.is_enabled %]>
               <br>
             </td>
index 29108fd6c4d487f26d469daceca8679d1c7d7965..d13dceb66ae1af35cf438666a62632abc4432b61 100644 (file)
@@ -32,7 +32,7 @@
   #                  with the key xxx in data hash of the current row.
   #     content: If specified, the content of this variable is used
   #              instead of the data pulled from the current row. 
-  #              NOTE: This value is not HTML filtered at output!
+  #              NOTE: This value is only partially HTML filtered!
   #     content_use_field: If defined and true, then each value in the 
   #                        column corresponds with a key in the
   #                        field_descs field, and that value from the 
@@ -41,8 +41,8 @@
   #                        This content WILL be HTML-filtered in this case.
   #     align: left/center/right. Controls the horizontal alignment of the
   #            text in the column.
-  #     allow_html_content: if defined, then this column allows html content
-  #                         so it will not be filtered 
+  #     allow_html_content: if defined, then this column allows some html content
+  #                         and so it will be only partially filtered.
   #     yesno_field: Turn the data from 0/!0 into Yes/No
   #
   # data:
@@ -94,6 +94,7 @@
          content = c.content
          content_use_field = c.content_use_field
          align = c.align
+         class = c.class
          allow_html_content = c.allow_html_content
          yesno_field = c.yesno_field
        %]
              IF override.override_content_use_field %]
           [% SET align = override.align
              IF override.override_align %]
+          [% SET class = override.class
+             IF override.override_class %]
           [% SET allow_html_content = override.allow_html_content
              IF override.override_allow_html_content %]
           [% SET yesno_field = override.yesno_field
         [% END %]
       [% END %]
 
-      <td [% IF align %] align="[% align FILTER html %]" [% END %]>
+      <td [% IF align %] align="[% align FILTER html %]" [% END %]
+          [% IF class %] class="[% class FILTER html %]" [% END %]>
 
         [% IF contentlink %]
           [% link_uri = contentlink %]
            [% colname = row.${c.name} %]
            [% field_descs.${colname} FILTER html %]
         [% ELSIF content %]
-            [% content FILTER none %]
+            [% content FILTER html_light %]
         [% ELSE %]
           [% IF yesno_field %]
             [% IF row.${c.name} %]
             [% END %]
           [% ELSE %]
             [% IF allow_html_content %]
-              [% row.${c.name} FILTER none %]
+              [% row.${c.name} FILTER html_light %]
             [% ELSE %]
               [% row.${c.name} FILTER html %]
             [% END %]
index ce593ee65ba3453a4abbbbf8068d11c35ea58696..03125eaf1da3b6da3457f497a33ad982e2ce87a3 100644 (file)
@@ -89,7 +89,7 @@
               <td class="groupname">
                 <label for="group_[% group.id %]">
                   <strong>[% group.name FILTER html %]:</strong>
-                  [%+ group.description FILTER html %]
+                  [%+ group.description FILTER html_light %]
                 </label>
               </td>
             </tr>
index 9cbd7530db9f903ef831fce386a0c396ff1f4f2b..227671d4f19b2b7345bd9e4df902211b98ecf8aa 100644 (file)
     heading            => 'Edit user...'
     contentlink        => 'editusers.cgi?action=edit&amp;userid=%%userid%%' _
                           listselectionurlparams
-    allow_html_content => 1
    }
    {name               => 'realname'
     heading            => 'Real name'
-    allow_html_content => 1
    }
   ]
 %]
   %]
 [% END %]
 
+[%# Disabled users are crossed out. Missing realnames are noticed in red. %]
+[% overrides.login_name = [] %]
+[% overrides.realname = [] %]
+
 [% FOREACH thisuser = users %]
-  [%# We FILTER html here because we need admin/table.html.tmpl to accept HTML
-    # for styling, so we cannot let admin/table.html.tmpl do the FILTER.
-    #%]
-  [% thisuser.login_name = BLOCK %]
-    [% thisuser.login_name FILTER html %]
-  [% END %]
-  [% IF thisuser.realname %]
-    [% thisuser.realname = BLOCK %]
-      [% thisuser.realname FILTER html %]
-    [% END %]
-  [% ELSE %]
-    [% SET thisuser.realname = '<span style="color: red">missing</span>' %]
+  [% IF !thisuser.realname %]
+    [%# We cannot pass one class now and one class later. %]
+    [% SET classes = (thisuser.disabledtext ? "bz_inactive missing" : "missing") %]
+    [% overrides.realname.push({
+        match_value      => "$thisuser.login_name"
+        match_field      => 'login_name'
+        content          => "missing"
+        override_content => 1
+        class            => "$classes"
+        override_class   => 1 })
+    %]
   [% END %]
+
   [% IF thisuser.disabledtext %]
-    [% thisuser.login_name = "<span class=\"bz_inactive\">$thisuser.login_name</span>" %]
-    [% thisuser.realname = "<span class=\"bz_inactive\">$thisuser.realname</span>" %]
+    [% overrides.login_name.push({
+        match_value    => "$thisuser.login_name"
+        match_field    => 'login_name'
+        class          => "bz_inactive"
+        override_class => 1 })
+    %]
+
+    [% overrides.realname.push({
+        match_value    => "$thisuser.login_name"
+        match_field    => 'login_name'
+        class          => "bz_inactive"
+        override_class => 1 })
+    %]
   [% END %]
 [% END %]
 
@@ -83,6 +96,7 @@
 [% PROCESS admin/table.html.tmpl
   columns = columns
   data    = users
+  overrides = overrides
 %]
 
 <p>
index 20b311234b1ce90ffb4d48e0126ae55b1abfb0fa..18ac4ec05537c71aa2971a8336058bc5cfc1f178 100644 (file)
@@ -386,7 +386,7 @@ function set_assign_to() {
         <input type="checkbox" id="bit-[% g.bit %]"
           name="bit-[% g.bit %]" value="1"
           [% " checked=\"checked\"" IF g.checked %]>
-          <label for="bit-[% g.bit %]">[% g.description %]</label><br>
+          <label for="bit-[% g.bit %]">[% g.description FILTER html_light %]</label><br>
       [% END %]
       <br>
     [% END %]
index 2652b4b7676d32a14643ee818135debfe4779ca8..d3e2d8d4f2b24ad530cf7250112a963c9579538c 100644 (file)
             <td>
               [% resolution_descs.${bug.resolution} FILTER html %]
               [% IF bug.resolution == "DUPLICATE" %]
-                of [% terms.bug %] [%+ "${bug.dup_id}" FILTER bug_link(bug.dup_id) %]
+                of [% terms.bug %] [%+ "${bug.dup_id}" FILTER bug_link(bug.dup_id) FILTER none %]
               [% END %]
             </td>
           </tr>
       <input type="checkbox" name="bit-[% group.bit %]" value="1"
         [% " checked=\"checked\"" IF group.ison %]
         [% " disabled=\"disabled\"" IF NOT group.ingroup %]>
-      [% group.description %]
+      [% group.description FILTER html_light %]
       <br>
       [% END %]
     [% END %]
   <th align="right">[% terms.Bug %] [%+ bug.bug_id %] [%+ dep.title %]:</th>
   <td>
   [% FOREACH depbug = bug.${dep.fieldname} %]
-    [% depbug FILTER bug_link(depbug) %][% " " %]
+    [% depbug FILTER bug_link(depbug) FILTER none %][% " " %]
   [% END %]
   </td>
   <td>
index cc4503bb77a5a1e3d530b40e6bdeb6df04df4493..2c594fde5fa6c2b693e80116372a9075c73ecc96 100644 (file)
 
 'reports/components.html.tmpl' => [
   'numcols',
-  'comp.description', 
 ],
 
 'reports/duplicates-table.html.tmpl' => [
 ],
 
 'reports/keywords.html.tmpl' => [
-  'keyword.description', 
   'keyword.bugcount', 
 ],
 
 
 'list/edit-multiple.html.tmpl' => [
   'group.id', 
-  'group.description',
-  'group.description FILTER inactive', 
   'knum', 
   'menuname', 
 ],
 
-'list/list-simple.html.tmpl' => [
-  'title', 
-],
-
 'list/list.rdf.tmpl' => [
   'template_version', 
   'bug.bug_id', 
   'VERSION', 
 ],
 
-'global/choose-classification.html.tmpl' => [
-  'class.description', 
-],
-
 'global/choose-product.html.tmpl' => [
   'target',
-  'proddesc.$p', 
 ],
 
 # You are not permitted to add any values here. Everything in this file should 
   'bug.bug_id', 
   'bug.votes', 
   'group.bit', 
-  'group.description', 
   'dep.title', 
   'dep.fieldname', 
   'accesskey', 
   'bug.${dep.fieldname}.join(\', \')', 
   'selname',
-  'depbug FILTER bug_link(depbug)',
-  '"${bug.dup_id}" FILTER bug_link(bug.dup_id)',
 ],
 
 'bug/knob.html.tmpl' => [
 
 'bug/create/create.html.tmpl' => [
   'g.bit',
-  'g.description',
   'sel.name',
   'sel.description',
   'cloned_bug_id'
   'link_uri'
 ],
 
-'admin/classifications/select.html.tmpl' => [
-  'cl.description', 
-],
-
 'admin/products/groupcontrol/confirm-edit.html.tmpl' => [
   'group.count', 
 ],
   'bug_count'
 ],
 
-'admin/settings/edit.html.tmpl' => [
-  'name',
-  'checkbox_name'
-],
-
 'account/login.html.tmpl' => [
   'target', 
 ],
   'prefname',
 ],
 
-'account/prefs/permissions.html.tmpl' => [
-  'bit_description.name', 
-  'bit_description.desc', 
-],
-
 'account/prefs/prefs.html.tmpl' => [
   'current_tab.label',
   'current_tab.name',
 ],
 
-'account/prefs/settings.html.tmpl' => [
-  'name',
-  'default_name'
-],
-
 );
index 0a14fe44e9784fc80b9652116249cbf169404384..df0c379118dcfb4e034837ab1fb3a47ee710594f 100644 (file)
@@ -54,7 +54,7 @@
     </th>
 
     [% IF class.description %]
-      <td valign="top">&nbsp;[% class.description %]</td>
+      <td valign="top">&nbsp;[% class.description FILTER html_light %]</td>
     [% END %]
   </tr>
 [% END %]
index 078b9b70076bdfd68dfc8c0efe69bc5fb43b0358..c9c5941d1cdb82fe57632ae0e814aef75612743e 100644 (file)
@@ -49,7 +49,7 @@
     </th>
 
     [% IF proddesc.$p %]
-      <td valign="top">[% proddesc.$p %]</td>
+      <td valign="top">[% proddesc.$p FILTER html_light %]</td>
     [% END %]
   </tr>
 [% END %]
index dde98d546f23f1f1bb78b24c00ea135fcbe97732..62399f83d33ca7feab9ed8a10a43320d77c8fbf6 100644 (file)
       [% END %]
 
       <td>
-        [% IF group.isactive %]
-          [% group.description %]
-        [% ELSE %]
-          [% group.description FILTER inactive %]
-        [% END %]
+        [% SET inactive = !group.isactive %]
+        [% group.description FILTER html_light FILTER inactive(inactive) %]
       </td>
 
     </tr>
index 9cdc1bed93828971d42c0d48df8e99356973bb38..8494baf6078cf01e7124320b1ec642a771d29305 100644 (file)
@@ -30,8 +30,6 @@
 [%############################################################################%]
 
 [% DEFAULT title = "$terms.Bug List" %]
-[% title = title FILTER html %]
-
 
 [%############################################################################%]
 [%# Bug Table                                                                #%]
@@ -40,7 +38,7 @@
 <html>
 
   <head>
-    <title>[% title %]</title>
+    <title>[% title FILTER html %]</title>
     <base href="[% Param("urlbase") %]">
     <link href="skins/standard/buglist.css" rel="stylesheet" type="text/css">
   </head>
index 3578a86e418323068ae9ab39c4e3c54281d4105c..37e4627704fa6018dedacc50ec4bb948a7b4aa12 100644 (file)
@@ -93,7 +93,7 @@
   </tr>
   <tr>
     <td colspan="[% numcols - 1 %]">
-      [% comp.description %]
+      [% comp.description FILTER html_light %]
     </td>
   </tr>
 [% END %]
index bd52cf6eca99c88a93847655057677024eceba9c..10bfe1e8730be514d9634132a049416a70062cd3 100644 (file)
@@ -22,7 +22,7 @@
 [%# INTERFACE:
   # keywords: array of hashes. May be empty. Each has has three members:
   #   name: the name of the keyword
-  #   description: keyword description. May be HTML.
+  #   description: keyword description. Can contain some limited HTML code.
   #   bugcount: number of bugs with that keyword
   # caneditkeywords: boolean. True if this user can edit keywords
  %]
@@ -52,7 +52,7 @@
       <a name="[% keyword.name FILTER html %]">
         [% keyword.name FILTER html %]</a>
     </th>
-    <td>[% keyword.description %]</td>
+    <td>[% keyword.description FILTER html_light %]</td>
     <td align="right">
       [% IF keyword.bugcount > 0 %]
         <a href="buglist.cgi?keywords=[% keyword.name FILTER url_quote %]">