3
b<j             0   @   sj  d dl mZmZ d dlZd dlZd dlZd dlZd dlZd dlZd dl	Z	d dl
mZ d dlmZ d dlmZmZmZmZ d dlmZ yd dlmZ W n  ek
r   d dlmZ Y nX yd dlmZ W n  ek
r   d d	lmZ Y nX d dlZyd d
lmZ W n" ek
r"   d d
lmZ Y nX ddlm Z m!Z!m"Z"m#Z#m$Z$m%Z% ddl&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z. ddl/m/Z/ ddl0m0Z0 ddl1m1Z1m2Z2 ddl3m3Z3 ddl4m4Z4 ddl5T ddl6m7Z7 ddl8m8Z8 ddl9m9Z9 ddl:m;Z;m<Z<m=Z=m>Z>m?Z? yd dl@mAZA d dlBZByeBjCddZDdd ZEW n eFk
r   y eBjGeBjHZDeDjI  dd ZEW n, eJk
r   eBjCeBjHdZDdd ZEY nX Y n2 eJk
r   eBjGeBjHZDeDjI  d d ZEY nX W n\ eeKfk
r ZL z:eMeLZNd!eNkrd"ZOnd#eN ZOeOd$7 ZOd%aPd&d ZEW Y ddZL[LX nX d'd( ZQd)ZRd3ZSg ZTG d+d, d,eUZVG d-d. d.eUZWeTjXd. d/d0 ZYd1d2 ZZdS )4    )absolute_importdivisionN)saxutils)timeout)debuginfowarningerror)ST_SIZE)urlparse)encodestring)encodebytes)md5   )getListFromXmlgetTextFromXmlgetRootTagNamedecode_from_s3encode_to_s3s3_quote)convertHeaderTupleListToDicthash_file_md5	unicodisedeunicodisecheck_bucket_namecheck_bucket_name_dns_supportgetHostnameFromBucketcalculateChecksum)
SortedDict)	AccessLog)ACLGranteeLogDelivery)BidirMap)Config)*)MultiPartUpload)S3Uri)ConnMan)sign_request_v2sign_request_v4checksum_sha256_filechecksum_sha256_bufferformat_param_str)ArgumentErrorT)mimec             C   s
   t j| S )N)magic_Z	from_file)file r1   E/oak/stanford/groups/akundaje/marinovg/programs/s3cmd-master/S3/S3.pymime_magic_fileC   s    r3   c             C   s4   y
t j| S  tttfk
r.   t jt| S X d S )N)r/   r0   UnicodeDecodeErrorUnicodeEncodeErrorr-   r   )r0   r1   r1   r2   r3   P   s    
)flagsc             C   s
   t j| S )N)r/   Zid_filename)r0   r1   r1   r2   r3   Z   s    c             C   s   t jt| S )N)r/   r0   r   )r0   r1   r1   r2   r3   c   s    magicz%Module python-magic is not available.z'Module python-magic can't be used (%s).z. Guessing MIME types based on file extensions.Fc             C   s   t stt da tj| d S )NTr   )magic_warnedr   magic_message	mimetypes
guess_type)r0   r1   r1   r2   r3   n   s    c             C   sj   dd }|| }|d k	rZt |trZd|krR|jd\}}|tdd  }||f}n|d f}|d krfd}|S )Nc             S   s   t | }|S )N)r3   )r0   Z	magictyper1   r1   r2   _mime_magicw   s    zmime_magic.<locals>._mime_magic;charset)NN)
isinstancestrsplitlen)r0   r<   resultmimetyper>   r1   r1   r2   
mime_magicu   s    

rE      i   c               @   sF   e Zd Zi Zi ZdddZdd Zdd Zdd	 Zd
d Z	dd Z
dS )	S3RequestNc             C   sn   || _ t|pi dd| _t| j jjdkrF| j jj  | j jj| jd< || _|| _|pXi | _	|| _
| j  d S )NT)ignore_caser   zx-amz-security-token)s3r   headersrB   configaccess_tokenrole_refreshresourcemethod_stringparamsbodyrequester_pays)selfrI   rO   rN   rJ   rQ   rP   r1   r1   r2   __init__   s    
zS3Request.__init__c             C   s"   | j jjr| jdkrd| jd< d S )NGETPOSTPUTHEADZ	requesterzx-amz-request-payer)rU   rV   rW   rX   )rI   rK   rR   rO   rJ   )rS   r1   r1   r2   rR      s    zS3Request.requester_paysc             C   s,   d| j kr| j d= tjdtj | j d< d S )Ndatez%a, %d %b %Y %H:%M:%S +0000z
x-amz-date)rJ   timestrftimegmtime)rS   r1   r1   r2   update_timestamp   s    
zS3Request.update_timestampc             C   s&   | j jrdS | j jjs| j jr"dS dS )NFT)rI   endpoint_requires_signature_v4rK   signature_v2fallback_to_signature_v2)rS   r1   r1   r2   use_signature_v2   s
    zS3Request.use_signature_v2c             C   s
  | j jd}| j rVtd |r4d|| j d f }n
| j d }t| j|| j| j| _ntd | jj	| j d }|r|t
jkrt
jj|djd|  s|t
jkrtt j| rd|| j d f }n
| j d }t
jj| j d t j}t| j||| j|| j| j| _d S )NbucketzUsing signature v2z/%s%surizUsing signature v4 z%s.)rN   getra   r   r(   rO   rP   rJ   rI   get_hostnamerG   	redir_map
startswithr   r#   host_bucket
region_mapbucket_locationr)   rQ   )rS   bucket_nameZresource_urihostnameZbucket_regionr1   r1   r2   sign   s&    



zS3Request.signc             C   sT   | j   | j  t| j}t|d ddd|d< |d  t| j7  < | j|| jfS )Nrc   FT)quote_backslashesunicode_output)	r]   rn   dictrN   r   r,   rP   rO   rJ   )rS   rN   r1   r1   r2   get_triplet   s    
zS3Request.get_triplet)N)__name__
__module____qualname__rj   rg   rT   rR   r]   ra   rn   rr   r1   r1   r1   r2   rG      s   
	!rG   c               @   sF  e Zd ZedddddddZedd	d
dddZeded ed B ed ed B ed ed B ed ed B ed ed B ed ed B ed ed B ed ed B ed ed B ed ed B dZddddZdZdd Z	d d! Z
d"d# Zd$d% Zdd'd(Zd)d* Zdd+d,Zdd-d.Zdd/d0Zdd1d2Zd3d4 Zdd6d7Zd8d9 Zd:d; Zdd<d=Zdd>d?Zdd@dAZddBdCZddDdEZdFdG ZdHdI ZdJdK ZddLdMZdNdO Z ddQdRZ!ddSdTZ"dUdV Z#dWdX Z$dYdZ Z%d[d\ Z&d]d^ Z'dd_d`Z(ddadbZ)ddcddZ*dedf Z+dgdh Z,didj Z-dkdl Z.dmdn Z/dodp Z0dqdr Z1dsdt Z2dudv Z3dwdx Z4dydz Z5d{d| Z6d}d~ Z7dddZ8dddZ9dddZ:dddZ;dddZ<dd Z=dd Z>dd Z?dddZ@dddZAdd ZBdd ZCdd ZDdd ZEdd ZFefddZGdddZHdPdeddd&fddZIdddZJdddZKdefddZLd&S )S3r   rF               )rU   rW   rX   DELETErV   MASK   i   i   i   i   )SERVICEBUCKETOBJECTBATCHr|   r   r~   rU   r   rW   r{   r   rX   rV   r   )ZUNDFINEDLIST_ALL_BUCKETSBUCKET_CREATEBUCKET_LISTBUCKET_DELETE
OBJECT_PUT
OBJECT_GETOBJECT_HEADOBJECT_DELETEOBJECT_POSTBATCH_DELETEzBucket '%s' does not existz Access to bucket '%s' was deniedzBucket '%s' already exists)NoSuchBucketAccessDeniedZBucketAlreadyExists   c             C   s   || _ d| _d| _d| _d S )NF)rK   r`   r^   expect_continue_not_supported)rS   rK   r1   r1   r2   rT     s    zS3.__init__c             C   s(   d}| j jdkr| j jS | j jr$d}|S )NSTANDARDrd   ZREDUCED_REDUNDANCY)rK   storage_classreduced_redundancy)rS   clsr1   r1   r2   r     s    zS3.storage_classc             C   s   |r|t jkrt j| }n(|r6t| jj|r6t|}n| jjj }| jjrb|j	drx|d d }n|j	drx|d d }t
d||f  |S )Nz:443rw   z:80   zget_hostname(%s): %s)rG   rg   r   rK   ri   r   	host_baselower	use_httpsendswithr   )rS   rb   hostr1   r1   r2   rf     s    


zS3.get_hostnamec             C   s   |j  tj|< d S )N)r   rG   rg   )rS   rb   redir_hostnamer1   r1   r2   set_hostname,  s    zS3.set_hostnameNc             C   s   |j d}|rh|tjkr2tjj |djd|  sL|tjkrht| jj| rhdt|ddd|d f }n|d }|rd	||f }| jjdkr| jj	 rd
| j
||f }td|  |S )Nrb   rd   z%s.z/%s%sFT)ro   rp   rc   z%s%szhttp://%s%szformat_uri(): )re   rG   rg   rh   r   rK   ri   r   
proxy_hostr   rf   r   )rS   rN   	base_pathrl   rc   r1   r1   r2   
format_uri/  s     


zS3.format_uric             C   s*   | j d}| j|}t|d d|d< |S )Nr   dataZBucketlist)create_requestsend_requestr   )rS   requestresponser1   r1   r2   list_all_bucketsD  s    

zS3.list_all_bucketsc             C   s^   g }g }x4| j |||||D ]\}}	}
|j|
 |j|	 qW i }||d< ||d< ||d< |S )Nr   common_prefixes	truncated)bucket_list_streamingextend)rS   rb   prefix	recursive
uri_paramslimitZ	item_listprefixesr   dirsobjectsr   r1   r1   r2   bucket_listJ  s    
zS3.bucket_listc             #   sD  dd }dd }dd } fdd}	|r0|j  p2i }d	}
g }d
}d
}|}x|
r>| j||||| | d }| d }|t|7 }|t|7 }||| kr|||  }| d }
|
r0|dks|| |k r"|r|	 d ||d< n&|r|d d |d< nd||fV  P td|d   n|
||fV  P |
||fV  qJW dS )ze Generator that produces <dir_list>, <object_list> pairs of groups of content of a specified bucket. c             S   s   t | dpd}|j dkS )Nz.//IsTruncatedfalse)r   r   )r   Zis_truncatedr1   r1   r2   _list_truncatedY  s    z1S3.bucket_list_streaming.<locals>._list_truncatedc             S   s
   t | dS )NZContents)r   )r   r1   r1   r2   _get_contents^  s    z/S3.bucket_list_streaming.<locals>._get_contentsc             S   s
   t | dS )NZCommonPrefixes)r   )r   r1   r1   r2   _get_common_prefixesa  s    z6S3.bucket_list_streaming.<locals>._get_common_prefixesc                s   t  d dp|d d S )Nr   Z
NextMarkerr   Key)r   )r   current_list)r   r1   r2   _get_next_markerd  s    z2S3.bucket_list_streaming.<locals>._get_next_markerTr   r   r   ZmarkerPrefixFzListing continues after '%s'Nr   r   )copybucket_list_noparserB   r   )rS   rb   r   r   r   r   r   r   r   r   r   r   num_objectsZnum_prefixesmax_keysr   Zcurrent_prefixesr1   )r   r2   r   W  s@    
zS3.bucket_list_streamingc             C   sb   |d kri }|r||d< | j j r0| r0d|d< |dkrDt||d< | jd||d}| j|}|S )	Nr   /	delimiterr   zmax-keysr   )rb   r   r   )rK   r   r@   r   r   )rS   rb   r   r   r   r   r   r   r1   r1   r2   r     s    
zS3.bucket_list_noparsec             C   s   t dd}|r|j| d}|r|j j dkr|j j dkr|j }|j dkr\|j }d}||7 }|d7 }td	|  t|dd
 nt|dd
 | jjrd|d< | j	d|||d}| j
|}|S )NT)rH   rd   USz	us-east-1EUz/<CreateBucketConfiguration><LocationConstraint>z1</LocationConstraint></CreateBucketConfiguration>zbucket_location: )
dns_strictFzpublic-readz	x-amz-aclr   )rb   rJ   rQ   )r   updatestripupperr   r   r   rK   
acl_publicr   r   )rS   rb   rk   extra_headersrJ   rQ   r   r   r1   r1   r2   bucket_create  s&    

$
zS3.bucket_createc             C   s   | j d|d}| j|}|S )Nr   )rb   )r   r   )rS   rb   r   r   r1   r1   r2   bucket_delete  s    
zS3.bucket_deleteFc       	      C   s   |j  }| jd|j  dd id}tjj|d}tjj|d}z4|rd|oH| rd| jjtj|< dtj|< | j|}W d ||kr|tj|< n|tjkrtj|= ||kr|tj|< n|tjkrtj|= X t	|d d}| s|dkrd}n|d	krd
}|S )Nr   location)rb   r   rd   z	us-east-1r   ZLocationConstraintr   r   z	eu-west-1)rd   r   )
rb   r   rG   rg   re   rj   rK   r   r   r   )	rS   rc   force_us_defaultrb   r   Zsaved_redir_mapZsaved_region_mapr   r   r1   r1   r2   get_bucket_location  s0    



zS3.get_bucket_locationc             C   sJ   | j d|j dd id}| j|}|jdd}|rBt|d d}nd }|S )Nr   requestPayment)rb   r   r   rd   ZPayer)r   rb   r   re   r   )rS   rc   r   r   Z	resp_datapayerr1   r1   r2   get_bucket_requester_pays  s    
zS3.get_bucket_requester_paysc             C   sT   i }| j ||d< y| j||d< W n* tk
rN } zd |d< W Y d d }~X nX |S )Nzbucket-locationzrequester-pays)r   r   S3Error)rS   rc   r   er1   r1   r2   bucket_info  s    zS3.bucket_infoc             C   s   |j  }| jd|dd id}yR| j|}t|d d|d< t|d d|d< | jj|j  | j|d	 |d
< |S  tk
r } z|jdkrt	d d S  W Y d d }~X nX d S )Nr   website)rb   r   r   z.//IndexDocument//Suffixindex_documentz.//ErrorDocument//Keyerror_document)rb   r   website_endpointi  zICould not get /?website - website probably not configured for this bucket)
rb   r   r   r   rK   r   r   r   statusr   )rS   rc   rk   rb   r   r   r   r1   r1   r2   website_info  s     

zS3.website_infoc             C   s   |j  }d}|d7 }|d| jj 7 }|d7 }| jjrT|d7 }|d| jj 7 }|d7 }|d7 }| jd	||d
d id}| j|}td|  |S )NzF<WebsiteConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">z  <IndexDocument>z    <Suffix>%s</Suffix>z  </IndexDocument>z  <ErrorDocument>z    <Key>%s</Key>z  </ErrorDocument>z</WebsiteConfiguration>r   r   )rb   rQ   r   zReceived response '%s')rb   rK   website_indexwebsite_errorr   r   r   )rS   rc   rk   rb   rQ   r   r   r1   r1   r2   website_create  s    

zS3.website_createc             C   sN   |j  }| jd|dd id}| j|}td|  |d dkrJtd| |S )Nr   r   )rb   r   zReceived response '%s'r      zExpected status 204: %s)rb   r   r   r   S3ResponseError)rS   rc   rk   rb   r   r   r1   r1   r2   website_delete  s    
zS3.website_deletec             C   s   |j  }| jd|dd id}y| j|}W nP tk
rz } z4|jdkrRtd d S |jdkrhtd d S  W Y d d }~X nX t|d }|d	krtd
| d S t|d d|d< t|d d|d< t|d d|d< |S )Nr   	lifecycle)rb   r   i  zMCould not get /?lifecycle - lifecycle probably not configured for this bucketi  zKCould not get /?lifecycle - lifecycle support not implemented by the serverr   ZLifecycleConfigurationz7Could not get /?lifecycle - unexpected xml response: %sz.//Rule//Prefixr   z.//Rule//Expiration//DaterY   z.//Rule//Expiration//Daysdays)rb   r   r   r   r   r   r   r   )rS   rc   rk   rb   r   r   r   Zroot_tag_namer1   r1   r2   expiration_info  s2    




zS3.expiration_infoc             C   s   | j jr| j jrtd| j jp&| j js^| j jr8tdtd |j }| jd|dd id}n
| j|}| j	|}td|  |S )Nz+Expect either --expiry-day or --expiry-datezdel bucket lifecycler   r   )rb   r   zReceived response '%s')
rK   expiry_dateexpiry_daysParameterErrorexpiry_prefixr   rb   r   _expiration_setr   )rS   rc   rk   rb   r   r   r1   r1   r2   expiration_set=  s    

zS3.expiration_setc             C   s   t d d}|d7 }|d| jj 7 }|d7 }|d7 }| jjrN|d| jj 7 }n| jjrf|d| jj 7 }|d	7 }|d
7 }|d7 }tdd}t||d< |j }| jd|||dd id}|S )Nzput bucket lifecyclez<LifecycleConfiguration>z  <Rule>z    <Prefix>%s</Prefix>z    <Status>Enabled</Status>z    <Expiration>z    <Date>%s</Date>z    <Days>%s</Days>z    </Expiration>z	  </Rule>z</LifecycleConfiguration>T)rH   zcontent-md5r   r   )rb   rJ   rQ   r   )	r   rK   r   r   r   r   compute_content_md5rb   r   )rS   rc   rQ   rJ   rb   r   r1   r1   r2   r   M  s(    
zS3._expiration_setc             C   s   | j j}d }|dkr&| j j r&td| j jrn| j jrJttjjt	|}| j j
r`t|\}}ntj|\}}|sz| j j}||fS )N-zRYou must specify --mime-type or --default-mime-type for files uploaded from stdin.)rK   default_mime_typer   guess_mime_typefollow_symlinksr   ospathrealpathr   use_mime_magicrE   r:   r;   )rS   filenamecontent_typecontent_charsetr1   r1   r2   _guess_content_typed  s    zS3._guess_content_typec             C   s,   | j j}|s| j j}|d| j jj  7 }|S )Nz
; charset=)rK   	mime_typer   encodingr   )rS   r   r1   r1   r2   stdin_content_typev  s
    zS3.stdin_content_typec             C   sb   | j j}d }|dkr| j S |s.| j|\}}|s>| j jj }| j||r^|d k	r^|d | }|S )Nr   z
; charset=)rK   r   r   r   r   r   add_encoding)rS   r   r   r   r1   r1   r2   r   ~  s    zS3.content_typec             C   sb   d|krdS | j jjd}|d dkr*dS |jdd}t|dk rFdS |d }||krZd	S dS d S )
Nzcharset=F,r   rd   .rF   r   T)rK   add_encoding_extsrA   rsplitrB   )rS   r   r   Zextspartsextr1   r1   r2   r     s    zS3.add_encodingrd   c             C   s  |j dkrtd|j  |dkr:tjjt| r:tdyX|dkrftjt	j
j ddd}d|_d	}n*tjt|dd
}||_tjt|t }W n4 ttfk
r } ztd|j W Y d d }~X nX tdd}|r|j| | jjrd|d< | jjrd|d< | jj|d< | j|d|d< | jjr0d|d< | j |d< d}	| jj r^|dkr^td| jjr|| jjt ks|dkrd}	|| jj| jj t krtd| jj| jjf |	r| j|||||S | jj ry| j!|}
W n t"k
r   d }
Y nX |
d k	rt#|
d d }|
d d j$d}||kr~t%d|d	|| jj&}||krjt'd|  d S t'd|||f  nt'd |||f  t(||d< | j)d!||d"}||j* |d#}| j+|||}|S )$NrI   z Expected URI type 's3', got '%s'r   zNot a regular filerbF)modeclosefdz<stdin>r   )r  z%sT)rH   AES256zx-amz-server-side-encryptionzaws:kmsz+x-amz-server-side-encryption-aws-kms-key-id)r   zcontent-typezpublic-readz	x-amz-aclzx-amz-storage-classz2Multi-part upload is required to upload from stdinzZChunk size %d MB results in more than %d chunks. Please increase --multipart-chunk-size-mbrJ   zcontent-lengthetagz"'rd   z,Put: size and md5sum match for %s, skipping.zBMultiPart: checksum (%s vs %s) does not match for %s, reuploading.z>MultiPart: size (%d vs %d) does not match for %s, reuploading.r   )rc   rJ   )sourcedestinationextra),type
ValueErrorr   r   isfiler   InvalidFileErrorioopensysstdinfilenostream_namestatr
   IOErrorOSErrorstrerrorr   r   rK   server_side_encryptionkms_keyr   r   r   enable_multipartr   multipart_chunk_size_mbSIZE_1MBmultipart_max_chunkssend_file_multipartput_continueobject_info	Exceptionintr   r   
send_chunkr   r@   r   rc   	send_file)rS   r   rc   r   extra_labelZ
src_streamsizer   rJ   	multipartr   Zremote_sizeZremote_checksumZchecksumr   labelsr   r1   r1   r2   
object_put  sv    
 









zS3.object_putc       	      C   sJ   |j dkrtd|j  | jd|d}|j ||d}| j||||}|S )NrI   z Expected URI type 's3', got '%s'r   )rc   )r  r  r	  )r
  r  r   rc   	recv_file)	rS   rc   stream	dest_namestart_positionr%  r   r(  r   r1   r1   r2   
object_get  s    
zS3.object_getc                s     fdd D }| j | dS )z" Batch delete given a remote_list c                s   g | ]} | d  qS )object_uri_strr1   ).0item)remote_listr1   r2   
<listcomp>   s    z*S3.object_batch_delete.<locals>.<listcomp>N)object_batch_delete_uri_strs)rS   r2  urisr1   )r2  r2   object_batch_delete  s    zS3.object_batch_deletec       	      C   sv   dd }|}t |dkr tdt|d j }|||}tt|dddd}| jd	|||d
did}| j|}|S )z* Batch delete given a list of object uris c             S   s   d}xn|D ]f}t |}|jdkr.td|j |j sBtd| |j | krVtdtj|j }|d| 7 }q
W |d7 }t|}|S )Nz.<?xml version="1.0" encoding="UTF-8"?><Delete>rI   z Expected URI type 's3', got '%s'zURI '%s' has no objectz2The batch should contain keys from the same bucketz<Object><Key>%s</Key></Object>z	</Delete>)	r&   r
  r  
has_objectrb   r   escapeobjectr   )rb   Zkey_listrQ   keyrc   r9  r1   r1   r2   compose_batch_del_xml  s    

z>S3.object_batch_delete_uri_strs.<locals>.compose_batch_del_xmlr   zKey list is emptyzapplication/xml)zcontent-md5zcontent-typeT)rH   r   deleteN)rb   rJ   rQ   r   )rB   r  r&   rb   r   r   r   r   )	rS   r5  r;  Zbatchrb   Zrequest_bodyrJ   r   r   r1   r1   r2   r4    s    

zS3.object_batch_delete_uri_strsc             C   s4   |j dkrtd|j  | jd|d}| j|}|S )NrI   z Expected URI type 's3', got '%s'r   )rc   )r
  r  r   r   )rS   rc   r   r   r1   r1   r2   object_delete"  s
    

zS3.object_deletec             C   s   |j dkrtd|j  | jjdk r,td| jjdkr@tdd	}|d
| jj 7 }|d7 }|d| jj 7 }|d7 }|d7 }| jd||dd id}| j|}td|  |S )NrI   z Expected URI type 's3', got '%s'r   z*You must restore a file for 1 or more daysStandard	ExpeditedBulkz7Valid restoration priorities: bulk, standard, expeditedz@<RestoreRequest xmlns="http://s3.amazonaws.com/doc/2006-03-01/">z  <Days>%s</Days>z  <GlacierJobParameters>z    <Tier>%s</Tier>z  </GlacierJobParameters>z</RestoreRequest>r   restore)rc   rQ   r   zReceived response '%s')r>  r?  r@  )	r
  r  rK   restore_daysr   restore_priorityr   r   r   )rS   rc   rQ   r   r   r1   r1   r2   object_restore)  s"    


zS3.object_restorec             C   sN   ddddddddd	d
dddg}x*|| j j D ]}|j |kr,||j = q,W |S )NrY   zcontent-lengthzlast-modifiedzcontent-md5zx-amz-version-idzx-amz-delete-markerzaccept-ranges
connectionr  Zserverz
x-amz-id-2zx-amz-request-idzx-amz-storage-class)rK   remove_headersr   )rS   rJ   Z	to_removehr1   r1   r2   _sanitize_headers<  s"    zS3._sanitize_headersc             C   s  |j dkrtd|j  |j dkr0td|j  | jjdkry| j|}W n4 tk
r~ } z|jdkrj|d}W Y dd}~X nX d}	d}
|s| jjrd}|r| j|}|d }
t	|
d }| jj
rJ|
}|dkr| j|}|d }t	|d }||krtjt }n| jjt }||krJ|dkrB| j|}|d }t	|d }|}
d}	|
rh| j|
 t|
dd	}
n
tdd	}
| jjrd
|
d< | j |
d< | jjrd|
d< | jjrd|
d< | jj|
d< |r|
j| | jjr| jj|
d< |sd|
d< nd|
d< |	r| j||||
|}n<td|j |j f ddd|
d< | jd||
d}| j|}|d rt|d dkrd|d< td t|| jjdkr|ry| j|| W n4 tk
r } z|jdkr|W Y dd}~X nX |S )a   Remote copy an object and eventually set metadata

        Note: A little memo description of the nightmare for performance here:
        ** FOR AWS, 2 cases:
        - COPY will copy the metadata of the source to dest, but you can't
        modify them. Any additional header will be ignored anyway.
        - REPLACE will set the additional metadata headers that are provided
        but will not copy any of the source headers.
        So, to add to existing meta during copy, you have to do an object_info
        to get original source headers, then modify, then use REPLACE for the
        copy operation.

        ** For Minio and maybe other implementations:
        - if additional headers are sent, they will be set to the destination
        on top of source original meta in all cases COPY and REPLACE.
        It is a nice behavior except that it is different of the aws one.

        As it was still too easy, there is another catch:
        In all cases, for multipart copies, metadata data are never copied
        from the source.
        rI   z Expected URI type 's3', got '%s'Ni  FTrJ   zcontent-length)rH   zpublic-readz	x-amz-aclzx-amz-storage-classr  zx-amz-server-side-encryptionzaws:kmsz+x-amz-server-side-encryption-aws-kms-key-idzcontent-typeCOPYzx-amz-metadata-directiveZREPLACEz/%s/%s)ro   rp   zx-amz-copy-sourcer   )rc   rJ   r   Errori  r   zHServer error during the COPY operation. Overwrite response status to 500)r
  r  rK   r   get_aclr   r   r   r   r"  r  r%   MAX_CHUNK_SIZE_MBr  multipart_copy_chunk_size_mbrH  r   r   r  r  r   copy_file_multipartr   rb   r9  r   r   r   r	   set_acl)rS   src_uridst_urir   src_sizer%  replace_metaaclexcr'  rJ   Zsrc_infoZsrc_headersZ	thresholdr   r   r1   r1   r2   object_copyV  s    




















zS3.object_copyc             C   s   | j |||||ddS )NT)rS  )rV  )rS   rP  rQ  r   rR  r%  r1   r1   r2   object_modify  s    zS3.object_modifyc             C   s`   | j |||||}td||f  |d  s<t|d dkrR| j| td| n
td| |S )NzObject %s copied to %sr   CopyObjectResultCompleteMultipartUploadResultzObject '%s' deletedzGObject '%s' NOT deleted because of an unexpected response data content.)rX  rY  )rV  r   r   r=  r   )rS   rP  rQ  r   rR  r%  Zresponse_copyr1   r1   r2   object_move  s    



zS3.object_movec             C   s   | j d|d}| j|}|S )Nr   )rc   )r   r   )rS   rc   r   r   r1   r1   r2   r     s    
zS3.object_infoc             C   sP   |j  r| jd|dd id}n| jd|j dd id}| j|}t|d }|S )Nr   rT  )rc   r   r   )rb   r   r   )r7  r   rb   r   r    )rS   rc   r   r   rT  r1   r1   r2   rK    s    
z
S3.get_aclc             C   st   d| }t d||f  tddidd}|j rJ| jd|||dd id	}n| jd
|j ||dd id}| j|}|S )Nz%szset_acl(%s): acl-xml: %szcontent-typezapplication/xmlT)rH   r   rT  )rc   rJ   rQ   r   r   )rb   rJ   rQ   r   )r   r   r7  r   rb   r   )rS   rc   rT  rQ   rJ   r   r   r1   r1   r2   rO    s    
z
S3.set_aclc             C   s.   | j d|j dd id}| j|}t|d S )Nr   policy)rb   r   r   )r   rb   r   r   )rS   rc   r   r   r1   r1   r2   
get_policy$  s    
zS3.get_policyc             C   s8   t dd}d|d< | jd|||dd id}| j|}|S )NT)rH   zapplication/jsonzcontent-typer   r[  )rc   rJ   rQ   r   )r   r   r   )rS   rc   r[  rJ   r   r   r1   r1   r2   
set_policy*  s    

zS3.set_policyc             C   s.   | j d|dd id}td|  | j|}|S )Nr   r[  )rc   r   zdelete_policy(%s))r   r   r   )rS   rc   r   r   r1   r1   r2   delete_policy4  s
    
zS3.delete_policyc             C   s.   | j d|j dd id}| j|}t|d S )Nr   cors)rb   r   r   )r   rb   r   r   )rS   rc   r   r   r1   r1   r2   get_cors;  s    
zS3.get_corsc             C   sD   t dd}d|d< t||d< | jd|||dd id}| j|}|S )	NT)rH   zapplication/xmlzcontent-typezcontent-md5r   r_  )rc   rJ   rQ   r   )r   r   r   r   )rS   rc   r_  rJ   r   r   r1   r1   r2   set_corsA  s    

zS3.set_corsc             C   s.   | j d|dd id}td|  | j|}|S )Nr   r_  )rc   r   zdelete_cors(%s))r   r   r   )rS   rc   r   r   r1   r1   r2   delete_corsL  s
    
zS3.delete_corsc             C   sL   t dd}t||d< | jd|||dd id}td||f  | j|}|S )NT)rH   zcontent-md5r   r   )rc   rJ   rQ   r   z(set_lifecycle_policy(%s): policy-xml: %s)r   r   r   r   r   )rS   rc   r[  rJ   r   r   r1   r1   r2   set_lifecycle_policyS  s    

zS3.set_lifecycle_policyc             C   s\   t dd}d|d< d}| jjr(|d7 }n|d7 }|d7 }| jd	||d
d id}| j|}|S )NT)rH   zapplication/xmlzcontent-typezN<RequestPaymentConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
z<Payer>Requester</Payer>
z<Payer>BucketOwner</Payer>
z</RequestPaymentConfiguration>
r   r   )rc   rQ   r   )r   rK   rR   r   r   )rS   rc   rJ   rQ   r   r   r1   r1   r2   	set_payer]  s    



zS3.set_payerc             C   sB   | j d|j dd id}td|  | j|}td|d   |S )Nr   r   )rb   r   zget_lifecycle_policy(%s)z%s: Got Lifecycle Policyr   )r   rb   r   r   )rS   rc   r   r   r1   r1   r2   get_lifecycle_policyk  s    
zS3.get_lifecycle_policyc             C   s.   | j d|dd id}td|  | j|}|S )Nr   r   )rc   r   zdelete_lifecycle_policy(%s))r   r   r   )rS   rc   r   r   r1   r1   r2   delete_lifecycle_policyt  s
    
zS3.delete_lifecycle_policyc             C   s.   g }x$| j |||D ]\}}|j| qW |S )N)get_multipart_streamingr   )rS   rc   r   r   upload_listr   uploadsr1   r1   r2   get_multipart{  s    zS3.get_multipartc             c   s<  |r|j  pi }|j }d}d}|}d |d< x|r6| j|d||d}|d }	t|	d}
|t|
7 }||krv|| }t|	d}| s|j dkrd	}|r*|dks||k r|
r t|	d}|s|
d d }||d< t|	d}|r||d< nd|kr|d= nd	|
fV  P td|d   n||
fV  P ||
fV  q0W d S )NTr   ri  )r   r   r   r   ZUploadz.//IsTruncatedr   Fr   ZNextKeyMarkerr   Z	KeyMarkerZNextUploadIdMarkerZUploadIdMarkerzListing continues after '%s'r   r   )r   rb   r   r   rB   r   r   r   )rS   rc   r   r   rb   r   r   r   r   xml_datarh  xml_truncatedZnext_keyZupload_id_markerr1   r1   r2   rg    sL    







zS3.get_multipart_streamingc             C   s0   g }x&| j ||||D ]\}}|j| qW |S )N)list_multipart_streamingr   )rS   rc   	upload_idr   r   	part_listr   r   r1   r1   r2   list_multipart  s    zS3.list_multipartc             c   s   |r|j  pi }d}d}|}x|r| j||||}|d }	t|	d}
|t|
7 }||kr`|| }t|	d}| s||j dkrd}|r|dks||k r|
rt|	d	}|s|
d d
 }||d< nd|
fV  P td|d   n||
fV  P ||
fV  qW d S )NTr   r   ZPartz.//IsTruncatedr   Fr   ZNextPartNumberMarker
PartNumberzpart-number-markerz!Listing continues after Part '%s'r   r   )r   list_multipart_noparser   rB   r   r   r   )rS   rc   rn  r   r   r   r   	max_partsr   rk  ro  rl  Znext_part_numberr1   r1   r2   rm    s<    




zS3.list_multipart_streamingc             C   sF   |d kri }|dkr t ||d< ||d< | jd||d}| j|}|S )Nr   z	max-partsuploadIdr   )rc   r   r   )r@   r   r   )rS   rc   rn  r   rs  r   r   r1   r1   r2   rr    s    
zS3.list_multipart_noparsec             C   s"   | j d|d|id}| j|}|S )Nr   rt  )rc   r   )r   r   )rS   rc   idr   r   r1   r1   r2   abort_multipart  s    
zS3.abort_multipartc             C   s2   | j d|j dd id}| j|}t|d }|S )Nr   logging)rb   r   r   )r   rb   r   r   )rS   rc   r   r   	accesslogr1   r1   r2   get_accesslog  s
    
zS3.get_accesslogc             C   s^   | j |}td|j |f  |jtd |jtd td|j |f  | j|| d S )NzCurrent ACL(%s): %sZREAD_ACPZWRITEzUpdated ACL(%s): %s)rK  r   rc   ZappendGranteer!   rO  )rS   rc   rT  r1   r1   r2   set_accesslog_acl  s    
zS3.set_accesslog_aclc       
      C   s   t  }|r |j| |j| n|j  d| }td||f  | jd|j |dd id}y| j|}W n\ tk
r }	 z@|	j	d dkrt	d | j
td	|j   | j|}n W Y d d }	~	X nX ||fS )
Nz%sz$set_accesslog(%s): accesslog-xml: %sr   rw  )rb   rQ   r   CodeZInvalidTargetBucketForLoggingz.Setting up log-delivery ACL for target bucket.zs3://%s)r   ZenableLoggingZsetAclPublicZdisableLoggingr   r   rb   r   r   r   rz  r&   )
rS   rc   enablelog_target_prefix_urir   rx  rQ   r   r   r   r1   r1   r2   set_accesslog  s$    
zS3.set_accesslogc             C   s   d dd}|r|s|rt d|r>|j }|j r:|j p<d }|rZ||d< |rZd| |d< tjjtj| tjd @ }	t| |	||||}
t	d|d  |
S )Nr   )rb   rc   z>Both 'uri' and either 'bucket' or 'object' parameters suppliedrb   rc   r|   zCreateRequest: resource[uri]=%s)
r  rb   r7  r9  rv   http_methodsgetkey
operationsrG   r   )rS   	operationrc   rb   r9  rJ   rQ   r   rN   rO   r   r1   r1   r2   r   (  s    
zS3.create_requestc             C   s   | j | d d S )Nr   r   )_max_retries)rS   retriesr1   r1   r2   
_fail_wait>  s    zS3._fail_waitc       
      O   s0  |d j d}d|krzt|d dkrzt|d d}t|d d}| j|| td| |rp|tj|< td| |||S |jd	kr$|d j d
}	|	r|	jdr|	dd  }	n|	jdr|	dd  }	t	d|	 j
}	|jd }| j||	 td|	 |r|tj|< td| |||S td| t|d S )NrJ   zx-amz-bucket-regionr   r   z	.//Bucketz.//EndpointzRedirected to: %szRedirected to region: %srX   r   zhttp://   zhttps://rx   rb   zRedirection error: No info provided by the server to where should be forwarded the request (HEAD request). (Hint target region: %s))re   rB   r   r   r   rG   rj   rO   rh   r   rm   rN   r   r   )
rS   r   r   fnargskwargsZredir_regionZredir_bucketr   Zlocation_urlr1   r1   r2   _http_redirection_handlerB  s6    











zS3._http_redirection_handlerc       	      O   s  d|krt |d dkrt|d d}|dkrrt|d d}|dk	rh|tj|jd < td| |||S td	 nj|d
krt|d d}|dkrtd d| _|||S n2|dkr|j	  r| j
 rtd d| _
|||S n,|j	  o| j
 r
td d| _
|||S dS )zR
        Returns None if no handler available for the specific error code
        r   r   r{  ZAuthorizationHeaderMalformedZRegionNrb   zForwarding request to %szVCould not determine bucket the location. Please consider using the --region parameter.ZInvalidRequestMessagez\The authorization mechanism you have provided is not supported. Please use AWS4-HMAC-SHA256.zEndpoint requires signature v4TZInvalidArgumentzFalling back to signature v2)rB   r   rG   rj   rN   r   r   r   r^   ra   r`   )	rS   r   r   r  r  r  failureCoderegionmessager1   r1   r2   _http_400_handlerg  s2    



zS3._http_400_handlerc             O   sz   d|krnt |d dkrnt|d d}|dkrnt|d d}|dkrn|j  rn| j rntd d| _|||S t|d S )	Nr   r   r{  r   r  z=AWS authentication requires a valid Date or x-amz-date headerzFalling back to signature v2T)rB   r   ra   r`   r   r   )rS   r   r   r  r  r  r  r  r1   r1   r2   _http_403_handler  s    
zS3._http_403_handlerc             C   s   |j jdr|j  rtjj|j d t jdkrtd yFtd|j d  }| j	|dd}|dk	rt|tj|j d < td| W n4 t
k
r } ztd	| td
 W Y dd}~X nX dS )a?  Get and update region for the request if needed.

        Signature v4 needs the region of the bucket or the request will fail
        with the indication of the correct region.
        We are trying to avoid this failure by pre-emptively getting the
        correct region to use, if not provided by the user.
        rb   r   z====== SEND Inner request to determine the bucket region =====zs3://T)r   NzE===== SUCCESS Inner request to determine the bucket region (%r) =====z,getlocation inner request failure reason: %sz?===== FAILED Inner request to determine the bucket region =====)rN   re   ra   rG   rj   r#   rk   r   r&   r   r!  )rS   r   Zs3_urir  rU  r1   r1   r2   update_region_inner_request  s    

zS3.update_region_inner_requestc             C   s  | j | t|j|_|j}|j \}}}i }td d }ytj| j|d }| j	||j
}td|||t|jprdf  |jj|||j| |jj }	|	j|d< |	j|d< t|	j |d< |	j |d< d	|d krt|d d	 }
|
|d
< tj| W n2 ttfk
r    Y n ttfk
r } ztdtj|  t|drn|jrn|jtjtjtj fksdt!|ksdt!|krt"|t# r tj$| |rt%d|d |f  t%d| j&|  t'j(| j&| | j)||d S t*d|d  W Y d d }~X n    tdtj|   Y nX tdtj|  |d d#krb| j+||| j)|S |d dkr| j,||| j)|}|r|S t-|}|r|j.d$krt%d|d |f  t%d| j&|  t'j(| j&| | j)||d S ||d dkr| j/||| j)|S |d dkr&t-||d dksB|d dkrt-|}|d dkr\d }|rt%d|d |f  t%d| j&|  t'j(| j&| | j)||d S ||d d!k s|d d"krt-||S )%Nz"Processing request, please wait...rb   zESending request method_string=%r, uri=%r, headers=%r, body=(%i bytes)rd   r   reasonrJ   r   zx-amz-meta-s3cmd-attrszs3cmd-attrsz
Response:
errnoz[Errno 104]z
[Errno 32]z Retrying failed request: %s (%s)rc   zWaiting %d sec...r   zRequest failed for: %s-  3  i  	BadDigestOperationAbortedTokenRefreshRequiredRequestTimeouti  i  i  i  i  r      i+  )r  r  )r  r  r  r  )0r  r   rQ   rJ   rr   r   r'   re   rf   r   r   rB   cr   getresponser   r  r   
getheadersreadparse_attrs_headerput
S3SSLErrorS3SSLCertificateErrorr  r!  pprintpformathasattrr  EPIPE
ECONNRESET	ETIMEDOUTr@   r?   SocketTimeoutExceptioncloser   r  rZ   sleepr   S3RequestErrorr  r  r   coder  )rS   r   r  rJ   rO   rN   r   connrc   http_responseattrsr   
handler_fnerrr1   r1   r2   r     s    




 
zS3.send_requestc             C   s   | j jstd | j|S d|kr*d|d< | j j||}y| j|}W n. tk
rt } z|jd  W Y dd}~X nX |j|d |jd |S )zrWrapper around send_request for slow requests.

        To be able to show progression for small requests
        z$Sending slow request, please wait...actionr   failedN)current_positiondone)rK   progress_meterr   r   progress_classr!  r  r   )rS   r   r(  Zoperation_sizeprogressr   rU  r1   r1   r2   send_request_with_progress"  s    


zS3.send_request_with_progressc
       )   .   C   s,	  | j | |	d kr| jj}	| jr(|	r(d}	|j}
t|
d  }}|j}| jjrdd|d< | jj||}nt	d|  t
j
 }|rt|||}nt|||}||_|	r|sd}	nd|
d< |j \}}}
yftj| j|d }|jj|| j||j x*|
j D ]}|jjt|t|
|  qW |jj  W n tk
rL } z W Y d d }~X n tk
r } z| jjrr|jd	 |rtd
|d |f  td| j|  t
j| j| | j ||||||d ||S t!d|d  W Y d d }~X nX |dkr |j"| t# }yd }|	rft$j$|jj%gg g t&\}}}|rB|jj' }n$| rf| rftdt& d| _d}	|	 s|r|j(tj)kr|r|j*  tj+|j_,x|dkrt-| jj.|}|dkr|j*|}n|}|st/d| jj0dkrt
j
 }|j1| |jj2| | jjr"|j1t3|d |t3|8 }|}| jj0dkrjt
j
 | }t4|| jj0 } t5| | |}|rt
jt-|| jj6 qW |j7 }!|jj' }i }"|j(|"d< |j8|"d< t9|j: |"d< |j* |"d< ||"d< tj;| t<dt=j>|"  W n tk
r  } z W Y d d }~X n t/k
rZ } z| jjrF|jd	  W Y d d }~X n tk
r } zd| jjr|jd	 |rd}#t?|dr|j@r|j@t@jAt@jBt@jCfksdtD|ksdtD|krPtE|tF rPyN|jj' }i }"|j(|"d< |j8|"d< t9|j: |"d< |j* |"d< ||"d< d}#W n tk
rN   tGd Y nX |#std|d |f  td| j|  t
j| j| | j ||||||d |||		S n t<d ||f  t!d|d  W Y d d }~X nX t
j
 }$|$| |"d!< |"d! rt4|"d |"d!  pt4d@|"d"< | jjr:|j1  |jd# |"d dAkrh| jH||"| j |||||||	d&
S |"d d'kr| jI||"| j |||||||	d&
}%|%r|%S tJ|"}&|&jKdBkr|&|"d d,kr| jL||"| j |||||||	d&
S |"d d-kr |r d| _| j ||||||d ||dd.	S d/|"d kr:d|"d d/< |"d d0k sV|"d d1krtd}'|"d d2krd}'|"d d3kr|r|d4 pd5}nN|"d d6krd}'|r|d4 pd5}n&|"d d'krtJ|"}&|&jKdCkrd}'|'rl|rTtd|d tJ|"f  |rtd7|  td| j|  t
j| j| | j ||||||d |||		S td8|  t!d8| tJ|"t<d9|!|"d jd/djMd:f  |"d jd/djMd:}(d;|(k	r(|(|j7 k	r(|"d jd<d=k	r(td> |	rtd?|  | j ||||||d |||		S td8|  t!d8| |"S )DNFzcontent-lengthuploadr  z!Sending file '%s', please wait...z100-continueZexpectrb   r  z Retrying failed request: %s (%s)rc   zWaiting %d sec...r   zUpload failed for: %srd   zQHTTP Expect Continue feature disabled because of no reply of the server in %.2fs.Tr   z3File smaller than expected. Was the file truncated?)delta_positionr   r  rJ   r   r&  z
Response:
r  z[Errno 104]z
[Errno 32]zXCannot retrieve any response status before encountering an EPIPE or ECONNRESET exceptionzUpload failed: %s (%s)zGiving up on '%s' %selapsedspeedr  -  3  )offset
chunk_sizeuse_expect_continuei  r  r  r  r  i  i  )r  r  r  i+  i  i  r   g{Gz?i  z(Retrying on lower speed (throttle=%0.2f)z$Too many failures. Giving up on '%s'z"MD5 sums: computed=%s, received=%sz"'r   zx-amz-server-side-encryptionzaws:kmszMD5 Sums don't match!zRetrying upload of %sr   )r  r  )r  r  r  r  )r  r  r  r  )Nr  rK   use_http_expectr   rJ   r"  r  r  r  r   rZ   r+   r*   rQ   rr   r'   re   rf   r  
putrequestr   r   keys	putheaderr   
endheadersr   r!  r  r   r  r  r$  S3UploadErrorseekr   selectsockEXPECT_CONTINUE_TIMEOUTr  r   CONTINUEr  _CS_REQ_SENT_HTTPConnection__stateminr#  r  	limitrater   Zwrapper_send_bodyrB   floatmaxthrottle_max	hexdigestr  r   r  r  r   r  r  r  r  r  r  r  r@   r?   r  r	   r  r  r   r  r  r   ))rS   r   r+  r(  bufferZthrottler  r  r  r  rJ   	size_left
size_totalr   r  timestamp_startZsha256_hashrO   rN   r  headerr   md5_hashr  readablewritableZexceptionallr   
start_timeZlimitrate_throttlereal_durationexpected_durationZmd5_computedr   Zknown_errortimestamp_endr  r  Z	try_retrymd5_from_s3r1   r1   r2   r$  :  st   



"

















",

",zS3.send_filec       
      C   s   t j  }t| ||||}|j| |j }t j  }	|	| |d< ||d< |d rbt|d |d  phtd|d< |d rt|d dkrtt|d d|S )	Nr  r&  r   r  r   rJ  r  r   )rZ   r%   Zupload_all_partsZcomplete_multipart_uploadr  r   r  r   )
rS   r+  rJ   rc   r&  r%  r  r  r   r  r1   r1   r2   r  7  s    
(zS3.send_file_multipartc             C   s   | j |||||S )N)r  )rS   rP  rQ  r&  rJ   r%  r1   r1   r2   rN  G  s    zS3.copy_file_multipartc          8   C   s  | j | |j \}}}|j}	| jjr>d|d< | jj|d}
ntd|	  tj }d }ytj	| j
|d }|jj|| j||j x*|j D ]}|jjt|t||  qW |dkrtd|  |jjdd|  |jj  i }|jj }|j|d	< |j|d
< t|j |d< d|d kr8t|d d }||d< tdtj|  W n& tk
rv } z W Y d d }~X n  ttfk
rt } z| jjr|
jd t |dr|j!r|j!t!j"t!j#t!j$fksdt%|ksdt%|krt&|t' r tj(| |rTt)d|d |f  t)d| j*|  tj+| j*| | j,|||||d S t-d|d  W Y d d }~X nX |d	 d5kr|j. |d< | j/||| j,||||S |d	 dkr|j. |d< | j0||| j,||||}|r|S t1||d	 dkr|j. |d< | j2||| j,||||S |d	 dkr@|j. |d< t1||d	 dk s\|d	 dkrp|j. |d< t1||dkrt3 }t4|d d  }|| }|}| jjr||
_5||
_6||
_7y |dkr|j.d}t8|dkst9x||k r|| jj:kr| jj:p|}| jj;dkr tj }|j.|}t8|dkr@t<d!| jj;dkrtj | }t=|| jj; }||krtj+||  |j>| |dkr|j?| |t8|7 }| jjr|
j?t8|d" qW tj@| W n tAk
r    Y n  ttfk
r } z| jjr|
jd t |drJ|j!rJ|j!t!j"t!j#t!j$fksfdt%|ksfdt%|krvt&|t' rv tj(| |rt)d|d |f  t)d| j*|  tj+| j*| | j,|||||d S t-d|d  W Y d d }~X nX |jB  tj }| jjr |
j?  |
jd# |d j	d$d%jCd&}d'|d krly|d d( }W n tDk
rj   Y nX d)|kr|dkr|jE |d(< n\ytF|	|d(< W nJ tk
r } z,|j!t!jGkrt)d*|	|f  t)d+ W Y d d }~X nX |j	d(|k|d,< || |d-< ||d.< |d- r0t=|d. |d-  p6t=d6|d/< |d. |t4|d d   kr~t)d0|t4|d d   |d. f  td1|j	d(  d)|kr|d,  r|d j	d2d3krt)d4|j	d(|f  |S )7NZdownloadr  r   z#Receiving file '%s', please wait...rb   zRequesting Range: %d .. endZRangez	bytes=%d-r   r  rJ   zx-amz-meta-s3cmd-attrszs3cmd-attrsz
Response:
r  r  z[Errno 104]z
[Errno 32]z Retrying failed request: %s (%s)rc   zWaiting %d sec...r   zDownload failed for: %s-  3  r   i  i  i  r  i+  zcontent-lengthzEOF from S3!)r  r  r  rd   z"'zx-amz-meta-s3tools-gpgencr   r   zUnable to open file: %s: %sz(Unable to verify MD5. Assume it matches.Zmd5matchr  r&  r  z4Reported size (%s) does not match received size (%s)zReceiveFile: Computed MD5 = %szx-amz-server-side-encryptionzaws:kmsz5MD5 signatures do not match: computed=%s, received=%s)r  r  r   )Hr  rr   r  rK   r  r  r   rZ   r'   re   rf   r  r  r   r   r  r  r   r   r  r  r   r  r   r  r  r  r  r   r  r!  r  r  r  r  r  r  r@   r?   r  r  r   r  r  r*  S3DownloadErrorr  r  r  r   r  r   r"  
total_sizeinitial_positionr  rB   AssertionError
recv_chunkr  r   r  writer   r  r  flushr   KeyErrorr  r   ENOENT)rS   r   r+  r(  r-  r  rO   rN   rJ   r   r  r  r  r  r   r  r  r   r  r  r  r  r  r   Z
this_chunkr  r  r  r  r  r1   r1   r2   r*  L  s&   







"













"



, *zS3.recv_file)Nr   )NNNr   r   )NNNr   r   )NNNr   )NN)F)N)N)N)N)N)N)Nrd   )r   rd   )NNrd   F)NNrd   )NNrd   r   )Nr   r   )Nr   r   )Nr   r   )Nr   r   )Nr   )NF)NNNNrd   N)r   r   )rd   )rd   )Mrs   rt   ru   r"   r  Ztargetsr  codesr  rT   r   rf   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r)  r.  r6  r4  r=  rD  rH  rV  rW  rZ  r   rK  rO  r\  r]  r^  r`  ra  rb  rc  rd  re  rf  rj  rg  rp  rm  rr  rv  ry  rz  r~  r   r  r  r  r  r  r   r  r$  r  rN  r*  r1   r1   r1   r2   rv      s   



4


!	






W
 
  
 


	
	
6

 
* 


%*f
 |

rv   c             C   s2   i }x(| j dD ]}|j d\}}|||< qW |S )Nr   :)rA   )Zattrs_headerr  attrr:  valr1   r1   r2   r    s
    r  c             C   s@   t t| }t|j }t|}|d dkr8|dd }t|S )Nr   
r   r   r   )r   r   r   digestr   )rQ   mZ	base64md5r1   r1   r2   r     s    r   i   )[
__future__r   r   r  r   rZ   r  r:   r  r  Zxml.saxr   socketr   r  rw  r   r   r   r	   r  r
   r   ImportErrorurllib.parsebase64r   r   r  hashlibr   	BaseUtilsr   r   r   r   r   r   Utilsr   r   r   r   r   r   r   r   r   r   r    r!   r"   r#   
ExceptionsZ	MultiPartr%   r&   r'   Cryptor(   r)   r*   r+   r,   Zctypesr-   r7   ZMagicr/   r3   	TypeErrorr  Z
MAGIC_MIMEloadAttributeErrorr  r   r@   Z	error_strr9   r8   rE   r  r  __all__r9  rG   rv   appendr  r   r1   r1   r1   r2   <module>	   s    (
P              >
