Parent: [b4fa50] (diff)

Download this file

patches.py    117 lines (100 with data), 5.1 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
import re
import webob
import tg.decorators
from decorator import decorator
from pylons import request
import mock
import simplejson
from allura.lib import helpers as h
def apply():
old_lookup_template_engine = tg.decorators.Decoration.lookup_template_engine
@h.monkeypatch(tg.decorators.Decoration)
def lookup_template_engine(self, request):
'''Wrapper to handle totally borked-up HTTP-ACCEPT headers'''
try:
return old_lookup_template_engine(self, request)
except:
pass
environ = dict(request.environ, HTTP_ACCEPT='*/*')
request = webob.Request(environ)
return old_lookup_template_engine(self, request)
@h.monkeypatch(tg, tg.decorators)
def override_template(controller, template):
'''Copy-pasted patch to allow multiple colons in a template spec'''
if hasattr(controller, 'decoration'):
decoration = controller.decoration
else:
return
if hasattr(decoration, 'engines'):
engines = decoration.engines
else:
return
for content_type, content_engine in engines.iteritems():
template = template.split(':', 1)
template.extend(content_engine[2:])
try:
override_mapping = request._override_mapping
except AttributeError:
override_mapping = request._override_mapping = {}
override_mapping[controller.im_func] = {content_type: template}
@h.monkeypatch(tg, tg.decorators)
@decorator
def without_trailing_slash(func, *args, **kwargs):
'''Monkey-patched to use 301 redirects for SEO'''
response_type = getattr(request, 'response_type', None)
if (request.method == 'GET' and request.path.endswith('/')
and not response_type and len(request.params)==0):
raise webob.exc.HTTPMovedPermanently(location=request.url[:-1])
return func(*args, **kwargs)
@h.monkeypatch(tg, tg.decorators)
@decorator
def with_trailing_slash(func, *args, **kwargs):
'''Monkey-patched to use 301 redirects for SEO'''
response_type = getattr(request, 'response_type', None)
if (request.method == 'GET' and not(request.path.endswith('/'))
and not response_type and len(request.params)==0):
raise webob.exc.HTTPMovedPermanently(location=request.url+'/')
return func(*args, **kwargs)
# http://blog.watchfire.com/wfblog/2011/10/json-based-xss-exploitation.html
# change < to its unicode escape when rendering JSON out of turbogears
# This is to avoid IE9 and earlier, which don't know the json content type
# and may attempt to render JSON data as HTML if the URL ends in .html
original_tg_jsonify_GenericJSON_encode = tg.jsonify.GenericJSON.encode
escape_pattern_with_lt = re.compile(simplejson.encoder.ESCAPE.pattern.rstrip(']') + '<' + ']')
@h.monkeypatch(tg.jsonify.GenericJSON)
def encode(self, o):
# ensure_ascii=False forces encode_basestring() to be called instead of
# encode_basestring_ascii() and encode_basestring_ascii may likely be c-compiled
# and thus not monkeypatchable
with h.push_config(self, ensure_ascii=False), \
h.push_config(simplejson.encoder, ESCAPE=escape_pattern_with_lt), \
mock.patch.dict(simplejson.encoder.ESCAPE_DCT, {'<': r'\u003C'}):
return original_tg_jsonify_GenericJSON_encode(self, o)
# must be saved outside the newrelic() method so that multiple newrelic()
# calls (e.g. during tests) don't cause the patching to get applied to itself
# over and over
old_controller_call = tg.controllers.DecoratedController._call
def newrelic():
@h.monkeypatch(tg.controllers.DecoratedController,
tg.controllers.decoratedcontroller.DecoratedController)
def _call(self, controller, *args, **kwargs):
'''Set NewRelic transaction name to actual controller name'''
import newrelic.agent
newrelic.agent.set_transaction_name(newrelic.agent.callable_name(controller))
return old_controller_call(self, controller, *args, **kwargs)