o ~_C@sddlmZddlmZddlmZddlZddlZddlZddl Z ddl Z ddl m Z ddl ZddlmZddlmZddlmZGd d d ejjZejd edS) )print_function)division)inputN)DEFAULT_BUFFER_SIZE)BackendException)config)logc@seZdZdZejdZdZdZ dZ ddgZ dZ d Z d Zd d Zd dZddZddZddZddZddZddZddZddZdd Zd!d"Zd#d$Zd%S)& ADBackendz Backend for Amazon Drive. It communicates directly with Amazon Drive using their RESTful API and does not rely on externally setup software (like acd_cli). z~/.duplicity_ad_oauthtoken.jsonzhttps://www.amazon.com/ap/oaz$https://api.amazon.com/auth/o2/tokenz'https://breunig.xyz/duplicity/copy.htmlzclouddrive:read_otherzclouddrive:writez=amzn1.application-oa2-client.791c9c2d78444e85a32eb66f92eb6bcc@5b322c6a37b25f16d848a6a556eddcc30314fc46ae65c87068ff1bc4588d715bCDuplicityFormBoundaryd66364f7f8924f7e9d478e19cf4b871d114a1e00262542cCstjj||d|_d|_i|_d|_|j d|_ t j dkr%t dz ddladdlmaWn ty<tdw||dS) Nz%https://drive.amazonaws.com/drive/v1/z/https://content-na.drive.amazonaws.com/cdproxy//l zxYour --volsize is bigger than 10 GiB, which is the maximum file size on Amazon Drive that does not require work arounds.r) OAuth2Sessiona Amazon Drive backend requires python-requests and python-requests-oauthlib to be installed. For Debian and derivates use: apt-get install python-requests python-requests-oauthlib For Fedora and derivates use: yum install python-requests python-requests-oauthlib) duplicitybackendBackend__init__ metadata_url content_url names_to_idsbackup_target_idpathlstrip backup_targetrvolsizer FatalErrorrequestsrequests_oauthlibr ImportErrorrinitialize_oauth2_sessionresolve_backup_target)self parsed_urlr">/usr/lib/python3/dist-packages/duplicity/backends/adbackend.pyr<s(   zADBackend.__init__c sfdd}d}ztj }t|}Wdn1swYWnty=}z td|WYd}~nd}~wwtjj j |jj dj |d_ |dur^j j j jd}|jtjjkrpd}|durtjr~tjstdjj j\}}td td t|td td d d d}j j j j |d}j jd}|!|||} d| vsd| vrtd| d_| d_"dS)z1Setup or refresh oauth2 session with Amazon Drivec s~z!tjd}t||WdWdS1swYWdSty>}ztdj|fWYd}~dSd}~ww)zStores oauth2 token on diskwNzCould not save the OAuth2 token to %s. This means you may need to do the OAuth2 authorization process again soon. Original error: %s)openOAUTH_TOKEN_PATHjsondump ExceptionrError)tokenferrr r"r# token_updateras&z:ADBackend.initialize_oauth2_session..token_updaterNzMCould not load OAuth2 token. Trying to create a new one. (original error: %s)) client_id client_secret)scope redirect_urir+auto_refresh_kwargsauto_refresh_urlr/zaccount/endpointzThe OAuth2 token could not be loaded from %s and you are not running duplicity interactively, so duplicity cannot possibly access Amazon Drive.zIn order to allow duplicity to access Amazon Drive, please open the following URL in a browser and copy the URL of the page you see after authorization here:zURL of the resulting page: zhttp://zhttps://)r1authorization_response metadataUrl contentUrlz1Could not retrieve endpoint URLs for this account)#r%r&r'loadIOErrorrNoticer CLIENT_ID OAUTH_SCOPEOAUTH_REDIRECT_URL CLIENT_SECRETOAUTH_TOKEN_URL http_client refresh_tokengetr status_codercodesoksysstdoutisattystdinrauthorization_urlOAUTH_AUTHORIZE_URLprintrreplacestrip fetch_tokenraise_for_statusr) r r/r+r,r-endpoints_responserM_ redirected_tourlsr"r.r#r^sz         z#ADBackend.initialize_oauth2_sessioncs|j|jd}|ddd}dd|jdDD]Rtdd}|kr1|d }| |jd ||f}fd d|D}t |d krVt d |fqt |dkrc|dd}qt d||}qt d|||_dS)z/Resolve node id for remote backup target folderz)nodes?filters=kind:FOLDER AND isRoot:truedataridcSsg|]}|r|qSr"r").0xr"r"r# sz3ADBackend.resolve_backup_target..r z^[A-Za-z0-9_-]**z4nodes?filters=kind:FOLDER AND name:%s AND parents:%scsg|] }|dkr|qS)name)rErZr, componentr"r#r\sz[There are multiple folders with the same name below one parent. ParentID: %s FolderName: %sr7z'Folder %s does not exist yet. Creating.zBackup target folder has id: %sN)rCrErr'rsplitresearchgroupread_all_pageslenrrDebugmkdirr)r responseparent_node_idquerymatches candidatesr"r`r#rs0   zADBackend.resolve_backup_targetcCs||jvr ||j|S)z.Find id of remote file in backup target folder)r_listrEr remote_filenamer"r"r# get_file_ids  zADBackend.get_file_idcCs>||gdd}|jj|jdt|d}||dS)z/Create a new folder as a child of a parent nodeFOLDER)r^parentskindnodes)rXrY)rCpostrr'dumpsrS)r rl folder_namerXrkr"r"r#rjs zADBackend.mkdirccs|j}td|dt|d|VdVdV|} |t}|r.|Vnnq#Wdn1s:wYtd|d |VdS) z>Generator for multipart/form-data file upload from source filez9--%s Content-Disposition: form-data; name="metadata" z%s z--%s sKContent-Disposition: form-data; name="content"; filename="i_love_backups" s*Content-Type: application/octet-stream TNz --%s-- multipart/form-data; boundary=%s)MULTIPART_BOUNDARYstrencoder'ryr%readr)r metadata source_pathboundarystreamr,r"r"r#multipart_streams.     zADBackend.multipart_streamcCsg}d}d|vr dnd} |||}|j|}|jdkr'td|j|f|}d|vr?t|dd kr?||dn |St||d krM |Sd |vrT |S|d }q ) z5Iterates over nodes API URL until all pages were readr6?z &startToken=z ?startToken=Tz*Pagination failed with status=%s on URL=%srXrcount nextToken)rCrErFrr'rhextend)r urlresult next_token token_param paginated_urlrkparsedr"r"r#rgs.    zADBackend.read_all_pagescCs||td|)z@Report error when file already existed in location and delete itzUpload failed, because there was a file with the same name as %s already present. The file was deleted, and duplicity will retry the upload unless the retry limit has been reached.)_deleterrqr"r"r#raise_for_existing_files z!ADBackend.raise_for_existing_filec Cs|j|jd}||d}tj|j}||kr(t d|j||f||j vr9t d|| ||d|jgd}dd|ji}|||}|jj|jd ||d } | jd kre||nr| jd krrt d |ne| jdks|| jdkrt d|| jtjftjd} | dkr| d8} td||d} || krt ddS| dkrt d| dq||| dkst d|t d|| jf| | } d| vrt d|| f| d|j | d<dS)z#Upload a local file to Amazon Drivez account/quota availablez[Out of space: trying to store "%s" (%d bytes), but only %d bytes available on Amazon Drive.z^File %s seems to already exist on Amazon Drive. Deleting before attempting to upload it again.FILE)r^rvruz Content-Typer{znodes?suppress=deduplication)rXheadersiz%s uploaded successfullyiiz%s upload failed with timeout status code=%d. Speculatively waiting for %d seconds to see if Amazon Drive finished the upload anywayrr7sizez-Upload turned out to be successful after all.Nz.Uploaded file is not yet there, %d tries left.z<%s upload failed and file did not show up within time limit.z0%s upload returned an undesirable status code %srYzW%s was uploaded, but returned JSON does not contain ID of new file. Retrying. JSON: %sr^)rCrErrSr'osrgetsizer^rrrrirrr|rrxrrFrInfortimeouttimesleep_query) r rrrquotar source_sizerrrXrktries remote_sizerr"r"r#_puts           zADBackend._putcCs|d?}||}|durtd||jj|jd|ddd}||jtdD] }|r7| |q.| WddS1sGwYdS) zDownload file from Amazon DrivewbNz1File "%s" cannot be downloaded: it does not existz/nodes/z/contentT)r) chunk_size) r%rsrrCrErrS iter_contentrwriteflush)r rr local_path local_filefile_idrkchunkr"r"r#_getes$    "zADBackend._getcCsL||}|dur ddiS|j|jd|}|d|ddiS)z)Retrieve file size info from Amazon DriveNrrnodes/contentProperties)rsrCrErrSr'r rrrrkr"r"r#rws zADBackend._querycCs8||jd|jd}dd|D|_t|jS)z(List files in Amazon Drive backup folderrz/children?filters=kind:FILEcSsi|] }|d|dqS)r^rYr"r_r"r"r# sz#ADBackend._list..)rgrrrlistkeys)r filesr"r"r#rpszADBackend._listcCsH||}|durtd||j|jd|}||j|=dS)zDelete file from Amazon DriveNz.File "%s" cannot be deleted: it does not existztrash/)rsrrCputrrSrrr"r"r#rs  zADBackend._deleteN)__name__ __module__ __qualname____doc__rr expanduserr&rNrBr@r?r>rAr|rrrrsrjrrgrrrrrprr"r"r"r#r &s. "M   J r ad) __future__rrbuiltinsros.pathrr'rIrrdiorduplicity.backendrduplicity.errorsrrrrrr register_backendr"r"r"r#s"       v