o
    i+F                     @   s   d dl mZ d dl mZ d dl mZ d dlmZ d dlT d dlmZm	Z	m
Z
 d dlmZ d dlmZ d	d
lZd	d
lZeeZG dd deZd
S )   )http)
exceptions)Bucket)_make_range_string)*)	to_stringurlsplitparse_qs)BaseCryptoProviderClientError    Nc                       s   e Zd ZdZ									d$ fdd	Zdd	 Z		d% fd
d	Zd%ddZ			d&ddZ					d'ddZ				d&ddZ
d(ddZ		d%ddZd& fdd	Zd& fdd	Zd( fdd	Zd( fdd	Z	d(d d!Zd"d# Z  ZS ))CryptoBucketu  用于加密Bucket和Object操作的类，诸如上传、下载Object等。创建、删除bucket的操作需使用Bucket类接口。

    用法（假设Bucket属于杭州区域） ::

        >>> import oss2
        >>> auth = oss2.Auth('your-access-key-id', 'your-access-key-secret')
        >>> bucket = oss2.CryptoBucket(auth, 'http://oss-cn-hangzhou.aliyuncs.com', 'your-bucket', oss2.LocalRsaProvider())
        >>> bucket.put_object('readme.txt', 'content of the object')
        <oss2.models.PutObjectResult object at 0x029B9930>

    :param auth: 包含了用户认证信息的Auth对象
    :type auth: oss2.Auth

    :param str endpoint: 访问域名或者CNAME
    :param str bucket_name: Bucket名
    :param crypto_provider: 客户端加密类。该参数默认为空
    :type crypto_provider: oss2.crypto.BaseCryptoProvider
    :param bool is_cname: 如果endpoint是CNAME则设为True；反之，则为False。

    :param session: 会话。如果是None表示新开会话，非None则复用传入的会话
    :type session: oss2.Session

    :param float connect_timeout: 连接超时时间，以秒为单位。

    :param str app_name: 应用名。该参数不为空，则在User Agent中加入其值。
        注意到，最终这个字符串是要作为HTTP Header的值传输的，所以必须要遵循HTTP标准。

    :param bool enable_crc: 如果开启crc校验则设为True；反之，则为False

    FN Tc                    s   t |ts	tdtd| tt| j||||||||	|
|||d || _	i | _
t | _| jrBtjd | j d t | _d S tjd t | _d S )Nz9crypto_provider must be an instance of BaseCryptoProviderzInit CryptoBucket: {0})proxiesregioncloudbox_idis_path_style/)
isinstancer
   r   loggerdebugformatsuperr   __init__crypto_providerupload_contexts	threadingLockupload_contexts_lockapp_namer   
USER_AGENTOSS_ENCRYPTION_CLIENT
user_agent)selfauthendpointbucket_namer   is_cnamesessionconnect_timeoutr    
enable_crcr   r   r   r   	__class__ F/home/ubuntu/.local/lib/python3.10/site-packages/oss2/crypto_bucket.pyr   2   s   


zCryptoBucket.__init__c                 C   s.   d|vr| j |d< d S |d  dt 7  < d S )Nz
User-Agentr   )r#   r"   )r$   headersr.   r.   r/   _init_user_agentN   s   zCryptoBucket._init_user_agentc                    sX   t d t|}| | | j }| j||j}|	|}t
t| ||||S )u\  上传一个普通文件。

        用法 ::
            >>> bucket.put_object('readme.txt', 'content of readme.txt')
            >>> with open(u'local_file.txt', 'rb') as f:
            >>>     bucket.put_object('remote_file.txt', f)

        :param mat_desc: map，对象文件的description
        :param key: 上传到OSS的文件名

        :param data: 待上传的内容。
        :type data: bytes，str或file-like object

        :param headers: 用户指定的HTTP头部。可以指定Content-Type、Content-MD5、x-oss-meta-开头的头部等
        :type headers: 可以是dict，建议是oss2.CaseInsensitiveDict

        :param progress_callback: 用户指定的进度回调函数。可以用来实现进度条等功能。参考 :ref:`progress_callback` 。

        :return: :class:`PutObjectResult <oss2.models.PutObjectResult>`
        z#Start to put object to CryptoBucket)r   r   r   CaseInsensitiveDictr1   r   create_content_materialmake_encrypt_adaptercipherto_object_metar   r   
put_object)r$   keydatar0   progress_callbackcontent_crypto_materialr,   r.   r/   r7   T   s   




zCryptoBucket.put_objectc                 C      t d)u   使用加签的url上传对象

        :param sign_url: 加签的url
        :param data: 待上传的数据
        :param headers: 用户指定的HTTP头部。可以指定Content-Type、Content-MD5、x-oss-meta-开头的头部等，必须和签名时保持一致
        :param progress_callback: 用户指定的进度回调函数。参考 :ref:`progress_callback`
        :return:
        1The operation is not support for CryptoBucket nowr   )r$   sign_urlr9   r0   r:   r.   r.   r/   put_object_with_urlu   s   
z CryptoBucket.put_object_with_urlc                 C   r<   Nz-The operation is not support for CryptoBucketr   )r$   r8   positionr9   r0   r:   init_crcr.   r.   r/   append_object      zCryptoBucket.append_objectc              	   C   s  |rt dt|}| | d}d}|r]|d du r$|d r$t d| j|d |d \}	}
|	|
f}t|}|r?||d< |d rS|d |d k rS|d |d  }td	||| td		| j
t|||| | jd
| j
|||d}td	|j|j t||| j| j|dS )u\  下载一个文件。

        用法 ::

            >>> result = bucket.get_object('readme.txt')
            >>> print(result.read())
            'hello world'

        :param key: 文件名
        :param byte_range: 指定下载范围。参见 :ref:`byte_range`

        :param headers: HTTP头部
        :type headers: 可以是dict，建议是oss2.CaseInsensitiveDict

        :param progress_callback: 用户指定的进度回调函数。参考 :ref:`progress_callback`
        :param process: oss文件处理，如图像服务等。指定后process，返回的内容为处理后的文件。

        :param params: http 请求的查询字符串参数
        :type params: dict

        :return: file-like object

        :raises: 如果文件不存在，则抛出 :class:`NoSuchKey <oss2.exceptions.NoSuchKey>` ；还可能抛出其他异常
        9Process object operation is not support for Crypto Bucketr   r   Nr   :Don't support range get while start is none and end is notrangeQadjust range of get object, byte_range: {0}, adjust_byte_range: {1}, discard: {2}z[Start to get object from CryptoBucket: {0}, key: {1}, range: {2}, headers: {3}, params: {4}GET)r0   paramsz.Get object done, req_id: {0}, status_code: {1}r   discard)r   r   r2   r1   r   adjust_ranger   r   r   r   r'   r   _do
request_idstatusGetObjectResultr+   )r$   r8   
byte_ranger0   r:   processrJ   rL   range_stringstartendadjust_byte_rangerespr.   r.   r/   
get_object   s:   

zCryptoBucket.get_objectc                 C   s  t t|j}|rtj|v rtdt|}| | d}d}|rg|d s.|d r.td| j	
|d |d \}}	||	f}
t|
}|rI||d< |d r]|
d |d k r]|d |
d  }td||
| td| j||| | jd	||d
}t||| j| j	|dS )u1  使用加签的url下载文件

        :param sign_url: 加签的url
        :param byte_range: 指定下载范围。参见 :ref:`byte_range`

        :param headers: HTTP头部
        :type headers: 可以是dict，建议是oss2.CaseInsensitiveDict，必须和签名时保持一致

        :param progress_callback: 用户指定的进度回调函数。参考 :ref:`progress_callback`

        :return: file-like object

        :raises: 如果文件不存在，则抛出 :class:`NoSuchKey <oss2.exceptions.NoSuchKey>` ；还可能抛出其他异常
        rE   r   r   r   rF   rG   rH   z\Start to get object with url from CryptoBucket: {0}, sign_url: {1}, range: {2}, headers: {3}rI   )r0   rK   )r	   r   queryr   PROCESSr   r   r2   r1   r   rM   r   r   r   r   r'   _do_urlrQ   r+   )r$   r>   rR   r0   r:   rZ   rL   rT   rU   rV   rW   rX   r.   r.   r/   get_object_with_url   s:   



z CryptoBucket.get_object_with_urlc                 C   r<   )Nz.The operation is not support for Crypto Bucketr   )r$   r8   select_meta_paramsr.   r.   r/   create_select_object_meta      z&CryptoBucket.create_select_object_metac                 C   r<   r@   r   )r$   r8   sqlr:   select_paramsr.   r.   r/   select_object   rD   zCryptoBucket.select_objectc                    s   t |}| | |r|jstdtd|j|j |jr2| j	j
|j|j}|s1tdn	| j	j
|j|_| j	 }||_|||}tt| ||}|S )u  客户端加密初始化分片上传。

        :param params
        :param upload_context

        :param headers: HTTP头部
        :type headers: 可以是dict，建议是oss2.CaseInsensitiveDict

        :return: :class:`InitMultipartUploadResult <oss2.models.InitMultipartUploadResult>`
        返回值中的 `crypto_multipart_context` 记录了加密Meta信息，在upload_part时需要一并传入
        zSIt is not support none upload_context and must specify data_size of upload_context zNStart to init multipart upload by CryptoBucket, data_size: {0}, part_size: {1}z:part_size is invalid for multipart upload for CryptoBucket)r   r2   r1   	data_sizer   r   infor   	part_sizer   r5   is_valid_part_sizedetermine_part_sizer3   r;   r6   r   r   init_multipart_upload)r$   r8   r0   rJ   upload_contextresr;   rX   r,   r.   r/   ri     s$   



z"CryptoBucket.init_multipart_uploadc                    s   t d|| t|}| | |r|}ntd|j}	|	j| j	j
jks.|	j| j	jkr5d}
t|
| |	||}| j	|	j}| j	|	j}|j|d  }| j	j
|}t|	j
}|||| | j	||}tt| ||||||}|S )u  客户端加密上传一个分片。

        :param upload_context:
        :param str key: 待上传文件名，这个文件名要和 :func:`init_multipart_upload` 的文件名一致。
        :param str upload_id: 分片上传ID
        :param int part_number: 分片号，最小值是1.
        :param data: 待上传数据。
        :param progress_callback: 用户指定进度回调函数。可以用来实现进度条等功能。参考 :ref:`progress_callback` 。

        :param headers: 用户指定的HTTP头部。可以指定Content-MD5头部等
        :type headers: 可以是dict，建议是oss2.CaseInsensitiveDict

        :return: :class:`PutObjectResult <oss2.models.PutObjectResult>`
        zMStart to upload multipart of CryptoBucket, upload_id = {0}, part_number = {1}zWCould not init upload context, upload contexts flag is False and upload context is nonez@Envelope or data encryption/decryption algorithm is inconsistentr   )r   re   r   r   r2   r1   r   r;   cek_algr   r5   algwrap_algInconsistentErrorr6   decrypt_encrypted_keyencrypted_keydecrypt_encrypted_ivencrypted_ivrf   calc_offsetcopy
initializer4   r   r   upload_part)r$   r8   	upload_idpart_numberr9   r:   r0   rj   contextr;   err_msg	plain_keyplain_ivoffsetcounterr5   rX   r,   r.   r/   rw   '  s4   


zCryptoBucket.upload_partc              
      s^   t d| t|}| | ztt| ||||}W |S  t	y. } z|d}~ww )u  客户端加密完成分片上传，创建文件。
        当所有分片均已上传成功，才可以调用此函数

        :param str key: 待上传的文件名，这个文件名要和 :func:`init_multipart_upload` 的文件名一致。
        :param str upload_id: 分片上传ID

        :param parts: PartInfo列表。PartInfo中的part_number和etag是必填项。其中的etag可以从 :func:`upload_part` 的返回值中得到。
        :type parts: list of `PartInfo <oss2.models.PartInfo>`

        :param headers: HTTP头部
        :type headers: 可以是dict，建议是oss2.CaseInsensitiveDict

        :return: :class:`PutObjectResult <oss2.models.PutObjectResult>`
        zCStart to complete multipart upload of CryptoBucket, upload_id = {0}N)
r   re   r   r   r2   r1   r   r   complete_multipart_uploadr   )r$   r8   rx   partsr0   rX   er,   r.   r/   r   V  s   

z&CryptoBucket.complete_multipart_uploadc              
      sZ   t d| t|}| | ztt| ||}W |S  t	y, } z|d}~ww )uU  取消分片上传。

        :param headers: 可以是dict，建议是oss2.CaseInsensitiveDict
        :param str key: 待上传的文件名，这个文件名要和 :func:`init_multipart_upload` 的文件名一致。
        :param str upload_id: 分片上传ID

        :return: :class:`RequestResult <oss2.models.RequestResult>`
        z@Start to abort multipart upload of CryptoBucket, upload_id = {0}N)
r   re   r   r   r2   r1   r   r   abort_multipart_uploadr   )r$   r8   rx   r0   rX   r   r,   r.   r/   r   p  s   	

z#CryptoBucket.abort_multipart_uploadc                 C   r<   )u!  分片拷贝。把一个已有文件的一部分或整体拷贝成目标文件的一个分片。

        :param target_part_number:
        :param target_upload_id:
        :param target_key:
        :param source_key:
        :param source_bucket_name:
        :param byte_range: 指定待拷贝内容在源文件里的范围。参见 :ref:`byte_range`

        :param headers: HTTP头部
        :type headers: 可以是dict，建议是oss2.CaseInsensitiveDict

        :return: :class:`PutObjectResult <oss2.models.PutObjectResult>`
        r=   r   )r$   source_bucket_name
source_keyrR   
target_keytarget_upload_idtarget_part_numberr0   r.   r.   r/   upload_part_copy  s   zCryptoBucket.upload_part_copyc                 C   r<   r@   r   )r$   r8   rS   r.   r.   r/   process_object  r`   zCryptoBucket.process_object)	FNNr   TNNNF)NN)NNN)NNNNN)N)__name__
__module____qualname____doc__r   r1   r7   r?   rC   rY   r]   r_   rc   ri   rw   r   r   r   r   __classcell__r.   r.   r,   r/   r      sT     
!

@

2
&/
r   )r   r   r   r   apir   modelscompatr   r   r	   cryptor
   r   ru   r   logging	getLoggerr   r   r   r.   r.   r.   r/   <module>   s   
