]> git.ipfire.org Git - thirdparty/bugzilla.git/commitdiff
Bug 192677: Add new test to flag failure-to-filter situations in the templates, and...
authorjustdave%syndicomm.com <>
Fri, 25 Apr 2003 03:49:27 +0000 (03:49 +0000)
committerjustdave%syndicomm.com <>
Fri, 25 Apr 2003 03:49:27 +0000 (03:49 +0000)
result of it.
Patch by Gervase Markham <gerv@mozilla.org>
r= myk, bbaetz, justdave
a= justdave

19 files changed:
duplicates.cgi
t/008filter.t [new file with mode: 0644]
template/en/default/account/auth/login.html.tmpl
template/en/default/attachment/edit.html.tmpl
template/en/default/bug/create/create-guided.html.tmpl
template/en/default/bug/create/create.html.tmpl
template/en/default/bug/create/make-template.html.tmpl
template/en/default/bug/show-multiple.html.tmpl
template/en/default/filterexceptions.pl [new file with mode: 0644]
template/en/default/global/choose-product.html.tmpl
template/en/default/global/code-error.html.tmpl
template/en/default/global/hidden-fields.html.tmpl
template/en/default/global/message.html.tmpl
template/en/default/global/user-error.html.tmpl
template/en/default/list/change-columns.html.tmpl
template/en/default/list/list.html.tmpl
template/en/default/list/table.html.tmpl
template/en/default/reports/duplicates.html.tmpl
template/en/default/search/form.html.tmpl

index 1a3c08a9f4befd8b13ffd6d86bd3a01a47666581..64a3f7ab3c6eb7584bfd43c1acc9fbc38dc49841 100755 (executable)
@@ -74,7 +74,7 @@ my $sortby = formvalue("sortby");
 my $changedsince = formvalue("changedsince", 7);
 my $maxrows = formvalue("maxrows", 100);
 my $openonly = formvalue("openonly");
-my $reverse = formvalue("reverse");
+my $reverse = formvalue("reverse") ? 1 : 0;
 my $product = formvalue("product");
 my $sortvisible = formvalue("sortvisible");
 my @buglist = (split(/[:,]/, formvalue("bug_id")));
@@ -159,8 +159,14 @@ if (!tie(%before, 'AnyDBM_File', "data/duplicates/dupes$whenever",
     $dobefore = 1;
 }
 
+my $origmaxrows = $maxrows;
 detaint_natural($maxrows)
-  || ThrowUserError("invalid_maxrows", { maxrows => $maxrows});
+  || ThrowUserError("invalid_maxrows", { maxrows => $origmaxrows});
+
+my $origchangedsince = $changedsince;
+detaint_natural($changedsince)
+  || ThrowUserError("invalid_changedsince", 
+                    { changedsince => $origchangedsince });
 
 my @bugs;
 my @bug_ids; 
diff --git a/t/008filter.t b/t/008filter.t
new file mode 100644 (file)
index 0000000..10d7fc6
--- /dev/null
@@ -0,0 +1,182 @@
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code are the Bugzilla tests.
+#
+# The Initial Developer of the Original Code is Jacob Steenhagen.
+# Portions created by Jacob Steenhagen are
+# Copyright (C) 2001 Jacob Steenhagen. All
+# Rights Reserved.
+#
+# Contributor(s): Gervase Markham <gerv@gerv.net>
+
+#################
+#Bugzilla Test 8#
+#####filter######
+
+# This test scans all our templates for every directive. Having eliminated
+# those which cannot possibly cause XSS problems, it then checks the rest
+# against the safe list stored in the filterexceptions.pl file. 
+
+# Sample exploit code: '>"><script>alert('Oh dear...')</script>
+
+use strict;
+use lib 't';
+
+use vars qw(%safe);
+
+use Support::Templates;
+use File::Spec 0.82;
+use Test::More tests => $Support::Templates::num_actual_files;
+use Cwd;
+
+# Undefine the record separator so we can read in whole files at once
+my $oldrecsep = $/;
+$/ = undef;
+my $topdir = cwd;
+
+foreach my $path (@Support::Templates::include_paths) {
+    $path =~ m|template/([^/]+)/|;
+    my $lang = $1;
+    chdir $topdir; # absolute path
+    my @testitems = Support::Templates::find_actual_files($path);
+    
+    next unless @testitems;
+    
+    # Some people require this, others don't. No-one knows why.
+    chdir $path; # relative path
+    
+    # We load a %safe list of acceptable exceptions.
+    if (!-r "filterexceptions.pl") {
+        ok(0, "$path has templates but no filterexceptions.pl file. --ERROR");
+        next;
+    }
+    else {
+        do "filterexceptions.pl";
+    }
+    
+    # We preprocess the %safe hash of lists into a hash of hashes. This allows
+    # us to flag which members were not found, and report that as a warning, 
+    # thereby keeping the lists clean.
+    foreach my $file (keys %safe) {
+        my $list = $safe{$file};
+        $safe{$file} = {};
+        foreach my $directive (@$list) {
+            $safe{$file}{$directive} = 0;    
+        }
+    }
+
+    foreach my $file (@testitems) {
+        # There are some files we don't check, because there is no need to
+        # filter their contents due to their content-type.
+        if ($file =~ /\.(txt|png)\.tmpl$/) {
+            ok(1, "($lang) $file is filter-safe");
+            next;
+        }
+        
+        # Read the entire file into a string
+        open (FILE, "<$file") || die "Can't open $file: $!\n";    
+        my $slurp = <FILE>;
+        close (FILE);
+
+        my @unfiltered;
+
+        # /g means we execute this loop for every match
+        # /s means we ignore linefeeds in the regexp matches
+        while ($slurp =~ /\[%(.*?)%\]/gs) {
+            my $directive = $1;
+
+            my @lineno = ($` =~ m/\n/gs);
+            my $lineno = scalar(@lineno) + 1;
+
+            # Comments
+            next if $directive =~ /^[+-]?#/;        
+
+            # Remove any leading/trailing + or - and whitespace.
+            $directive =~ s/^[+-]?\s*//;
+            $directive =~ s/\s*[+-]?$//;
+
+            # Directives
+            next if $directive =~ /^(IF|END|UNLESS|FOREACH|PROCESS|INCLUDE|
+                                     BLOCK|USE|ELSE|NEXT|LAST|DEFAULT|FLUSH|
+                                     ELSIF|SET|SWITCH|CASE)/x;
+
+            # Simple assignments
+            next if $directive =~ /^[\w\.\$]+\s+=\s+/;
+
+            # Conditional literals with either sort of quotes 
+            # There must be no $ in the string for it to be a literal
+            next if $directive =~ /^(["'])[^\$]*[^\\]\1/;
+
+            # Special values always used for numbers
+            next if $directive =~ /^[ijkn]$/;
+            next if $directive =~ /^count$/;
+            
+            # Params
+            next if $directive =~ /^Param\(/;
+
+            # Other functions guaranteed to return OK output
+            next if $directive =~ /^(time2str|GetBugLink)\(/;
+
+            # Safe Template Toolkit virtual methods
+            next if $directive =~ /\.(size)$/;
+
+            # Special Template Toolkit loop variable
+            next if $directive =~ /^loop\.(index|count)$/;
+            
+            # Things which are already filtered
+            # Note: If a single directive prints two things, and only one is 
+            # filtered, we may not catch that case.
+            next if $directive =~ /FILTER\ (html|csv|js|url_quote|quoteUrls|
+                                            time|uri|xml)/x;
+
+            # Exclude those on the nofilter list
+            if (defined($safe{$file}{$directive})) {
+                $safe{$file}{$directive}++;
+                next;
+            };
+
+            # This intentionally makes no effort to eliminate duplicates; to do
+            # so would merely make it more likely that the user would not 
+            # escape all instances when attempting to correct an error.
+            push(@unfiltered, "$lineno:$directive");
+        }  
+
+        my $fullpath = File::Spec->catfile($path, $file);
+        
+        if (@unfiltered) {
+            my $uflist = join("\n  ", @unfiltered);
+            ok(0, "($lang) $fullpath has unfiltered directives:\n  $uflist\n--ERROR");
+        }
+        else {
+            # Find any members of the exclusion list which were not found
+            my @notfound;
+            foreach my $directive (keys %{$safe{$file}}) {
+                push(@notfound, $directive) if ($safe{$file}{$directive} == 0);    
+            }
+
+            if (@notfound) {
+                my $nflist = join("\n  ", @notfound);
+                ok(0, "($lang) $fullpath - FEL has extra members:\n  $nflist\n" . 
+                                                                  "--WARNING");
+            }
+            else {
+                # Don't use the full path here - it's too long and unwieldy.
+                ok(1, "($lang) $file is filter-safe");
+            }
+        }
+    }
+}
+
+$/ = $oldrecsep;
+
+exit 0;
index 6dbd6531f4527475dfaf84221d125c067fb78a74..f342b17914034158b3b1966f41c0f9ee06c14470 100644 (file)
@@ -34,7 +34,7 @@
   I need a legitimate login and password to continue.
 </p>
 
-<form action="[% target %]" method="POST">
+<form action="[% target FILTER html %]" method="POST">
   <table>
     <tr>
       <td align="right">
index 57d99f766704e0295ba5189b957161193b8b2d95..7cd682cd575ffaef701a1f628c8aa351fea4c6cd 100644 (file)
@@ -51,7 +51,7 @@
       // If this is a plaintext document, remove cruft that Mozilla adds
       // because it treats it as an HTML document with a big PRE section.
       // http://bugzilla.mozilla.org/show_bug.cgi?id=86012
-      var contentType = '[% contenttype %]';
+      var contentType = '[% contenttype FILTER js %]';
       if ( contentType == 'text/plain' )
         {
           theContent = theContent.replace( /^<html><head\/?><body><pre>/i , "" );
index a716ddca6ba4b85104e497150467f00108c00e87..7ab7436a71e1c31ea3749ad2a687bc28606091ff 100644 (file)
@@ -211,8 +211,10 @@ function PutDescription() {
 <form method="post" action="post_bug.cgi">  
   <input type="hidden" name="format" value="guided">
   <input type="hidden" name="assigned_to" value="">
-  <input type="hidden" name="priority" value="[% default.priority %]">
-  <input type="hidden" name="version" value="[% default.version %]">
+  <input type="hidden" name="priority" 
+         value="[% default.priority FILTER html %]">
+  <input type="hidden" name="version" 
+         value="[% default.version FILTER html %]">
   
 <table valign="top" cellpadding="5" cellspacing="5" border="0">
 
index c59cd3a7078fd6e39df4e35fbcd9d0251e8d786d..fcc894e1e63cced466d8aac60243b9a37bc03323 100644 (file)
     [% sel = { description => 'Priority', name => 'priority' } %]
     [% INCLUDE select %]
   [% ELSE %]
-    <input type="hidden" name="priority" value="[% default.priority %]">
+    <input type="hidden" name="priority" 
+           value="[% default.priority FILTER html %]">
   [% END %]
 
   [% sel = { description => 'Severity', name => 'bug_severity' } %]
index 1e2495ff86fbd1d2f91ca8a5452862654a2497e5..958d183cc9840b14e4aa11b1b31c86d6a3b77c02 100644 (file)
@@ -25,7 +25,7 @@
 %]
 
 <p>
-If you bookmark <a href="enter_bug.cgi?[% url %]">this link</a>,
+If you bookmark <a href="enter_bug.cgi?[% url FILTER html %]">this link</a>,
 going to the bookmark will bring up the enter bug page with the fields
 initialized as you've requested.
 </p>
index a5cdc4dc88b2fa774eb68302719c1984ed2d754f..41d824eb3b9c054de428e1f2174d09f40df7dd0c 100644 (file)
     <tr>
       <td colspan="4">
         <b>URL:</b>&nbsp;
-        <a href="[% bug.bug_file_loc %]">[% bug.bug_file_loc FILTER html %]</a> 
+        <a href="[% bug.bug_file_loc FILTER html %]">
+                 [% bug.bug_file_loc FILTER html %]</a> 
     </tr>
     
     <tr>
diff --git a/template/en/default/filterexceptions.pl b/template/en/default/filterexceptions.pl
new file mode 100644 (file)
index 0000000..b462b7b
--- /dev/null
@@ -0,0 +1,597 @@
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code are the Bugzilla tests.
+#
+# The Initial Developer of the Original Code is Jacob Steenhagen.
+# Portions created by Jacob Steenhagen are
+# Copyright (C) 2001 Jacob Steenhagen. All
+# Rights Reserved.
+#
+# Contributor(s): Gervase Markham <gerv@gerv.net>
+
+# Important! The following classes of directives are excluded in the test,
+# and so do not need to be added here. Doing so will cause warnings.
+# See 008filter.t for more details.
+#
+# Comments                        - [%#...
+# Directives                      - [% IF|ELSE|UNLESS|FOREACH...
+# Assignments                     - [% foo = ...
+# Simple literals                 - [% " selected" ...
+# Values always used for numbers  - [% (i|j|k|n|count) %]
+# Params                          - [% Param(...
+# Safe functions                  - [% (time2str|GetBugLink)...
+# Safe vmethods                   - [% foo.size %]
+# TT loop variables               - [% loop.count %]
+# Already-filtered stuff          - [% wibble FILTER html %]
+#   where the filter is one of html|csv|js|url_quote|quoteUrls|time|uri|xml
+
+# Key:
+#
+# "#": directive should be filtered, but not doing so is not a security hole
+# The plan is to come back and add filtering for all those marked "#" after
+# the security release.
+#
+# "# Email": as above; but noting that it's an email address.
+# Other sorts of comments denote cleanups noticed while doing this work;
+# they should be fixed in the very short term.
+
+%::safe = (
+
+'sidebar.xul.tmpl' => [
+  'template_version', 
+],
+
+'flag/list.html.tmpl' => [
+  'flag.id', 
+  'flag.status', 
+  'type.id', 
+],
+
+'search/boolean-charts.html.tmpl' => [
+  '"field${chartnum}-${rownum}-${colnum}"', 
+  '"value${chartnum}-${rownum}-${colnum}"', 
+  '"type${chartnum}-${rownum}-${colnum}"', 
+  'field.name', 
+  'field.description', 
+  'type.name', 
+  'type.description', 
+  '"${chartnum}-${rownum}-${newor}"', 
+  '"${chartnum}-${newand}-0"', 
+  'newchart',
+  'jsmagic',
+],
+
+'search/form.html.tmpl' => [
+  'qv.value',
+  'qv.name',
+  'qv.description',
+  'field.name',
+  'field.description',
+  'field.accesskey',
+  'sel.name',
+  'sel.accesskey',
+  'button_name', #
+],
+
+'search/knob.html.tmpl' => [
+  'button_name', #
+],
+
+'search/search-report-graph.html.tmpl' => [
+  'button_name', #
+],
+
+'search/search-report-table.html.tmpl' => [
+  'button_name', #
+],
+
+'request/queue.html.tmpl' => [
+  'column_headers.$group_field', 
+  'column_headers.$column', 
+  'request.status', 
+  'request.bug_id', 
+  'request.attach_id', 
+],
+
+'reports/components.html.tmpl' => [
+  'numcols',
+  'numcols - 1',
+  'comp.description', 
+  'comp.initialowner', # email address
+  'comp.initialqacontact', # email address
+],
+
+'reports/duplicates-simple.html.tmpl' => [
+  'title', #
+],
+
+'reports/duplicates-table.html.tmpl' => [
+  '"&maxrows=$maxrows" IF maxrows',
+  '"&changedsince=$changedsince" IF changedsince',
+  '"&product=$product" IF product', #
+  '"&format=$format" IF format', #
+  '"&bug_id=$bug_ids_string&sortvisible=1" IF sortvisible',
+  'column.name', 
+  'column.description',
+  'vis_bug_ids.push(bug.id)', 
+  'bug.id', 
+  'bug.count', 
+  'bug.delta', 
+  'bug.component', #
+  'bug.bug_severity', #
+  'bug.op_sys', #
+  'bug.target_milestone', #
+],
+
+'reports/duplicates.html.tmpl' => [
+  'bug_ids_string', 
+  'maxrows',
+  'changedsince',
+  'reverse',
+],
+
+'reports/keywords.html.tmpl' => [
+  'keyword.description', 
+  'keyword.bugcount', 
+],
+
+'reports/report-table.csv.tmpl' => [
+  '"$tbl_field_disp: $tbl\n" IF tbl_field', #
+  'row_field_disp IF row_field', #
+  'col_field_disp', #
+  'num_bugs',
+  'data.$tbl.$col.$row',
+  '', # This is not a bug in the filter exceptions - this template has an 
+      # empty directive which is necessary for it to work properly.
+],
+
+'reports/report-table.html.tmpl' => [
+  'buglistbase', 
+  '"&amp;$tbl_vals" IF tbl_vals', 
+  '"&amp;$col_vals" IF col_vals', 
+  '"&amp;$row_vals" IF row_vals', 
+  'tbl_disp', # 
+  'classes.$row_idx.$col_idx', 
+  'urlbase', 
+  'data.$tbl.$col.$row', 
+  'row_total',
+  'col_totals.$col',
+  'grand_total', 
+],
+
+'reports/report.html.tmpl' => [
+  'tbl_field_disp IF tbl_field', #
+  'row_field_disp IF row_field', #
+  'col_field_disp', #
+  'imagebase', 
+  'width', 
+  'height', 
+  'imageurl', 
+  'formaturl', 
+  'other_format.name', 
+  'other_format.description', #
+  'sizeurl', 
+  'height + 100', 
+  'height - 100', 
+  'width + 100', 
+  'width - 100', 
+  'switchbase',
+  'format',
+  'cumulate',
+],
+
+'reports/duplicates.rdf.tmpl' => [
+  'template_version', 
+  'bug.id', 
+  'bug.count', 
+  'bug.delta', 
+],
+
+'list/change-columns.html.tmpl' => [
+  'column', 
+  'field_descs.${column} || column', #
+],
+
+'list/edit-multiple.html.tmpl' => [
+  'group.id', 
+  'group.description',
+  'group.description FILTER strike', 
+  'knum', 
+  'menuname', 
+],
+
+'list/list-simple.html.tmpl' => [
+  'title', 
+],
+
+'list/list.html.tmpl' => [
+  'buglist', 
+  'bugowners', # email address
+],
+
+'list/list.rdf.tmpl' => [
+  'template_version', 
+  'bug.bug_id', 
+  'column', 
+],
+
+'list/table.html.tmpl' => [
+  'id', 
+  'splitheader ? 2 : 1', 
+  'abbrev.$id.title || field_descs.$id || column.title', #
+  'tableheader',
+  'bug.bug_severity', #
+  'bug.priority', #
+  'bug.bug_id', 
+],
+
+'list/list.csv.tmpl' => [
+  'bug.bug_id', 
+],
+
+'list/list.js.tmpl' => [
+  'bug.bug_id', 
+],
+
+'global/help.html.tmpl' => [
+  'h.id', 
+  'h.html', 
+],
+
+'global/banner.html.tmpl' => [
+  'VERSION', 
+],
+
+'global/choose-product.html.tmpl' => [
+  'target',
+  'proddesc.$p', 
+],
+
+'global/code-error.html.tmpl' => [
+  'parameters', 
+  'bug.bug_id',
+  'field', 
+  'argument', #
+  'function', #
+  'bug_id', # Need to remove unused error no_bug_data
+  'variables.id', 
+  'template_error_msg', # Should move filtering from CGI.pl to template
+  'error', 
+  'error_message', 
+],
+
+'global/header.html.tmpl' => [
+  'javascript', 
+  'style', 
+  'style_url', 
+  'bgcolor', 
+  'onload', 
+  'h1',
+  'h2',
+  'h3', 
+  'message', 
+],
+'global/hidden-fields.html.tmpl' => [
+  'mvalue | html | html_linebreak', # Need to eliminate | usage
+  'field.value | html | html_linebreak',
+],
+
+'global/messages.html.tmpl' => [
+  'parameters',
+  '# ---', # Work out what this is
+  'namedcmd', #
+  'old_email', # email address
+  'new_email', # email address
+  'message_tag', 
+],
+
+'global/select-menu.html.tmpl' => [
+  'options', 
+  'onchange', # Again, need to be certain where we are filtering
+  'size', 
+],
+
+'global/useful-links.html.tmpl' => [
+  'email', 
+  'user.login', # Email address
+],
+
+# Need to change this and code-error to use a no-op filter, for safety
+'global/user-error.html.tmpl' => [
+  'disabled_reason', 
+  'bug_link', 
+  'action', # 
+  'bug_id', 
+  'both', 
+  'filesize', 
+  'attach_id', 
+  'field', 
+  'field_descs.$field', 
+  'today', 
+  'product', #
+  'max', 
+  'votes', 
+  'error_message', 
+],
+
+'global/confirm-user-match.html.tmpl' => [
+  '# use the global field descs', # Need to fix commenting style here
+  'script',
+  '# this is messy to allow later expansion',
+  '# ELSIF for things that don\'t belong in the field_descs hash here',
+  'fields.${field_name}.flag_type.name',
+],
+
+'global/site-navigation.html.tmpl' => [
+  'bug_list.first', 
+  'bug_list.$prev_bug', 
+  'bug_list.$next_bug', 
+  'bug_list.last', 
+  'bug.bug_id', 
+  'bug.votes', 
+  'PerformSubsts(Param(\'mybugstemplate\'), substs)', 
+],
+
+'bug/comments.html.tmpl' => [
+  'comment.isprivate', 
+  'comment.when', 
+],
+
+'bug/dependency-graph.html.tmpl' => [
+  'image_map', # We need to continue to make sure this is safe in the CGI
+  'image_url', 
+  'map_url', 
+  'bug_id', 
+],
+
+'bug/dependency-tree.html.tmpl' => [
+  'hide_resolved ? "Open b" : "B"', 
+  'bugid', 
+  'maxdepth', 
+  'dependson_ids.join(",")', 
+  'blocked_ids.join(",")', 
+  'dep_id', 
+  'hide_resolved ? 0 : 1', 
+  'hide_resolved ? "Show" : "Hide"', 
+  'realdepth < 2 || maxdepth == 1 ? "disabled" : ""', 
+  'hide_resolved', 
+  'realdepth < 2 ? "disabled" : ""', 
+  'maxdepth + 1', 
+  'maxdepth == 0 || maxdepth == realdepth ? "disabled" : ""', 
+  'realdepth < 2 || ( maxdepth && maxdepth < 2 ) ? "disabled" : ""',
+  'maxdepth > 0 && maxdepth <= realdepth ? maxdepth : ""',
+  'maxdepth == 1 ? 1 
+                       : ( maxdepth ? maxdepth - 1 : realdepth - 1 )',
+  'realdepth < 2 || ! maxdepth || maxdepth >= realdepth ?
+            "disabled" : ""',
+],
+
+'bug/edit.html.tmpl' => [
+  'bug.remaining_time', 
+  'bug.delta_ts', 
+  'bug.bug_id', 
+  'bug.votes', 
+  'group.bit', 
+  'group.description', 
+  'knum', 
+  'dep.title', 
+  'dep.fieldname', 
+  'accesskey', 
+  'bug.${dep.fieldname}.join(\', \')', 
+  'selname',
+  'depbug FILTER bug_link(depbug)',
+  '"bug ${bug.dup_id}" FILTER bug_link(bug.dup_id)',
+],
+
+'bug/navigate.html.tmpl' => [
+  'this_bug_idx + 1', 
+  'bug_list.first', 
+  'bug_list.last', 
+  'bug_list.$prev_bug', 
+  'bug_list.$next_bug', 
+],
+
+'bug/show-multiple.html.tmpl' => [
+  'bug.bug_id', 
+  'bug.component', #
+  'attr.description', #
+],
+
+'bug/show.xml.tmpl' => [
+  'VERSION', 
+  'a.attachid', 
+  'field', 
+],
+
+'bug/time.html.tmpl' => [
+  'time_unit FILTER format(\'%.1f\')', 
+  'time_unit FILTER format(\'%.2f\')', 
+  '(act / (act + rem)) * 100 
+       FILTER format("%d")', 
+],
+
+'bug/votes/list-for-bug.html.tmpl' => [
+  'voter.count', 
+  'total', 
+],
+
+'bug/votes/list-for-user.html.tmpl' => [
+  'product.maxperbug', 
+  'bug.id', 
+  'bug.count', 
+  'product.total', 
+  'product.maxvotes', 
+],
+# h2 = voting_user.name # Email
+
+'bug/process/confirm-duplicate.html.tmpl' => [
+  'original_bug_id', 
+  'duplicate_bug_id', 
+],
+
+'bug/process/midair.html.tmpl' => [
+  'bug_id', 
+],
+
+'bug/process/next.html.tmpl' => [
+  'bug.bug_id', 
+],
+
+'bug/process/results.html.tmpl' => [
+  'title.$type', 
+  'id', 
+],
+
+'bug/process/verify-new-product.html.tmpl' => [
+  'form.product', # 
+],
+
+'bug/process/bugmail.html.tmpl' => [
+  'description', 
+  'name', # Email 
+],
+
+'bug/create/comment.txt.tmpl' => [
+  'form.comment', 
+],
+
+'bug/create/create.html.tmpl' => [
+  'default.bug_status', #
+  'g.bit',
+  'g.description',
+  'sel.name',
+  'sel.description',
+],
+
+'bug/create/create-guided.html.tmpl' => [
+  'matches.0', 
+  'tablecolour',
+  'product', #
+  'buildid',
+  'sel', 
+],
+
+'bug/activity/show.html.tmpl' => [
+  'bug_id', 
+],
+
+'bug/activity/table.html.tmpl' => [
+  'operation.who', # Email
+  'change.attachid', 
+  'change.field', 
+],
+
+'attachment/create.html.tmpl' => [
+  'bugid', 
+  'attachment.id', 
+],
+
+'attachment/created.html.tmpl' => [
+  'attachid', 
+  'bugid', 
+  'contenttype', 
+],
+
+'attachment/edit.html.tmpl' => [
+  'attachid', 
+  'bugid', 
+  'a', 
+],
+
+'attachment/list.html.tmpl' => [
+  'attachment.attachid', 
+  'FOR flag = attachment.flags', # Bug? No FOR directive
+  'flag.type.name', 
+  'flag.status',
+  'flag.requestee.nick', # Email
+  'show_attachment_flags ? 4 : 3',
+  'bugid',
+],
+
+'attachment/show-multiple.html.tmpl' => [
+  'a.attachid', 
+],
+
+'attachment/updated.html.tmpl' => [
+  'attachid', 
+  'bugid', 
+],
+
+'admin/products/groupcontrol/confirm-edit.html.tmpl' => [
+  'group.count', 
+],
+
+'admin/products/groupcontrol/edit.html.tmpl' => [
+  'filt_product', 
+  'group.bugcount', 
+  'group.id', 
+  'const.CONTROLMAPNA', 
+  'const.CONTROLMAPSHOWN', 
+  'const.CONTROLMAPDEFAULT', 
+  'const.CONTROLMAPMANDATORY', 
+],
+
+'admin/flag-type/confirm-delete.html.tmpl' => [
+  'flag_count', 
+  'name', #
+  'flag_type.id', 
+],
+
+'admin/flag-type/edit.html.tmpl' => [
+  'action', 
+  'type.id', 
+  'type.target_type', 
+  'category', #
+  'item', #
+  'type.sortkey || 1',
+  '(last_action == "enter" || last_action == "copy") ? "Create" : "Save Changes"',
+],
+
+'admin/flag-type/list.html.tmpl' => [
+  'type.is_active ? "active" : "inactive"', 
+  'type.id', 
+  'type.flag_count', 
+],
+
+'account/login.html.tmpl' => [
+  'target', 
+],
+
+'account/prefs/account.html.tmpl' => [
+  'login_change_date', #
+],
+
+'account/prefs/email.html.tmpl' => [
+  'watchedusers', # Email
+  'useqacontact ? \'5\' : \'4\'', 
+  'role', 
+  'reason.name', 
+  'reason.description',
+],
+
+'account/prefs/permissions.html.tmpl' => [
+  'bit_description.name', 
+  'bit_description.desc', 
+],
+
+'account/prefs/prefs.html.tmpl' => [
+  'tab.name', 
+  'tab.description', 
+  'current_tab.name', 
+  'current_tab.description', 
+  'current_tab.description FILTER lower',
+],
+
+);
+
+# Should filter reports/report.html.tmpl:130 $format
index de0ca0be7fb52feca4f3dcf157af0a35bf77ef23..e79f7820d4a188f9a4bee4a8e94ccb6e232da811 100644 (file)
@@ -41,7 +41,7 @@
   <tr>
     <th align="right" valign="top">
       <a href="[% target %]?product=[% p FILTER url_quote %]
-                                       [%- "&amp;format=$format" IF format %]">
+            [% IF format %]&amp;format=[% format FILTER url_quote %][% END %]">
       [% p FILTER html %]</a>:
     </th>
 
index b35bbb0642dc48550129e90d5b1b6d5c38beffdb..92836f4db0cbf1a9f4cf8c03609ecc29b6a9a987 100644 (file)
@@ -86,7 +86,7 @@
 
   [% ELSIF error == "field_type_mismatch" %]
     Cannot seem to handle <code>[% field %]</code>
-    and <code>[% type %]</code> together.
+    and <code>[% type FILTER html %]</code> together.
  
   [% ELSIF error == "gd_not_installed" %]
     Charts will not work without the GD Perl module being installed.
index f968fab200d78217c94adea21febff65a4ac8945..a824c3489cb689c382d3290822a1c276bb2afcb1 100644 (file)
   [% NEXT IF exclude && field.key.search(exclude) %]
   [% IF mform.${field.key}.size > 1 %]
     [% FOREACH mvalue = mform.${field.key} %]
-      <input type="hidden" name="[% field.key %]"
+      <input type="hidden" name="[% field.key FILTER html %]"
              value="[% mvalue | html | html_linebreak %]">
     [% END %]
   [% ELSE %]
-    <input type="hidden" name="[% field.key %]"
+    <input type="hidden" name="[% field.key FILTER html %]"
            value="[% field.value | html | html_linebreak %]">
   [% END %]
 [% END %]
index f6cb321c65743ffec94c919b37ee73d1d5dfe2c2..58cd5690840577fd6cc7c496bb3a22e5d93598de 100644 (file)
@@ -34,7 +34,7 @@
 [%# Display a URL if the calling script or message block has included one. %]
 [% IF url && link %]
   <p>
-    <a href="[% url %]">[% link %]</a>
+    <a href="[% url FILTER html %]">[% link FILTER html %]</a>
   </p>
 [% END %]
 
index fe1d9e223c29158f0666cff81102fda1d0b367f0..934c0511fa98d362e2686ceb0359dcec3a1acb99 100644 (file)
     
   [% ELSIF error == "illegal_date" %]
     [% title = "Your Query Makes No Sense" %]
-    '<tt>[% date %]</tt>' is not a legal date.
+    '<tt>[% date FILTER html %]</tt>' is not a legal date.
     
   [% ELSIF error == "illegal_email_address" %]
     [% title = "Invalid Email Address" %]
     in your browser. To help us fix this limitation, add your comments to 
     <a href="http://bugzilla.mozilla.org/show_bug.cgi?id=70907">bug 70907</a>.
 
+  [% ELSIF error == "invalid_changedsince" %]
+    [% title = "Invalid 'Changed Since'" %]
+    The 'changed since' value, '[% changedsince FILTER html %]', must be an
+    integer >= 0.
+
   [% ELSIF error == "invalid_content_type" %]
     [% title = "Invalid Content-Type" %]
     The content type <em>[% contenttype FILTER html %]</em> is invalid.
   [% ELSIF error == "missing_email_type" %]
     [% title = "Your Query Makes No Sense" %]
     You must specify one or more fields in which to search for
-    <tt>[% email %]</tt>.
+    <tt>[% email FILTER html %]</tt>.
     
   [% ELSIF error == "missing_query" %]
     [% title = "Missing Query" %]
index 097a886bbf49ca47d4e6f37644da58257e905e43..7730bf78c02d036c18f9620159c7ffe6ad81c20f 100644 (file)
@@ -36,7 +36,7 @@
 [% field_descs.qa_contact_realname  = "QA Contact Realname" %]
 
 <form action="colchange.cgi">
-  <input type="hidden" name="rememberedquery" value="[% buffer %]">
+  <input type="hidden" name="rememberedquery" value="[% buffer FILTER html %]">
   [% FOREACH column = masterlist %]
     <input type="checkbox" id="[% column %]" name="column_[% column %]" 
       [% "checked='checked'" IF lsearch(collist, column) != -1 %]>
@@ -65,7 +65,7 @@
 </form>
 
 <form action="colchange.cgi">
-  <input type="hidden" name="rememberedquery" value="[% buffer %]">
+  <input type="hidden" name="rememberedquery" value="[% buffer FILTER html %]">
   <input type="hidden" name="resetit" value="1">
   <input type="submit" value="Reset to Bugzilla default">
 </form>
index 9b9f099d38771841293f38d2f4593a47cb01f94d..91a5584cfd688791f79699f3d4dc846d627ae543 100644 (file)
@@ -95,7 +95,7 @@
   <p>
     <a href="query.cgi">Query Page</a>
     &nbsp;&nbsp;<a href="enter_bug.cgi">Enter New Bug</a>
-    <a href="query.cgi?[% urlquerypart %]">Edit this query</a>
+    <a href="query.cgi?[% urlquerypart FILTER html %]">Edit this query</a>
   </p>
 
 [% ELSIF bugs.size == 1 %]
     <input type="hidden" name="buglist" value="[% buglist %]">
     <input type="submit" value="Long Format">
     &nbsp;&nbsp;
-    <a href="buglist.cgi?[% urlquerypart %]&amp;ctype=csv">CSV</a> &nbsp;&nbsp;
-    <a href="colchange.cgi?[% urlquerypart %]">Change Columns</a> &nbsp;&nbsp;
+    <a href="buglist.cgi?
+             [% urlquerypart FILTER html %]&amp;ctype=csv">CSV</a> &nbsp;&nbsp;
+    <a href="colchange.cgi?
+                [% urlquerypart FILTER html %]">Change Columns</a> &nbsp;&nbsp;
 
     [% IF bugs.size > 1 && caneditbugs && !dotweak %]
-      <a href="buglist.cgi?[% urlquerypart %]
+      <a href="buglist.cgi?[% urlquerypart FILTER html %]
         [%- "&order=$qorder" FILTER html IF order %]&amp;tweak=1">Change Several 
         Bugs at Once</a>
       &nbsp;&nbsp;
       <a href="mailto:[% bugowners %]">Send Mail to Bug Owners</a> &nbsp;&nbsp;
     [% END %]
 
-    <a href="query.cgi?[% urlquerypart %]">Edit this Query</a> &nbsp;&nbsp;
+    <a href="query.cgi?
+               [% urlquerypart FILTER html %]">Edit this Query</a> &nbsp;&nbsp;
 
   </form>
 
index 8a5d3ac57721ee4719078023b272d0f8d52f7b4a..53eb52b2d896a3ab32ee3a847f14ed13e836ed64 100644 (file)
@@ -82,7 +82,8 @@
 
     <tr align="left">
       <th colspan="[% splitheader ? 2 : 1 %]">
-        <a href="buglist.cgi?[% urlquerypart %]&amp;order=bugs.bug_id">ID</a>
+        <a href="buglist.cgi?
+                  [% urlquerypart FILTER html %]&amp;order=bugs.bug_id">ID</a>
       </th>
 
       [% IF splitheader %]
 
 [% BLOCK columnheader %]
   <th colspan="[% splitheader ? 2 : 1 %]">
-    <a href="buglist.cgi?[% urlquerypart %]&amp;order=
+    <a href="buglist.cgi?[% urlquerypart FILTER html %]&amp;order=
       [% column.name FILTER url_quote FILTER html %]
       [% ",$qorder" FILTER html IF order %]">
         [%- abbrev.$id.title || field_descs.$id || column.title -%]</a>
index ce4d070017fe8d00dc44019b3f30a346efe3656a..a522c4db7ca0efc93809f445eeeb8524add42512 100644 (file)
@@ -58,7 +58,7 @@
 <h3><a name="params">Change Parameters</a></h3>
 
 <form method="get" action="duplicates.cgi">
-  <input type="hidden" name="sortby" value="[% sortby %]">
+  <input type="hidden" name="sortby" value="[% sortby FILTER html %]">
   <input type="hidden" name="reverse" value="[% reverse %]">
   <input type="hidden" name="bug_id" value="[% bug_ids_string %]">
   <table>
index 0b80bdb26a7b447ce3bf6bb4c97d226ad09ebe9e..efc5dd0b2dfb372caee3409f920a57944d329342 100644 (file)
@@ -330,7 +330,7 @@ function selectProduct(f) {
 [% PROCESS "global/field-descs.none.tmpl" %]
 
 [%# If we resubmit to ourselves, we need to know if we are using a format. %]
-<input type="hidden" name="query_format" value="[% format %]">
+<input type="hidden" name="query_format" value="[% format FILTER html %]">
 
 [%# *** Summary *** %]