From d3e4c2c4b5bf900ac1c32cbb8469ef718e14c807 Mon Sep 17 00:00:00 2001 From: Steve Pulec Date: Tue, 3 Nov 2015 09:25:47 -0500 Subject: [PATCH] Add ability for specific backends to enable template escaping. Closes #441. --- moto/core/responses.py | 14 +++++++++++--- moto/ec2/responses/__init__.py | 4 ++++ moto/ec2/responses/tags.py | 3 --- moto/glacier/responses.py | 1 + moto/s3/responses.py | 1 + tests/test_ec2/test_elastic_block_store.py | 10 ++++++++++ 6 files changed, 27 insertions(+), 6 deletions(-) diff --git a/moto/core/responses.py b/moto/core/responses.py index bd54cf01c..5fda815e7 100644 --- a/moto/core/responses.py +++ b/moto/core/responses.py @@ -63,8 +63,16 @@ class DynamicDictLoader(DictLoader): class _TemplateEnvironmentMixin(object): - loader = DynamicDictLoader({}) - environment = Environment(loader=loader) + + def __init__(self): + super(_TemplateEnvironmentMixin, self).__init__() + self.loader = DynamicDictLoader({}) + self.environment = Environment(loader=self.loader, autoescape=self.should_autoescape) + + @property + def should_autoescape(self): + # Allow for subclass to overwrite + return False def contains_template(self, template_id): return self.loader.contains(template_id) @@ -73,7 +81,7 @@ class _TemplateEnvironmentMixin(object): template_id = id(source) if not self.contains_template(template_id): self.loader.update({template_id: source}) - self.environment = Environment(loader=self.loader) + self.environment = Environment(loader=self.loader, autoescape=self.should_autoescape) return self.environment.get_template(template_id) diff --git a/moto/ec2/responses/__init__.py b/moto/ec2/responses/__init__.py index f051a7ca7..e51992e41 100644 --- a/moto/ec2/responses/__init__.py +++ b/moto/ec2/responses/__init__.py @@ -66,3 +66,7 @@ class EC2Response( def ec2_backend(self): from moto.ec2.models import ec2_backends return ec2_backends[self.region] + + @property + def should_autoescape(self): + return True diff --git a/moto/ec2/responses/tags.py b/moto/ec2/responses/tags.py index effb4faf9..4a62261d5 100644 --- a/moto/ec2/responses/tags.py +++ b/moto/ec2/responses/tags.py @@ -1,6 +1,5 @@ from __future__ import unicode_literals -from xml.sax.saxutils import escape from moto.core.responses import BaseResponse from moto.ec2.models import validate_resource_ids from moto.ec2.utils import sequence_from_querystring, tags_from_query_string, filters_from_querystring @@ -26,8 +25,6 @@ class TagResponse(BaseResponse): def describe_tags(self): filters = filters_from_querystring(querystring_dict=self.querystring) tags = self.ec2_backend.describe_tags(filters=filters) - for tag in tags: - tag['value'] = escape(tag['value']) template = self.response_template(DESCRIBE_RESPONSE) return template.render(tags=tags) diff --git a/moto/glacier/responses.py b/moto/glacier/responses.py index 37cbdc4c9..eac9b94c6 100644 --- a/moto/glacier/responses.py +++ b/moto/glacier/responses.py @@ -11,6 +11,7 @@ from .utils import region_from_glacier_url, vault_from_glacier_url class GlacierResponse(_TemplateEnvironmentMixin): def __init__(self, backend): + super(GlacierResponse, self).__init__() self.backend = backend @classmethod diff --git a/moto/s3/responses.py b/moto/s3/responses.py index 687b0464f..42ad92715 100644 --- a/moto/s3/responses.py +++ b/moto/s3/responses.py @@ -24,6 +24,7 @@ def parse_key_name(pth): class ResponseObject(_TemplateEnvironmentMixin): def __init__(self, backend, bucket_name_from_url, parse_key_name, is_delete_keys=None): + super(ResponseObject, self).__init__() self.backend = backend self.bucket_name_from_url = bucket_name_from_url self.parse_key_name = parse_key_name diff --git a/tests/test_ec2/test_elastic_block_store.py b/tests/test_ec2/test_elastic_block_store.py index 0fd5d6bc2..b2308fe04 100644 --- a/tests/test_ec2/test_elastic_block_store.py +++ b/tests/test_ec2/test_elastic_block_store.py @@ -236,3 +236,13 @@ def test_modify_attribute_blockDeviceMapping(): instance = ec2_backends[conn.region.name].get_instance(instance.id) instance.block_device_mapping.should.have.key('/dev/sda1') instance.block_device_mapping['/dev/sda1'].delete_on_termination.should.be(True) + + +@mock_ec2 +def test_volume_tag_escaping(): + conn = boto.connect_ec2('the_key', 'the_secret') + vol = conn.create_volume(10, 'us-east-1a') + snapshot = conn.create_snapshot(vol.id, 'Desc') + snapshot.add_tags({'key': ''}) + + dict(conn.get_all_snapshots()[0].tags).should.equal({'key': ''})