files.new_contents: # 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 base64
  import hmac
  import time
  from hashlib import sha1
  
  import libcloud.utils.py3
  
  try:
      if libcloud.utils.py3.DEFAULT_LXML:
          from lxml.etree import Element, SubElement
      else:
          from xml.etree.ElementTree import Element, SubElement
  except ImportError:
      from xml.etree.ElementTree import Element, SubElement
  
  from libcloud.utils.py3 import httplib
  from libcloud.utils.py3 import urlquote
  from libcloud.utils.py3 import b
  from libcloud.utils.py3 import tostring
  
  from libcloud.utils.xml import fixxpath, findtext
  from libcloud.utils.files import read_in_chunks
  from libcloud.common.types import InvalidCredsError, LibcloudError
  from libcloud.common.base import ConnectionUserAndKey, RawResponse
  from libcloud.common.aws import AWSBaseResponse, AWSDriver, \
      AWSTokenConnection, SignedAWSConnection
  
  from libcloud.storage.base import Object, Container, StorageDriver
  from libcloud.storage.types import ContainerError
  from libcloud.storage.types import ContainerIsNotEmptyError
  from libcloud.storage.types import InvalidContainerNameError
  from libcloud.storage.types import ContainerDoesNotExistError
  from libcloud.storage.types import ObjectDoesNotExistError
  from libcloud.storage.types import ObjectHashMismatchError
  
  # How long before the token expires
  EXPIRATION_SECONDS = 15 * 60
  
  S3_US_STANDARD_HOST = 's3.amazonaws.com'
  S3_US_EAST2_HOST = 's3-us-east-2.amazonaws.com'
  S3_US_WEST_HOST = 's3-us-west-1.amazonaws.com'
  S3_US_WEST_OREGON_HOST = 's3-us-west-2.amazonaws.com'
  S3_US_GOV_WEST_HOST = 's3-us-gov-west-1.amazonaws.com'
  S3_CN_NORTH_HOST = 's3.cn-north-1.amazonaws.com.cn'
  S3_CN_NORTHWEST_HOST = 's3.cn-northwest-1.amazonaws.com.cn'
  S3_EU_WEST_HOST = 's3-eu-west-1.amazonaws.com'
  S3_EU_WEST2_HOST = 's3-eu-west-2.amazonaws.com'
  S3_EU_CENTRAL_HOST = 's3-eu-central-1.amazonaws.com'
  S3_AP_SOUTH_HOST = 's3-ap-south-1.amazonaws.com'
  S3_AP_SOUTHEAST_HOST = 's3-ap-southeast-1.amazonaws.com'
  S3_AP_SOUTHEAST2_HOST = 's3-ap-southeast-2.amazonaws.com'
  S3_AP_NORTHEAST1_HOST = 's3-ap-northeast-1.amazonaws.com'
  S3_AP_NORTHEAST2_HOST = 's3-ap-northeast-2.amazonaws.com'
  S3_AP_NORTHEAST_HOST = S3_AP_NORTHEAST1_HOST
  S3_SA_EAST_HOST = 's3-sa-east-1.amazonaws.com'
  S3_SA_SOUTHEAST2_HOST = 's3-sa-east-2.amazonaws.com'
  S3_CA_CENTRAL_HOST = 's3-ca-central-1.amazonaws.com'
  
  # Maps AWS region name to connection hostname
  REGION_TO_HOST_MAP = {
      'us-east-1': S3_US_STANDARD_HOST,
      'us-east-2': S3_US_EAST2_HOST,
      'us-west-1': S3_US_WEST_HOST,
      'us-west-2': S3_US_WEST_OREGON_HOST,
      'us-gov-west-1': S3_US_GOV_WEST_HOST,
      'cn-north-1': S3_CN_NORTH_HOST,
      'cn-northwest-1': S3_CN_NORTHWEST_HOST,
      'eu-west-1': S3_EU_WEST_HOST,
      'eu-west-2': S3_EU_WEST2_HOST,
      'eu-central-1': S3_EU_CENTRAL_HOST,
      'ap-south-1': S3_AP_SOUTH_HOST,
      'ap-southeast-1': S3_AP_SOUTHEAST_HOST,
      'ap-southeast-2': S3_AP_SOUTHEAST2_HOST,
      'ap-northeast-1': S3_AP_NORTHEAST1_HOST,
      'ap-northeast-2': S3_AP_NORTHEAST2_HOST,
      'sa-east-1': S3_SA_EAST_HOST,
      'sa-east-2': S3_SA_SOUTHEAST2_HOST,
      'ca-central-1': S3_CA_CENTRAL_HOST
  }
  
  API_VERSION = '2006-03-01'
  NAMESPACE = 'http://s3.amazonaws.com/doc/%s/' % (API_VERSION)
  
  # AWS multi-part chunks must be minimum 5MB
  CHUNK_SIZE = 5 * 1024 * 1024
  
  # Desired number of items in each response inside a paginated request in
  # ex_iterate_multipart_uploads.
  RESPONSES_PER_REQUEST = 100
  
  
  class S3Response(AWSBaseResponse):
      namespace = None
      valid_response_codes = [httplib.NOT_FOUND, httplib.CONFLICT,
                              httplib.BAD_REQUEST]
  
      def success(self):
          i = int(self.status)
          return 200 <= i <= 299 or i in self.valid_response_codes
  
      def parse_error(self):
          if self.status in [httplib.UNAUTHORIZED, httplib.FORBIDDEN]:
              raise InvalidCredsError(self.body)
          elif self.status == httplib.MOVED_PERMANENTLY:
              bucket_region = self.headers.get('x-amz-bucket-region', None)
              used_region = self.connection.driver.region
              raise LibcloudError('This bucket is located in a different '
                                  'region. Please use the correct driver.'
                                  'Bucket region "%s", used region "%s"' %
                                  (bucket_region, used_region),
                                  driver=S3StorageDriver)
          raise LibcloudError('Unknown error. Status code: %d' % (self.status),
                              driver=S3StorageDriver)
  
  
  class S3RawResponse(S3Response, RawResponse):
      pass
  
  
  class BaseS3Connection(ConnectionUserAndKey):
      """
      Represents a single connection to the S3 Endpoint
      """
  
      host = 's3.amazonaws.com'
      responseCls = S3Response
      rawResponseCls = S3RawResponse
  
      @staticmethod
      def get_auth_signature(method, headers, params, expires, secret_key, path,
                             vendor_prefix):
          """
          Signature = URL-Encode( Base64( HMAC-SHA1( YourSecretAccessKeyID,
                                      UTF-8-Encoding-Of( StringToSign ) ) ) );
  
          StringToSign = HTTP-VERB + "\n" +
              Content-MD5 + "\n" +
              Content-Type + "\n" +
              Expires + "\n" +
              CanonicalizedVendorHeaders +
              CanonicalizedResource;
          """
          special_headers = {'content-md5': '', 'content-type': '', 'date': ''}
          vendor_headers = {}
  
          for key, value in list(headers.items()):
              key_lower = key.lower()
              if key_lower in special_headers:
                  special_headers[key_lower] = value.strip()
              elif key_lower.startswith(vendor_prefix):
                  vendor_headers[key_lower] = value.strip()
  
          if expires:
              special_headers['date'] = str(expires)
  
          buf = [method]
          for _, value in sorted(special_headers.items()):
              buf.append(value)
          string_to_sign = '\n'.join(buf)
  
          buf = []
          for key, value in sorted(vendor_headers.items()):
              buf.append('%s:%s' % (key, value))
          header_string = '\n'.join(buf)
  
          values_to_sign = []
          for value in [string_to_sign, header_string, path]:
              if value:
                  values_to_sign.append(value)
  
          string_to_sign = '\n'.join(values_to_sign)
          b64_hmac =
  
  [... the rest is omitted ...]
files.new_path: libcloud/storage/drivers/s3.py
files.old_contents: # 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 base64
  import hmac
  import time
  from hashlib import sha1
  
  import libcloud.utils.py3
  
  try:
      if libcloud.utils.py3.DEFAULT_LXML:
          from lxml.etree import Element, SubElement
      else:
          from xml.etree.ElementTree import Element, SubElement
  except ImportError:
      from xml.etree.ElementTree import Element, SubElement
  
  from libcloud.utils.py3 import httplib
  from libcloud.utils.py3 import urlquote
  from libcloud.utils.py3 import b
  from libcloud.utils.py3 import tostring
  
  from libcloud.utils.xml import fixxpath, findtext
  from libcloud.utils.files import read_in_chunks
  from libcloud.common.types import InvalidCredsError, LibcloudError
  from libcloud.common.base import ConnectionUserAndKey, RawResponse
  from libcloud.common.aws import AWSBaseResponse, AWSDriver, \
      AWSTokenConnection, SignedAWSConnection
  
  from libcloud.storage.base import Object, Container, StorageDriver
  from libcloud.storage.types import ContainerError
  from libcloud.storage.types import ContainerIsNotEmptyError
  from libcloud.storage.types import InvalidContainerNameError
  from libcloud.storage.types import ContainerDoesNotExistError
  from libcloud.storage.types import ObjectDoesNotExistError
  from libcloud.storage.types import ObjectHashMismatchError
  
  # How long before the token expires
  EXPIRATION_SECONDS = 15 * 60
  
  S3_US_STANDARD_HOST = 's3.amazonaws.com'
  S3_US_EAST2_HOST = 's3-us-east-2.amazonaws.com'
  S3_US_WEST_HOST = 's3-us-west-1.amazonaws.com'
  S3_US_WEST_OREGON_HOST = 's3-us-west-2.amazonaws.com'
  S3_US_GOV_WEST_HOST = 's3-us-gov-west-1.amazonaws.com'
  S3_CN_NORTH_HOST = 's3.cn-north-1.amazonaws.com.cn'
  S3_CN_NORTHWEST_HOST = 's3.cn-northwest-1.amazonaws.com.cn'
  S3_EU_WEST_HOST = 's3-eu-west-1.amazonaws.com'
  S3_EU_WEST2_HOST = 's3-eu-west-2.amazonaws.com'
  S3_EU_CENTRAL_HOST = 's3-eu-central-1.amazonaws.com'
  S3_AP_SOUTH_HOST = 's3-ap-south-1.amazonaws.com'
  S3_AP_SOUTHEAST_HOST = 's3-ap-southeast-1.amazonaws.com'
  S3_AP_SOUTHEAST2_HOST = 's3-ap-southeast-2.amazonaws.com'
  S3_AP_NORTHEAST1_HOST = 's3-ap-northeast-1.amazonaws.com'
  S3_AP_NORTHEAST2_HOST = 's3-ap-northeast-2.amazonaws.com'
  S3_AP_NORTHEAST_HOST = S3_AP_NORTHEAST1_HOST
  S3_SA_EAST_HOST = 's3-sa-east-1.amazonaws.com'
  S3_SA_SOUTHEAST2_HOST = 's3-sa-east-2.amazonaws.com'
  S3_CA_CENTRAL_HOST = 's3-ca-central-1.amazonaws.com'
  
  API_VERSION = '2006-03-01'
  NAMESPACE = 'http://s3.amazonaws.com/doc/%s/' % (API_VERSION)
  
  # AWS multi-part chunks must be minimum 5MB
  CHUNK_SIZE = 5 * 1024 * 1024
  
  # Desired number of items in each response inside a paginated request in
  # ex_iterate_multipart_uploads.
  RESPONSES_PER_REQUEST = 100
  
  
  class S3Response(AWSBaseResponse):
      namespace = None
      valid_response_codes = [httplib.NOT_FOUND, httplib.CONFLICT,
                              httplib.BAD_REQUEST]
  
      def success(self):
          i = int(self.status)
          return 200 <= i <= 299 or i in self.valid_response_codes
  
      def parse_error(self):
          if self.status in [httplib.UNAUTHORIZED, httplib.FORBIDDEN]:
              raise InvalidCredsError(self.body)
          elif self.status == httplib.MOVED_PERMANENTLY:
              raise LibcloudError('This bucket is located in a different ' +
                                  'region. Please use the correct driver.',
                                  driver=S3StorageDriver)
          raise LibcloudError('Unknown error. Status code: %d' % (self.status),
                              driver=S3StorageDriver)
  
  
  class S3RawResponse(S3Response, RawResponse):
      pass
  
  
  class BaseS3Connection(ConnectionUserAndKey):
      """
      Represents a single connection to the S3 Endpoint
      """
  
      host = 's3.amazonaws.com'
      responseCls = S3Response
      rawResponseCls = S3RawResponse
  
      @staticmethod
      def get_auth_signature(method, headers, params, expires, secret_key, path,
                             vendor_prefix):
          """
          Signature = URL-Encode( Base64( HMAC-SHA1( YourSecretAccessKeyID,
                                      UTF-8-Encoding-Of( StringToSign ) ) ) );
  
          StringToSign = HTTP-VERB + "\n" +
              Content-MD5 + "\n" +
              Content-Type + "\n" +
              Expires + "\n" +
              CanonicalizedVendorHeaders +
              CanonicalizedResource;
          """
          special_headers = {'content-md5': '', 'content-type': '', 'date': ''}
          vendor_headers = {}
  
          for key, value in list(headers.items()):
              key_lower = key.lower()
              if key_lower in special_headers:
                  special_headers[key_lower] = value.strip()
              elif key_lower.startswith(vendor_prefix):
                  vendor_headers[key_lower] = value.strip()
  
          if expires:
              special_headers['date'] = str(expires)
  
          buf = [method]
          for _, value in sorted(special_headers.items()):
              buf.append(value)
          string_to_sign = '\n'.join(buf)
  
          buf = []
          for key, value in sorted(vendor_headers.items()):
              buf.append('%s:%s' % (key, value))
          header_string = '\n'.join(buf)
  
          values_to_sign = []
          for value in [string_to_sign, header_string, path]:
              if value:
                  values_to_sign.append(value)
  
          string_to_sign = '\n'.join(values_to_sign)
          b64_hmac = base64.b64encode(
              hmac.new(b(secret_key), b(string_to_sign), digestmod=sha1).digest()
          )
          return b64_hmac.decode('utf-8')
  
      def add_default_params(self, params):
          expires = str(int(time.time()) + EXPIRATION_SECONDS)
          params['AWSAccessKeyId'] = self.user_id
          params['Expires'] = expires
          return params
  
      def pre_connect_hook(self, params, headers):
          # pylint: disable=no-member
          params['Signature'] = self.get_auth_signature(
              method=self.method, headers=headers, params=params,
              expires=params['Expires'], secret_key=self.key, path=self.action,
              vendor_prefix=self.driver.http_vendor_prefix)
          return params, headers
  
  
  class S3Connection(AWSTokenConnection, BaseS3Connection):
      """
      Represents a single connection to the S3 endpoint, with AWS-specific
      features.
      """
      pass
  
  
  class S3SignatureV4Connection(SignedAWSConnection, BaseS3Connection):
      service_name = 's3'
      version = API_VERSION
  
      def __init__(self, user_id, key, secure=True, host=None, port=None,
                   url=None, timeout=None, proxy_url=None, token=None,
                   retry_delay=None, backoff=None):
          super(S3SignatureV4Connection, self).__init__(
              user_id, key, secure, host,
              port, url, timeout, proxy_url,
              token, retry_delay, backoff,
              4)  # force version 4
  
  
  class S3MultipartUpload(object):
      """
      Class representing an amazon s3 multipart upload
      """
  
      def __init__(self,
  
  [... the rest is omitted ...]
files.old_path: libcloud/storage/drivers/s3.py