blob: b453e18a95b5691161c93101e5892fd0e6f6e95f [file] [log] [blame]
Brian Silverman70325d62015-09-20 17:00:43 -04001// Copyright (c) 2007, Google Inc.
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met:
7//
8// * Redistributions of source code must retain the above copyright
9// notice, this list of conditions and the following disclaimer.
10// * Redistributions in binary form must reproduce the above
11// copyright notice, this list of conditions and the following disclaimer
12// in the documentation and/or other materials provided with the
13// distribution.
14// * Neither the name of Google Inc. nor the names of its
15// contributors may be used to endorse or promote products derived from
16// this software without specific prior written permission.
17//
18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29//
30// ---
31// Author: csilvers@google.com (Craig Silverstein)
32//
33// These are used by template.cc and when registering new modifiers.
34// (Or more exactly, registering new modifier/value pairs.)
35// They are not intended for any other users.
36//
37// If you do find yourself needing to use them directly, please email
38// template-users.
39//
40// Known outside-template users of this class:
41// template/bidi/bidi_modifiers_test.cc
42//
43// These routines are implemented in template_modifiers.cc.
44
45#ifndef TEMPLATE_TEMPLATE_MODIFIERS_INTERNAL_H_
46#define TEMPLATE_TEMPLATE_MODIFIERS_INTERNAL_H_
47
48#include <config.h>
49#include <sys/types.h> // for size_t
50#include <string.h> // for strchr
51#include <string>
52#include <vector>
53#include <ctemplate/template_modifiers.h> // for null_modifier
54
55// Annoying stuff for windows -- make sure clients (in this case
56// unittests) can import the class definitions and variables.
57#ifndef CTEMPLATE_DLL_DECL
58# ifdef _MSC_VER
59# define CTEMPLATE_DLL_DECL __declspec(dllimport)
60# else
61# define CTEMPLATE_DLL_DECL /* should be the empty string for non-windows */
62# endif
63#endif
64
65using std::string;
66using std::vector;
67
68namespace ctemplate_htmlparser {
69class HtmlParser;
70}
71
72namespace ctemplate {
73
74class TemplateModifier;
75
76// A Modifier belongs to an XssClass which determines whether
77// it is an XSS safe addition to a modifier chain or not. This
78// is used by the Auto-Escape mode when determining how to handle
79// extra modifiers provided in template. For example, :j is a safe
80// addition to :h because they are both in the same class (XSS_WEB_STANDARD).
81//
82// XssClass is not exposed in any API and cannot be set in custom
83// modifiers, it is for internal use only (for Auto-Escape). We currently
84// have only three classes.
85//
86// XSS_UNUSED: not used.
87// XSS_WEB_STANDARD: All the curent built-in escaping modifiers.
88// XSS_UNIQUE: Set for all custom modifiers added via AddModifier()
89// and may need to be escaped.
90// XSS_SAFE: Set for all custom modifiers added via AddXssSafeModifier()
91// that are considered to produce safe output and hence
92// do not need further escaping. Also includes the :none modifier.
93enum XssClass {
94 XSS_UNUSED,
95 XSS_WEB_STANDARD,
96 XSS_UNIQUE,
97 XSS_SAFE,
98};
99
100// TODO(csilvers): collapse this into the TemplateModifier class?
101struct ModifierInfo {
102 // longname should end in an '=' iff the modifier takes a value
103 // (same as in getopt(3)).
104 // To specialize -- add a modifier that applies only when we see the name
105 // with a particular value -- specify longname like so: "longname=value".
106 // (See example in the comment-doc below, for AddModifier.)
107 // sn can be '\0' if there is no associated shortname.
108 // m should be NULL *only if* default-registering a user-defined longname
109 // that the user neglected to register themselves. In this case, we
110 // use the null modifier as the actual modifier.
111 // xss_class indicates an equivalence class this modifier is
112 // in, such that any other modifier in the class could be applied
113 // after this modifier without affecting its XSS-safety. If in
114 // doubt, say XSS_UNIQUE, which is the most conservative choice.
115 ModifierInfo(string ln, char sn, XssClass xc, const TemplateModifier* m)
116 : long_name(ln), short_name(sn),
117 modval_required(strchr(ln.c_str(), '=') != NULL),
118 is_registered(m != NULL), xss_class(xc),
119 modifier(m ? m : &null_modifier) { }
120 string long_name;
121 char short_name;
122 bool modval_required; // true iff ln has an '=' in it
123 bool is_registered; // true for built-in and AddModifier mods
124 XssClass xss_class;
125 const TemplateModifier* modifier;
126};
127
128// An escaping directive is completely defined by the escaping function to use
129// (ModifierInfo.modifier) as well as the optional value it may require. This
130// structure is a small wrapper on ModifierInfo to convey that needed value.
131// Note: The given value pointer must be valid for the life of the struct.
132// Also, value is not null-terminated.
133struct ModifierAndValue {
134 ModifierAndValue(const ModifierInfo* mod_info, const char* val,
135 size_t val_len)
136 : modifier_info(mod_info), value(val), value_len(val_len) { }
137 const ModifierInfo* modifier_info;
138 const char* value;
139 size_t value_len;
140};
141
142// Returns whether or not candidate can be safely (w.r.t XSS)
143// used in lieu of our ModifierInfo. This is true iff:
144// 1. Both have the same modifier function OR
145// 2. Candidate's modifier function is in our ModifierInfo's
146// list (vector) of safe alternative modifier functions.
147// Note that this function is not commutative therefore
148// IsSafeXSSAlternative(a, b) may not be equal to IsSafeXSSAlternative(b, a).
149extern CTEMPLATE_DLL_DECL
150bool IsSafeXSSAlternative(const ModifierInfo& our,
151 const ModifierInfo& candidate);
152
153// modname is the name of the modifier (shortname or longname).
154// value is the modifier-value (empty string if there is no modval).
155// Returns a pointer into g_modifiers, or NULL if not found.
156extern CTEMPLATE_DLL_DECL
157const ModifierInfo* FindModifier(const char* modname, size_t modname_len,
158 const char* modval, size_t modval_len);
159
160
161// Convenience function to dump the (zero or more) modifiers (and values)
162// in the format:
163// :<modifier1>[=<val1>]<seperator>[:<modifier2>][=<val2>]...
164// If the modifier does not have a short_name, we print its long_name instead.
165// The separator may be an empty string.
166extern CTEMPLATE_DLL_DECL
167string PrettyPrintModifiers(
168 const vector<const ModifierAndValue*>& modvals,
169 const string& separator);
170
171extern CTEMPLATE_DLL_DECL
172string PrettyPrintOneModifier(const ModifierAndValue& modval);
173
174// Returns the appropriate escaping directives to escape content in an
175// HTML or Javascript context. HTML and Javascript contexts exercise
176// the same parser APIs and hence are combined here.
177// If an error occurs, we return NULL and append and error to error_msg.
178// The htmlparser and error_msg arguments must be non-NULL.
179// Currently, on success, we always return a vector of length 1, meaning
180// we never need to chain escaping directives. However, this is subject
181// to change.
182extern CTEMPLATE_DLL_DECL
183vector<const ModifierAndValue*> GetModifierForHtmlJs(
184 ctemplate_htmlparser::HtmlParser* htmlparser, string* error_msg);
185
186// Returns the appropriate escaping directives to escape content
187// in a CSS context.
188// Currently always returns cleanse_css and hence does not require the
189// parser nor can it fail. This will change once the parser is able to
190// distinguish between different CSS contexts, in particular CSS properties
191// that take URLs, which require a different escaping function (non-existent).
192extern CTEMPLATE_DLL_DECL
193vector<const ModifierAndValue*> GetModifierForCss(
194 ctemplate_htmlparser::HtmlParser* htmlparser, string* error_msg);
195
196// Returns the appropriate escaping directives to escape content
197// in an XML context.
198// Currently always returns xml_escape and hence does not require the
199// parser nor can it fail. This may change once the parser can parse XML.
200extern CTEMPLATE_DLL_DECL
201vector<const ModifierAndValue*> GetModifierForXml(
202 ctemplate_htmlparser::HtmlParser* htmlparser, string* error_msg);
203
204// Returns the appropriate escaping directives to escape content
205// in a JSON context.
206// Currently always returns javascript_escape and hence does not require the
207// parser nor can it fail. This may change once the parser can parse
208// and distinguish different contexts within JSON.
209extern CTEMPLATE_DLL_DECL
210vector<const ModifierAndValue*> GetModifierForJson(
211 ctemplate_htmlparser::HtmlParser* htmlparser, string* error_msg);
212
213// Return the default escaping directives to escape content for the given
214// context. These methods are useful when the caller does not have
215// access to a parser or when the parsed failed to parse.
216
217// GetDefaultModifierForHtml
218// GetDefaultModifierForJs
219// GetDefaultModifierForCss
220// GetDefaultModifierForXxml
221// GetDefaultModifierForJson
222// These functions are different from the GetModifierForXXX functions
223// in that they do not take a parser and cannot fail. They simply
224// return the most common escaping directive for the context they refer to.
225//
226// Some of these contexts (currently HTML and Javascript) have more than
227// one escaping directive associated with them and so we usually rely on
228// the current state of the parser to determine which directive to chose.
229// However, in some cases, the parser may fail to parse a given input
230// and so we may want to select the most likely escaping directive that
231// applies to the given context. Hence we use these functions instead of
232// the corresponding GetModifierForXXX ones.
233extern CTEMPLATE_DLL_DECL
234std::vector<const ModifierAndValue*> GetDefaultModifierForHtml();
235extern CTEMPLATE_DLL_DECL
236std::vector<const ModifierAndValue*> GetDefaultModifierForJs();
237extern CTEMPLATE_DLL_DECL
238std::vector<const ModifierAndValue*> GetDefaultModifierForCss();
239extern CTEMPLATE_DLL_DECL
240std::vector<const ModifierAndValue*> GetDefaultModifierForXml();
241extern CTEMPLATE_DLL_DECL
242std::vector<const ModifierAndValue*> GetDefaultModifierForJson();
243
244}
245
246#endif // TEMPLATE_TEMPLATE_MODIFIERS_INTERNAL_H_