# Copyright 2010 Google Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish, dis-
# tribute, sublicense, and/or sell copies of the Software, and to permit
# persons to whom the Software is furnished to do so, subject to the fol-
# lowing conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.

import urllib
import xml.sax

import boto
from boto import handler
from boto.resultset import ResultSet
from boto.exception import InvalidAclError
from boto.gs.acl import ACL, CannedACLStrings
from boto.gs.acl import SupportedPermissions as GSPermissions
from boto.gs.bucketlistresultset import VersionedBucketListResultSet
from boto.gs.cors import Cors
from boto.gs.key import Key as GSKey
from boto.s3.acl import Policy
from boto.s3.bucket import Bucket as S3Bucket

# constants for http query args
DEF_OBJ_ACL = 'defaultObjectAcl'
STANDARD_ACL = 'acl'
CORS_ARG = 'cors'

class Bucket(S3Bucket):
    """Represents a Google Cloud Storage bucket."""

    VersioningBody = ('<?xml version="1.0" encoding="UTF-8"?>\n'
                      '<VersioningConfiguration><Status>%s</Status>'
                      '</VersioningConfiguration>')
    WebsiteBody = ('<?xml version="1.0" encoding="UTF-8"?>\n'
                   '<WebsiteConfiguration>%s%s</WebsiteConfiguration>')
    WebsiteMainPageFragment = '<MainPageSuffix>%s</MainPageSuffix>'
    WebsiteErrorFragment = '<NotFoundPage>%s</NotFoundPage>'

    def __init__(self, connection=None, name=None, key_class=GSKey):
        super(Bucket, self).__init__(connection, name, key_class)

    def startElement(self, name, attrs, connection):
        return None

    def endElement(self, name, value, connection):
        if name == 'Name':
            self.name = value
        elif name == 'CreationDate':
            self.creation_date = value
        else:
            setattr(self, name, value)

    def get_key(self, key_name, headers=None, version_id=None,
                response_headers=None, generation=None):
        """Returns a Key instance for an object in this bucket.

         Note that this method uses a HEAD request to check for the existence of
         the key.

        :type key_name: string
        :param key_name: The name of the key to retrieve

        :type response_headers: dict
        :param response_headers: A dictionary containing HTTP
            headers/values that will override any headers associated
            with the stored object in the response.  See
            http://goo.gl/06N3b for details.

        :type version_id: string
        :param version_id: Unused in this subclass.

        :type generation: int
        :param generation: A specific generation number to fetch the key at. If
            not specified, the latest generation is fetched.

        :rtype: :class:`boto.gs.key.Key`
        :returns: A Key object from this bucket.
        """
        query_args_l = []
        if generation:
            query_args_l.append('generation=%s' % generation)
        if response_headers:
            for rk, rv in response_headers.iteritems():
                query_args_l.append('%s=%s' % (rk, urllib.quote(rv)))

        key, resp = self._get_key_internal(key_name, headers,
                                           query_args_l=query_args_l)
        return key

    def copy_key(self, new_key_name, src_bucket_name, src_key_name,
                 metadata=None, src_version_id=None, storage_class='STANDARD',
                 preserve_acl=False, encrypt_key=False, headers=None,
                 query_args=None, src_generation=None):
        """Create a new key in the bucket by copying an existing key.

        :type new_key_name: string
        :param new_key_name: The name of the new key

        :type src_bucket_name: string
        :param src_bucket_name: The name of the source bucket

        :type src_key_name: string
        :param src_key_name: The name of the source key

        :type src_generation: int
        :param src_generation: The generation number of the source key to copy.
            If not specified, the latest generation is copied.

        :type metadata: dict
        :param metadata: Metadata to be associated with new key.  If
            metadata is supplied, it will replace the metadata of the
            source key being copied.  If no metadata is supplied, the
            source key's metadata will be copied to the new key.

        :type version_id: string
        :param version_id: Unused in this subclass.

        :type storage_class: string
        :param storage_class: The storage class of the new key.  By
            default, the new key will use the standard storage class.
            Possible values are: STANDARD | DURABLE_REDUCED_AVAILABILITY

        :type preserve_acl: bool
        :param preserve_acl: If True, the ACL from the source key will
            be copied to the destination key.  If False, the
            destination key will have the default ACL.  Note that
            preserving the ACL in the new key object will require two
            additional API calls to GCS, one to retrieve the current
            ACL and one to set that ACL on the new object.  If you
            don't care about the ACL (or if you have a default ACL set
            on the bucket), a value of False will be significantly more
            efficient.

        :type encrypt_key: bool
        :param encrypt_key: Included for compatibility with S3. This argument is
            ignored.

        :type headers: dict
        :param headers: A dictionary of header name/value pairs.

        :type query_args: string
        :param query_args: A string of additional querystring arguments
            to append to the request

        :rtype: :class:`boto.gs.key.Key`
        :returns: An instance of the newly created key object
        """
        if src_generation:
            headers = headers or {}
            headers['x-goog-copy-source-generation'] = str(src_generation)
        return super(Bucket, self).copy_key(
            new_key_name, src_bucket_name, src_key_name, metadata=metadata,
            storage_class=storage_class, preserve_acl=preserve_acl,
            encrypt_key=encrypt_key, headers=headers, query_args=query_args)

    def list_versions(self, prefix='', delimiter='', marker='',
                      generation_marker='', headers=None):
        """
        List versioned objects within a bucket.  This returns an
        instance of an VersionedBucketListResultSet that automatically
        handles all of the result paging, etc. from GCS.  You just need
        to keep iterating until there are no more results.  Called
        with no arguments, this will return an iterator object across
        all keys within the bucket.

        :type prefix: string
        :param prefix: allows you to limit the listing to a particular
            prefix.  For example, if you call the method with
            prefix='/foo/' then the iterator will only cycle through
            the keys that begin with the string '/foo/'.

        :type delimiter: string
        :param delimiter: can be used in conjunction with the prefix
            to allow you to organize and browse your keys
            hierarchically. See:
            https://developers.google.com/storage/docs/reference-headers#delimiter
            for more details.

        :type marker: string
        :param marker: The "marker" of where you are in the result set

        :type generation_marker: string
        :param generation_marker: The "generation marker" of where you are in
            the result set.

        :type headers: dict
        :param headers: A dictionary of header name/value pairs.

        :rtype:
            :class:`boto.gs.bucketlistresultset.VersionedBucketListResultSet`
        :return: an instance of a BucketListResultSet that handles paging, etc.
        """
        return VersionedBucketListResultSet(self, prefix, delimiter,
                                            marker, generation_marker,
                                            headers)

    def delete_key(self, key_name, headers=None, version_id=None,
                   mfa_token=None, generation=None):
        """
        Deletes a key from the bucket.

        :type key_name: string
        :param key_name: The key name to delete

        :type headers: dict
        :param headers: A dictionary of header name/value pairs.

        :type version_id: string
        :param version_id: Unused in this subclass.

        :type mfa_token: tuple or list of strings
        :param mfa_token: Unused in this subclass.

        :type generation: int
        :param generation: The generation number of the key to delete. If not
            specified, the latest generation number will be deleted.

        :rtype: :class:`boto.gs.key.Key`
        :returns: A key object holding information on what was
            deleted.
        """
        query_args_l = []
        if generation:
            query_args_l.append('generation=%s' % generation)
        self._delete_key_internal(key_name, headers=headers,
                                  version_id=version_id, mfa_token=mfa_token,
                                  query_args_l=query_args_l)

    def set_acl(self, acl_or_str, key_name='', headers=None, version_id=None,
                generation=None, if_generation=None, if_metageneration=None):
        """Sets or changes a bucket's or key's ACL.

        :type acl_or_str: string or :class:`boto.gs.acl.ACL`
        :param acl_or_str: A canned ACL string (see
            :data:`~.gs.acl.CannedACLStrings`) or an ACL object.

        :type key_name: string
        :param key_name: A key name within the bucket to set the ACL for. If not
            specified, the ACL for the bucket will be set.

        :type headers: dict
        :param headers: Additional headers to set during the request.

        :type version_id: string
        :param version_id: Unused in this subclass.

        :type generation: int
        :param generation: If specified, sets the ACL for a specific generation
            of a versioned object. If not specified, the current version is
            modified.

        :type if_generation: int
        :param if_generation: (optional) If set to a generation number, the acl
            will only be updated if its current generation number is this value.

        :type if_metageneration: int
        :param if_metageneration: (optional) If set to a metageneration number,
            the acl will only be updated if its current metageneration number is
            this value.
        """
        if isinstance(acl_or_str, Policy):
            raise InvalidAclError('Attempt to set S3 Policy on GS ACL')
        elif isinstance(acl_or_str, ACL):
            self.set_xml_acl(acl_or_str.to_xml(), key_name, headers=headers,
                             generation=generation,
                             if_generation=if_generation,
                             if_metageneration=if_metageneration)
        else:
            self.set_canned_acl(acl_or_str, key_name, headers=headers,
                                generation=generation,
                                if_generation=if_generation,
                                if_metageneration=if_metageneration)

    def set_def_acl(self, acl_or_str, headers=None):
        """Sets or changes a bucket's default ACL.

        :type acl_or_str: string or :class:`boto.gs.acl.ACL`
        :param acl_or_str: A canned ACL string (see
            :data:`~.gs.acl.CannedACLStrings`) or an ACL object.

        :type headers: dict
        :param headers: Additional headers to set during the request.
        """
        if isinstance(acl_or_str, Policy):
            raise InvalidAclError('Attempt to set S3 Policy on GS ACL')
        elif isinstance(acl_or_str, ACL):
            self.set_def_xml_acl(acl_or_str.to_xml(), headers=headers)
        else:
            self.set_def_canned_acl(acl_or_str, headers=headers)

    def _get_xml_acl_helper(self, key_name, headers, query_args):
        """Provides common functionality for get_xml_acl and _get_acl_helper."""
        response = self.connection.make_request('GET', self.name, key_name,
                                                query_args=query_args,
                                                headers=headers)
        body = response.read()
        if response.status != 200:
            raise self.connection.provider.storage_response_error(
                response.status, response.reason, body)
        return body

    def _get_acl_helper(self, key_name, headers, query_args):
        """Provides common functionality for get_acl and get_def_acl."""
        body = self._get_xml_acl_helper(key_name, headers, query_args)
        acl = ACL(self)
        h = handler.XmlHandler(acl, self)
        xml.sax.parseString(body, h)
        return acl

    def get_acl(self, key_name='', headers=None, version_id=None,
                generation=None):
        """Returns the ACL of the bucket or an object in the bucket.

        :param str key_name: The name of the object to get the ACL for. If not
            specified, the ACL for the bucket will be returned.

        :param dict headers: Additional headers to set during the request.

        :type version_id: string
        :param version_id: Unused in this subclass.

        :param int generation: If specified, gets the ACL for a specific
            generation of a versioned object. If not specified, the current
            version is returned. This parameter is only valid when retrieving
            the ACL of an object, not a bucket.

        :rtype: :class:`.gs.acl.ACL`
        """
        query_args = STANDARD_ACL
        if generation:
            query_args += '&generation=%s' % generation
        return self._get_acl_helper(key_name, headers, query_args)

    def get_xml_acl(self, key_name='', headers=None, version_id=None,
                    generation=None):
        """Returns the ACL string of the bucket or an object in the bucket.

        :param str key_name: The name of the object to get the ACL for. If not
            specified, the ACL for the bucket will be returned.

        :param dict headers: Additional headers to set during the request.

        :type version_id: string
        :param version_id: Unused in this subclass.

        :param int generation: If specified, gets the ACL for a specific
            generation of a versioned object. If not specified, the current
            version is returned. This parameter is only valid when retrieving
            the ACL of an object, not a bucket.

        :rtype: str
        """
        query_args = STANDARD_ACL
        if generation:
            query_args += '&generation=%s' % generation
        return self._get_xml_acl_helper(key_name, headers, query_args)

    def get_def_acl(self, headers=None):
        """Returns the bucket's default ACL.

        :param dict headers: Additional headers to set during the request.

        :rtype: :class:`.gs.acl.ACL`
        """
        return self._get_acl_helper('', headers, DEF_OBJ_ACL)

    def _set_acl_helper(self, acl_or_str, key_name, headers, query_args,
                          generation, if_generation, if_metageneration,
                          canned=False):
        """Provides common functionality for set_acl, set_xml_acl,
        set_canned_acl, set_def_acl, set_def_xml_acl, and
        set_def_canned_acl()."""

        headers = headers or {}
        data = ''
        if canned:
            headers[self.connection.provider.acl_header] = acl_or_str
        else:
            data = acl_or_str.encode('UTF-8')

        if generation:
            query_args += '&generation=%s' % generation

        if if_metageneration is not None and if_generation is None:
            raise ValueError("Received if_metageneration argument with no "
                             "if_generation argument. A meta-generation has no "
                             "meaning without a content generation.")
        if not key_name and (if_generation or if_metageneration):
            raise ValueError("Received if_generation or if_metageneration "
                             "parameter while setting the ACL of a bucket.")
        if if_generation is not None:
            headers['x-goog-if-generation-match'] = str(if_generation)
        if if_metageneration is not None:
            headers['x-goog-if-metageneration-match'] = str(if_metageneration)

        response = self.connection.make_request('PUT', self.name, key_name,
                data=data, headers=headers, query_args=query_args)
        body = response.read()
        if response.status != 200:
            raise self.connection.provider.storage_response_error(
                response.status, response.reason, body)

    def set_xml_acl(self, acl_str, key_name='', headers=None, version_id=None,
                    query_args='acl', generation=None, if_generation=None,
                    if_metageneration=None):
        """Sets a bucket's or objects's ACL to an XML string.

        :type acl_str: string
        :param acl_str: A string containing the ACL XML.

        :type key_name: string
        :param key_name: A key name within the bucket to set the ACL for. If not
            specified, the ACL for the bucket will be set.

        :type headers: dict
        :param headers: Additional headers to set during the request.

        :type version_id: string
        :param version_id: Unused in this subclass.

        :type query_args: str
        :param query_args: The query parameters to pass with the request.

        :type generation: int
        :param generation: If specified, sets the ACL for a specific generation
            of a versioned object. If not specified, the current version is
            modified.

        :type if_generation: int
        :param if_generation: (optional) If set to a generation number, the acl
            will only be updated if its current generation number is this value.

        :type if_metageneration: int
        :param if_metageneration: (optional) If set to a metageneration number,
            the acl will only be updated if its current metageneration number is
            this value.
        """
        return self._set_acl_helper(acl_str, key_name=key_name, headers=headers,
                                    query_args=query_args,
                                    generation=generation,
                                    if_generation=if_generation,
                                    if_metageneration=if_metageneration)

    def set_canned_acl(self, acl_str, key_name='', headers=None,
                       version_id=None, generation=None, if_generation=None,
                       if_metageneration=None):
        """Sets a bucket's or objects's ACL using a predefined (canned) value.

        :type acl_str: string
        :param acl_str: A canned ACL string. See
            :data:`~.gs.acl.CannedACLStrings`.

        :type key_name: string
        :param key_name: A key name within the bucket to set the ACL for. If not
            specified, the ACL for the bucket will be set.

        :type headers: dict
        :param headers: Additional headers to set during the request.

        :type version_id: string
        :param version_id: Unused in this subclass.

        :type generation: int
        :param generation: If specified, sets the ACL for a specific generation
            of a versioned object. If not specified, the current version is
            modified.

        :type if_generation: int
        :param if_generation: (optional) If set to a generation number, the acl
            will only be updated if its current generation number is this value.

        :type if_metageneration: int
        :param if_metageneration: (optional) If set to a metageneration number,
            the acl will only be updated if its current metageneration number is
            this value.
        """
        if acl_str not in CannedACLStrings:
            raise ValueError("Provided canned ACL string (%s) is not valid."
                             % acl_str)
        query_args = STANDARD_ACL
        return self._set_acl_helper(acl_str, key_name, headers, query_args,
                                    generation, if_generation,
                                    if_metageneration, canned=True)

    def set_def_canned_acl(self, acl_str, headers=None):
        """Sets a bucket's default ACL using a predefined (canned) value.

        :type acl_str: string
        :param acl_str: A canned ACL string. See
            :data:`~.gs.acl.CannedACLStrings`.

        :type headers: dict
        :param headers: Additional headers to set during the request.
        """
        if acl_str not in CannedACLStrings:
            raise ValueError("Provided canned ACL string (%s) is not valid."
                             % acl_str)
        query_args = DEF_OBJ_ACL
        return self._set_acl_helper(acl_str, '', headers, query_args,
                                    generation=None, if_generation=None,
                                    if_metageneration=None, canned=True)

    def set_def_xml_acl(self, acl_str, headers=None):
        """Sets a bucket's default ACL to an XML string.

        :type acl_str: string
        :param acl_str: A string containing the ACL XML.

        :type headers: dict
        :param headers: Additional headers to set during the request.
        """
        return self.set_xml_acl(acl_str, '', headers,
                                query_args=DEF_OBJ_ACL)

    def get_cors(self, headers=None):
        """Returns a bucket's CORS XML document.

        :param dict headers: Additional headers to send with the request.
        :rtype: :class:`~.cors.Cors`
        """
        response = self.connection.make_request('GET', self.name,
                                                query_args=CORS_ARG,
                                                headers=headers)
        body = response.read()
        if response.status == 200:
            # Success - parse XML and return Cors object.
            cors = Cors()
            h = handler.XmlHandler(cors, self)
            xml.sax.parseString(body, h)
            return cors
        else:
            raise self.connection.provider.storage_response_error(
                response.status, response.reason, body)

    def set_cors(self, cors, headers=None):
        """Sets a bucket's CORS XML document.

        :param str cors: A string containing the CORS XML.
        :param dict headers: Additional headers to send with the request.
        """
        cors_xml = cors.encode('UTF-8')
        response = self.connection.make_request('PUT', self.name,
                                                data=cors_xml,
                                                query_args=CORS_ARG,
                                                headers=headers)
        body = response.read()
        if response.status != 200:
            raise self.connection.provider.storage_response_error(
                response.status, response.reason, body)

    def get_storage_class(self):
        """
        Returns the StorageClass for the bucket.

        :rtype: str
        :return: The StorageClass for the bucket.
        """
        response = self.connection.make_request('GET', self.name,
                                                query_args='storageClass')
        body = response.read()
        if response.status == 200:
            rs = ResultSet(self)
            h = handler.XmlHandler(rs, self)
            xml.sax.parseString(body, h)
            return rs.StorageClass
        else:
            raise self.connection.provider.storage_response_error(
                response.status, response.reason, body)


    # Method with same signature as boto.s3.bucket.Bucket.add_email_grant(),
    # to allow polymorphic treatment at application layer.
    def add_email_grant(self, permission, email_address,
                        recursive=False, headers=None):
        """
        Convenience method that provides a quick way to add an email grant
        to a bucket. This method retrieves the current ACL, creates a new
        grant based on the parameters passed in, adds that grant to the ACL
        and then PUT's the new ACL back to GCS.

        :type permission: string
        :param permission: The permission being granted. Should be one of:
                           (READ, WRITE, FULL_CONTROL).

        :type email_address: string
        :param email_address: The email address associated with the GS
                              account your are granting the permission to.

        :type recursive: bool
        :param recursive: A boolean value to controls whether the call
                          will apply the grant to all keys within the bucket
                          or not.  The default value is False.  By passing a
                          True value, the call will iterate through all keys
                          in the bucket and apply the same grant to each key.
                          CAUTION: If you have a lot of keys, this could take
                          a long time!
        """
        if permission not in GSPermissions:
            raise self.connection.provider.storage_permissions_error(
                'Unknown Permission: %s' % permission)
        acl = self.get_acl(headers=headers)
        acl.add_email_grant(permission, email_address)
        self.set_acl(acl, headers=headers)
        if recursive:
            for key in self:
                key.add_email_grant(permission, email_address, headers=headers)

    # Method with same signature as boto.s3.bucket.Bucket.add_user_grant(),
    # to allow polymorphic treatment at application layer.
    def add_user_grant(self, permission, user_id, recursive=False,
                       headers=None):
        """
        Convenience method that provides a quick way to add a canonical user
        grant to a bucket. This method retrieves the current ACL, creates a new
        grant based on the parameters passed in, adds that grant to the ACL and
        then PUTs the new ACL back to GCS.

        :type permission: string
        :param permission:  The permission being granted.  Should be one of:
                            (READ|WRITE|FULL_CONTROL)

        :type user_id: string
        :param user_id:     The canonical user id associated with the GS account
                            you are granting the permission to.

        :type recursive: bool
        :param recursive: A boolean value to controls whether the call
                          will apply the grant to all keys within the bucket
                          or not.  The default value is False.  By passing a
                          True value, the call will iterate through all keys
                          in the bucket and apply the same grant to each key.
                          CAUTION: If you have a lot of keys, this could take
                          a long time!
        """
        if permission not in GSPermissions:
            raise self.connection.provider.storage_permissions_error(
                'Unknown Permission: %s' % permission)
        acl = self.get_acl(headers=headers)
        acl.add_user_grant(permission, user_id)
        self.set_acl(acl, headers=headers)
        if recursive:
            for key in self:
                key.add_user_grant(permission, user_id, headers=headers)

    def add_group_email_grant(self, permission, email_address, recursive=False,
                              headers=None):
        """
        Convenience method that provides a quick way to add an email group
        grant to a bucket. This method retrieves the current ACL, creates a new
        grant based on the parameters passed in, adds that grant to the ACL and
        then PUT's the new ACL back to GCS.

        :type permission: string
        :param permission: The permission being granted. Should be one of:
            READ|WRITE|FULL_CONTROL
            See http://code.google.com/apis/storage/docs/developer-guide.html#authorization
            for more details on permissions.

        :type email_address: string
        :param email_address: The email address associated with the Google
            Group to which you are granting the permission.

        :type recursive: bool
        :param recursive: A boolean value to controls whether the call
                          will apply the grant to all keys within the bucket
                          or not.  The default value is False.  By passing a
                          True value, the call will iterate through all keys
                          in the bucket and apply the same grant to each key.
                          CAUTION: If you have a lot of keys, this could take
                          a long time!
        """
        if permission not in GSPermissions:
            raise self.connection.provider.storage_permissions_error(
                'Unknown Permission: %s' % permission)
        acl = self.get_acl(headers=headers)
        acl.add_group_email_grant(permission, email_address)
        self.set_acl(acl, headers=headers)
        if recursive:
            for key in self:
                key.add_group_email_grant(permission, email_address,
                                          headers=headers)

    # Method with same input signature as boto.s3.bucket.Bucket.list_grants()
    # (but returning different object type), to allow polymorphic treatment
    # at application layer.
    def list_grants(self, headers=None):
        """Returns the ACL entries applied to this bucket.

        :param dict headers: Additional headers to send with the request.
        :rtype: list containing :class:`~.gs.acl.Entry` objects.
        """
        acl = self.get_acl(headers=headers)
        return acl.entries

    def disable_logging(self, headers=None):
        """Disable logging on this bucket.

        :param dict headers: Additional headers to send with the request.
        """
        xml_str = '<?xml version="1.0" encoding="UTF-8"?><Logging/>'
        self.set_subresource('logging', xml_str, headers=headers)

    def enable_logging(self, target_bucket, target_prefix=None, headers=None):
        """Enable logging on a bucket.

        :type target_bucket: bucket or string
        :param target_bucket: The bucket to log to.

        :type target_prefix: string
        :param target_prefix: The prefix which should be prepended to the
            generated log files written to the target_bucket.

        :param dict headers: Additional headers to send with the request.
        """
        if isinstance(target_bucket, Bucket):
            target_bucket = target_bucket.name
        xml_str = '<?xml version="1.0" encoding="UTF-8"?><Logging>'
        xml_str = (xml_str + '<LogBucket>%s</LogBucket>' % target_bucket)
        if target_prefix:
            xml_str = (xml_str +
                       '<LogObjectPrefix>%s</LogObjectPrefix>' % target_prefix)
        xml_str = xml_str + '</Logging>'

        self.set_subresource('logging', xml_str, headers=headers)

    def configure_website(self, main_page_suffix=None, error_key=None,
                          headers=None):
        """Configure this bucket to act as a website

        :type main_page_suffix: str
        :param main_page_suffix: Suffix that is appended to a request that is
            for a "directory" on the website endpoint (e.g. if the suffix is
            index.html and you make a request to samplebucket/images/ the data
            that is returned will be for the object with the key name
            images/index.html). The suffix must not be empty and must not
            include a slash character. This parameter is optional and the
            property is disabled if excluded.

        :type error_key: str
        :param error_key: The object key name to use when a 400 error occurs.
            This parameter is optional and the property is disabled if excluded.

        :param dict headers: Additional headers to send with the request.
        """
        if main_page_suffix:
            main_page_frag = self.WebsiteMainPageFragment % main_page_suffix
        else:
            main_page_frag = ''

        if error_key:
            error_frag = self.WebsiteErrorFragment % error_key
        else:
            error_frag = ''

        body = self.WebsiteBody % (main_page_frag, error_frag)
        response = self.connection.make_request('PUT', self.name, data=body,
                                                query_args='websiteConfig',
                                                headers=headers)
        body = response.read()
        if response.status == 200:
            return True
        else:
            raise self.connection.provider.storage_response_error(
                response.status, response.reason, body)

    def get_website_configuration(self, headers=None):
        """Returns the current status of website configuration on the bucket.

        :param dict headers: Additional headers to send with the request.

        :rtype: dict
        :returns: A dictionary containing a Python representation
            of the XML response from GCS. The overall structure is:

            * WebsiteConfiguration

              * MainPageSuffix: suffix that is appended to request that
                is for a "directory" on the website endpoint.
              * NotFoundPage: name of an object to serve when site visitors
                encounter a 404.
        """
        return self.get_website_configuration_xml(self, headers)[0]

    def get_website_configuration_with_xml(self, headers=None):
        """Returns the current status of website configuration on the bucket as
        unparsed XML.

        :param dict headers: Additional headers to send with the request.

        :rtype: 2-Tuple
        :returns: 2-tuple containing:

            1) A dictionary containing a Python representation of the XML
               response from GCS. The overall structure is:

              * WebsiteConfiguration

                * MainPageSuffix: suffix that is appended to request that is for
                  a "directory" on the website endpoint.
                * NotFoundPage: name of an object to serve when site visitors
                  encounter a 404

            2) Unparsed XML describing the bucket's website configuration.
        """
        response = self.connection.make_request('GET', self.name,
                query_args='websiteConfig', headers=headers)
        body = response.read()
        boto.log.debug(body)

        if response.status != 200:
            raise self.connection.provider.storage_response_error(
                response.status, response.reason, body)

        e = boto.jsonresponse.Element()
        h = boto.jsonresponse.XmlHandler(e, None)
        h.parse(body)
        return e, body

    def delete_website_configuration(self, headers=None):
        """Remove the website configuration from this bucket.

        :param dict headers: Additional headers to send with the request.
        """
        self.configure_website(headers=headers)

    def get_versioning_status(self, headers=None):
        """Returns the current status of versioning configuration on the bucket.

        :rtype: bool
        """
        response = self.connection.make_request('GET', self.name,
                                                query_args='versioning',
                                                headers=headers)
        body = response.read()
        boto.log.debug(body)
        if response.status != 200:
            raise self.connection.provider.storage_response_error(
                    response.status, response.reason, body)
        resp_json = boto.jsonresponse.Element()
        boto.jsonresponse.XmlHandler(resp_json, None).parse(body)
        resp_json = resp_json['VersioningConfiguration']
        return ('Status' in resp_json) and (resp_json['Status'] == 'Enabled')

    def configure_versioning(self, enabled, headers=None):
        """Configure versioning for this bucket.

        :param bool enabled: If set to True, enables versioning on this bucket.
            If set to False, disables versioning.

        :param dict headers: Additional headers to send with the request.
        """
        if enabled == True:
            req_body = self.VersioningBody % ('Enabled')
        else:
            req_body = self.VersioningBody % ('Suspended')
        self.set_subresource('versioning', req_body, headers=headers)
