|
a/Allura/allura/lib/patches.py |
|
b/Allura/allura/lib/patches.py |
|
... |
|
... |
13 |
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
13 |
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
14 |
# KIND, either express or implied. See the License for the
|
14 |
# KIND, either express or implied. See the License for the
|
15 |
# specific language governing permissions and limitations
|
15 |
# specific language governing permissions and limitations
|
16 |
# under the License.
|
16 |
# under the License.
|
17 |
|
17 |
|
|
|
18 |
import re
|
|
|
19 |
|
18 |
import webob
|
20 |
import webob
|
19 |
import tg.decorators
|
21 |
import tg.decorators
|
20 |
from decorator import decorator
|
22 |
from decorator import decorator
|
21 |
from pylons import request
|
23 |
from pylons import request
|
|
|
24 |
import mock
|
|
|
25 |
import simplejson
|
22 |
|
26 |
|
23 |
from allura.lib import helpers as h
|
27 |
from allura.lib import helpers as h
|
24 |
|
28 |
|
25 |
def apply():
|
29 |
def apply():
|
26 |
old_lookup_template_engine = tg.decorators.Decoration.lookup_template_engine
|
30 |
old_lookup_template_engine = tg.decorators.Decoration.lookup_template_engine
|
|
... |
|
... |
76 |
and not response_type and len(request.params)==0):
|
80 |
and not response_type and len(request.params)==0):
|
77 |
raise webob.exc.HTTPMovedPermanently(location=request.url+'/')
|
81 |
raise webob.exc.HTTPMovedPermanently(location=request.url+'/')
|
78 |
return func(*args, **kwargs)
|
82 |
return func(*args, **kwargs)
|
79 |
|
83 |
|
80 |
|
84 |
|
|
|
85 |
# http://blog.watchfire.com/wfblog/2011/10/json-based-xss-exploitation.html
|
|
|
86 |
# change < to its unicode escape when rendering JSON out of turbogears
|
|
|
87 |
# This is to avoid IE9 and earlier, which don't know the json content type
|
|
|
88 |
# and may attempt to render JSON data as HTML if the URL ends in .html
|
|
|
89 |
|
|
|
90 |
original_tg_jsonify_GenericJSON_encode = tg.jsonify.GenericJSON.encode
|
|
|
91 |
escape_pattern_with_lt = re.compile(simplejson.encoder.ESCAPE.pattern.rstrip(']') + '<' + ']')
|
|
|
92 |
|
|
|
93 |
@h.monkeypatch(tg.jsonify.GenericJSON)
|
|
|
94 |
def encode(self, o):
|
|
|
95 |
# ensure_ascii=False forces encode_basestring() to be called instead of
|
|
|
96 |
# encode_basestring_ascii() and encode_basestring_ascii may likely be c-compiled
|
|
|
97 |
# and thus not monkeypatchable
|
|
|
98 |
with h.push_config(self, ensure_ascii=False), \
|
|
|
99 |
h.push_config(simplejson.encoder, ESCAPE=escape_pattern_with_lt), \
|
|
|
100 |
mock.patch.dict(simplejson.encoder.ESCAPE_DCT, {'<': r'\u003C'}):
|
|
|
101 |
return original_tg_jsonify_GenericJSON_encode(self, o)
|
|
|
102 |
|
|
|
103 |
|
81 |
# must be saved outside the newrelic() method so that multiple newrelic()
|
104 |
# must be saved outside the newrelic() method so that multiple newrelic()
|
82 |
# calls (e.g. during tests) don't cause the patching to get applied to itself
|
105 |
# calls (e.g. during tests) don't cause the patching to get applied to itself
|
83 |
# over and over
|
106 |
# over and over
|
84 |
old_controller_call = tg.controllers.DecoratedController._call
|
107 |
old_controller_call = tg.controllers.DecoratedController._call
|
85 |
|
108 |
|