o ckF[g@s,ddlZddlZddlmZmZddlZddlmZddl Z ddl m Z ddl m Z ddlmZddlmZddlmZdd lmZmZd d Zd d ZGdddeZGdddeZGdddeZGdddeZGdddeZGdddeZGdddeZ GdddeZ!Gddde Z"dS) N)sixurllib)detect_potential_s3sigv4)AWSAuthConnection)handler)Bucket)Key) ResultSet)BotoClientErrorS3ResponseErrorcCs|ds tddS)aJ Bucket names must not contain uppercase characters. We check for this by appending a lowercase character and testing with islower(). Note this also covers cases like numeric bucket names with dashes. >>> check_lowercase_bucketname("Aaaa") Traceback (most recent call last): ... BotoClientError: S3Error: Bucket names cannot contain upper-case characters when using either the sub-domain or virtual hosting calling format. >>> check_lowercase_bucketname("1234-5678-9123") True >>> check_lowercase_bucketname("abcdefg1234") True azuBucket names cannot contain upper-case characters when using either the sub-domain or virtual hosting calling format.T)islowerr )nr4/usr/lib/python3/dist-packages/boto/s3/connection.pycheck_lowercase_bucketname(s rcsfdd}|S)Ncs(t|dkr t|dr |i|S)N)lenr)argskwargsfrrwrapperBsz(assert_case_insensitive..wrapperr)rrrrrassert_case_insensitiveAs rc@s:eZdZddZd ddZddZd dd Zd d d Zd S)_CallingFormatcCsdSNrselfserverbucketrrrget_bucket_serverKz _CallingFormat.get_bucket_serverrcCs2d|}||||7}|||||7}|S)Nz%s:// build_hostget_pathbuild_path_baser connectionprotocolr r!keyurl_baserrrbuild_url_baseNsz_CallingFormat.build_url_basecCs|dkr|S|||Sr)r"rrrrr%Ts z_CallingFormat.build_hostcCs4tj|}d}|dkrd|}|dtj|S)Nr//%sbotoutilsget_utf8_valuerparsequote)rr!r+pathrrrbuild_auth_pathZs z_CallingFormat.build_auth_pathcCstj|}dtj|S)Nr/r0)rr!r+rrrr'as z_CallingFormat.build_path_baseNr)__name__ __module__ __qualname__r"r-r%r7r'rrrrrIs   rc@eZdZeddZdS)SubdomainCallingFormatcCs d||fS)Nz%s.%srrrrrr"hs z(SubdomainCallingFormat.get_bucket_serverNr9r:r;rr"rrrrr=fr=c@r<)VHostCallingFormatcCs|SNrrrrrr"osz$VHostCallingFormat.get_bucket_serverNr>rrrrr@mr?r@c@seZdZddZdddZdS)OrdinaryCallingFormatcCs|SrArrrrrr"vr#z'OrdinaryCallingFormat.get_bucket_serverrcCs0tj|}d}|r|d|7}|tj|S)Nr.z%s/r0)rr!r+ path_baserrrr'ys  z%OrdinaryCallingFormat.build_path_baseNr8)r9r:r;r"r'rrrrrBtsrBc@seZdZdddZdS)(ProtocolIndependentOrdinaryCallingFormatrcCs.d}||||7}|||||7}|S)Nz//r$r(rrrr-sz7ProtocolIndependentOrdinaryCallingFormat.build_url_baseNr8)r9r:r;r-rrrrrDsrDc@s4eZdZdZdZdZdZdZdZdZ dZ d Z d Z d S) LocationrEUz eu-central-1z us-west-1z us-west-2z sa-east-1zap-northeast-1zap-southeast-1zap-southeast-2z cn-north-1N) r9r:r;DEFAULTrF EUCentral1USWestUSWest2SAEast APNortheast APSoutheast APSoutheast2CNNorth1rrrrrEsrEc@ eZdZdS)NoHostProvidedNr9r:r;rrrrrQsrQc@rP)HostRequiredErrorNrRrrrrrSsrScs$eZdZdZejdddZdZdddddddde dded d e ddd ddffd d Z e ddZ ddZddZddZddZ      d2ddZ   d3ddZ   d4d d!Zd5d"d#Zd5d$d%Zd6d&d'Zd5d(d)Zd6d*d+Zdejdfd,d-Zd5d.d/Z   d7fd0d1 ZZS)8 S3Connectionzs3.amazonaws.coms3calling_formatz)boto.s3.connection.SubdomainCallingFormatz)Signature=%s&Expires=%d&AWSAccessKeyId=%sNTrr.awsFcsd}| turtjdd} | dur|j} d}t| tjr#tj | } | |_ ||_ ||_ t t|j| ||||||||| | | |||||d|rQd|vrStddSdS)NFrUhostT)debughttps_connection_factoryr6providersecurity_tokensuppress_consec_slashesvalidate_certs profile_name hmac-v4-s3z6When using SigV4, you must specify a 'host' parameter.)rQr1configget DefaultHost isinstancer string_typesr2 find_classrV bucket_classanonsuperrT__init___required_auth_capabilityrS)raws_access_key_idaws_secret_access_key is_secureportproxy proxy_port proxy_user proxy_passrXrYrZrVr6r[rgr\r]rhr^r_no_host_provided __class__rrrjs4    zS3Connection.__init__cCs|jrdgSdgS)NrhrU)rh)rrrrrksz&S3Connection._required_auth_capabilityccs|D]}|VqdSrA)get_all_buckets)rr!rrr__iter__s zS3Connection.__iter__cCs||duSrA)lookup)r bucket_namerrr __contains__szS3Connection.__contains__cCs ||_dS)aX Set the Bucket class associated with this bucket. By default, this would be the boto.s3.key.Bucket class but if you want to subclass that for some reason this allows you to associate your new class. :type bucket_class: class :param bucket_class: A subclass of Bucket that can be more specific N)rg)rrgrrrset_bucket_classs zS3Connection.set_bucket_classcCs2t|tjs Jddttjj|d|fS)zX Taken from the AWS book Python examples and modified for use with boto z;Policy document must include a valid expiration Time objectz({"expiration": "%s", "conditions": [%s]},)rdtime struct_timestrftimer1r2ISO8601join)rexpiration_time conditionsrrrbuild_post_policys zS3Connection.build_post_policyphttpSTANDARDc Cs|durg}| dur g} ttt|} | d||dr2| d|dtd n| d||rJ| d||d|d|r[| d ||d |d|rd| d ||jjr{|d |jjd| d |jj| r|d| d| d| | r|d| d| d| || | } t | }|d|d|d|j d|j |}|d|d|d|dd||j||f}||dS)a Taken from the AWS book Python examples and modified for use with boto This only returns the arguments required for the post form, not the actual form. This does not return the file input field which also needs to be added :type bucket_name: string :param bucket_name: Bucket to submit to :type key: string :param key: Key name, optionally add ${filename} to the end to attach the submitted filename :type expires_in: integer :param expires_in: Time (in seconds) before this expires, defaults to 6000 :type acl: string :param acl: A canned ACL. One of: * private * public-read * public-read-write * authenticated-read * bucket-owner-read * bucket-owner-full-control :type success_action_redirect: string :param success_action_redirect: URL to redirect to on success :type max_content_length: integer :param max_content_length: Maximum size for this file :type http_method: string :param http_method: HTTP Method to use, "http" or "https" :type storage_class: string :param storage_class: Storage class to use for storing the object. Valid values: STANDARD | REDUCED_REDUNDANCY :type server_side_encryption: string :param server_side_encryption: Specifies server-side encryption algorithm to use when Amazon S3 creates an object. Valid values: None | AES256 :rtype: dict :return: A dictionary containing field names/values as well as a url to POST to .. code-block:: python Nz{"bucket": "%s"}z ${filename}z["starts-with", "$key", "%s"]z {"key": "%s"}z {"acl": "%s"}acl)namevaluez!{"success_action_redirect": "%s"}success_action_redirectz["content-length-range", 0, %i]x-amz-security-tokenz{"x-amz-security-token": "%s"}zx-amz-storage-classz{"x-amz-storage-class": "%s"}zx-amz-server-side-encryptionz&{"x-amz-server-side-encryption": "%s"}policyAWSAccessKeyId signaturer+z%s://%s/)actionfields)r~gmtimeintappendendswithrr[r\rbase64 b64encoderl _auth_handler sign_stringrVr% server_name)rrzr+ expires_inrrmax_content_length http_methodrr storage_classserver_side_encryption expirationr policy_b64rurlrrrbuild_post_form_argss^:      z!S3Connection.build_post_form_argsrc Cs|j||} |j||} |j||} | dr"| dd} i} |dur,|| d<|dur5| ||j|| | || | d}|jj ||| dS)Nz:443 VersionId)headersrXparams)iso_date) rVr'r7r%rrupdatebuild_base_http_requestrpresign)rrmethodr!r+r force_httpresponse_headers version_idrr6 auth_pathrXr http_requestrrrgenerate_url_sigv4es"     zS3Connection.generate_url_sigv4c  Cs|jjddkr|r|j|||||||| dS|pi}| r"t|} ntt|} |j||} || } g} | durC| d| |r[| D]\}}| d|t j |fqI|j jre|j j|d<| rxd| vrmdnd}| |d| 7} |j|||r|jstj|| || |j }|j|}t j j |d d }d|j|| |jf}nd }|r|j j}| D]\}}||r| d|t j |fq| r|sdnd}||d| 7}|rd }d }n|j}|j}|j|||||||S) Nrr`)r!r+rrrrz versionId=%sz%s=%sr?&r)saferP)r capabilityrrr~rVr7r&ritemsrr4r5r[r\rr'rhr1r2canonical_stringr QueryStringrl header_prefix startswithr*ror-r)rrrr!r+r query_authrrexpires_in_absoluterexpiresrextra_qpkv delimiterc_stringb64_hmacencoded_canonical query_part hdr_prefixr*rorrr generate_urlsj            zS3Connection.generate_urlcCsv|jd|d}|}|jdkr|j|j|j|td|jfg}t ||}t |t s2| d}t j|||S)NGETri,rzutf-8) make_requestreadstatusr[storage_response_errorreasonr rgr XmlHandlerrdbytesencodexmlsax parseString)rrresponsebodyrshrrrrws     zS3Connection.get_all_bucketscCs|j|d}|jjS)a  Convenience method that returns the "CanonicalUserID" of the user who's credentials are associated with the connection. The only way to get this value is to do a GET request on the service which returns all buckets associated with the account. As part of that response, the canonical userid is returned. This method simply does all of that and then returns just the user id. :rtype: string :return: A string containing the canonical user id. r)rwownerid)rrrrrrget_canonical_user_ids z"S3Connection.get_canonical_user_idcCs|r |j||dS|||S)a Retrieves a bucket by name. If the bucket does not exist, an ``S3ResponseError`` will be raised. If you are unsure if the bucket exists or not, you can use the ``S3Connection.lookup`` method, which will either return a valid bucket or ``None``. If ``validate=False`` is passed, no request is made to the service (no charge/communication delay). This is only safe to do if you are **sure** the bucket exists. If the default ``validate=True`` is passed, a request is made to the service to ensure the bucket exists. Prior to Boto v2.25.0, this fetched a list of keys (but with a max limit set to ``0``, always returning an empty list) in the bucket (& included better error messages), at an increased expense. As of Boto v2.25.0, this now performs a HEAD request (less expensive but worse error messages). If you were relying on parsing the error message before, you should call something like:: bucket = conn.get_bucket('', validate=False) bucket.get_all_keys(maxkeys=0) :type bucket_name: string :param bucket_name: The name of the bucket :type headers: dict :param headers: Additional headers to pass along with the request to AWS. :type validate: boolean :param validate: If ``True``, it will try to verify the bucket exists on the service-side. (Default: ``True``) r) head_bucketrg)rrzvalidaterrrr get_buckets% zS3Connection.get_bucketcCs|jd||d}|}|jdkr|||S|jdkr.|j|j|j|}d|_d|_||jdkrE|j|j|j|}d|_d |_||j|j|j|) a| Determines if a bucket exists by name. If the bucket does not exist, an ``S3ResponseError`` will be raised. :type bucket_name: string :param bucket_name: The name of the bucket :type headers: dict :param headers: Additional headers to pass along with the request to AWS. :returns: A object HEADri AccessDeniedz Access Deniedi NoSuchBucketz#The specified bucket does not exist) rrrrgr[rr error_code error_message)rrzrrrerrrrrrs2     zS3Connection.head_bucketcCs(z |j|||d}W|Sd}Y|S)aR Attempts to get a bucket from S3. Works identically to ``S3Connection.get_bucket``, save for that it will return ``None`` if the bucket does not exist instead of throwing an exception. :type bucket_name: string :param bucket_name: The name of the bucket :type headers: dict :param headers: Additional headers to pass along with the request to AWS. :type validate: boolean :param validate: If ``True``, it will try to fetch all keys within the given bucket. (Default: ``True``) rN)r)rrzrrr!rrrry.s zS3Connection.lookupcCst||r|r|||jj<n|jj|i}|tjkrd}nd|d}|jd|||d}|}|jdkr?|j|j|j ||jdkrJ| ||S|j |j|j |)a Creates a new located bucket. By default it's in the USA. You can pass Location.EU to create a European bucket (S3) or European Union bucket (GCS). :type bucket_name: string :param bucket_name: The name of the new bucket :type headers: dict :param headers: Additional headers to pass along with the request to AWS. :type location: str :param location: The location of the new bucket. You can use one of the constants in :class:`boto.s3.connection.Location` (e.g. Location.EU, Location.USWest, etc.). :type policy: :class:`boto.s3.acl.CannedACLStrings` :param policy: A canned ACL policy that will be applied to the new key in S3. rz/z1PUT)rdatair) rr[ acl_headerrErGrrrstorage_create_errorrrgr)rrzrlocationrrrrrrr create_bucketGs2        zS3Connection.create_bucketcCs:|jd||d}|}|jdkr|j|j|j|dS)a Removes an S3 bucket. In order to remove the bucket, it must first be empty. If the bucket is not empty, an ``S3ResponseError`` will be raised. :type bucket_name: string :param bucket_name: The name of the bucket :type headers: dict :param headers: Additional headers to pass along with the request to AWS. DELETErN)rrrr[rr)rr!rrrrrr delete_bucketvs  zS3Connection.delete_bucketc st||jr |j}t|tr|j}|j||} tjd| |j ||} tjd| |j | |} |rV| d|7} tjd| | d|7} tjd| t t |j|| ||| | ||| d S)Nzpath=%sz auth_path=%sr)override_num_retries retry_handler)rdrgrrrVr'r1logrYr7r%rrirTr) rrr!r+rr query_argssenderrrr6rrXrurrrs(     zS3Connection.make_request) rNNNrNNrN)rrNFNNN)rrNTFNFNrA)TN)rrNrNNNN) r9r:r;rcr1rarbDefaultCallingFormatrrQrrjrrkrxr{r|rrrrrwrrrryrErGrrr __classcell__rrrurrTs`#    u  ;  * - /rT)#xml.saxrr boto.compatrrr~ boto.authr boto.utilsr1boto.connectionrrboto.s3.bucketr boto.s3.keyrboto.resultsetr boto.exceptionr r rrobjectrr=r@rBrDrErQrSrTrrrrs.