__  __    __   __  _____      _            _          _____ _          _ _ 
 |  \/  |   \ \ / / |  __ \    (_)          | |        / ____| |        | | |
 | \  / |_ __\ 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 -*-
#
# Copyright 2015 Yigal Asnis
# Copyright 2021 Jindrich Makovicka
#
# This file 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.
#
# It 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 os
import pickle

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


class GDriveBackend(duplicity.backend.Backend):
    """Connect to remote store using Google Drive API V3"""

    PAGE_SIZE = 100
    MIN_RESUMABLE_UPLOAD = 5 * 1024 * 1024

    def __init__(self, parsed_url):
        duplicity.backend.Backend.__init__(self, parsed_url)
        try:
            from googleapiclient.discovery import build
            from google.oauth2.service_account import Credentials
        except ImportError as e:
            raise BackendException(
                f"""GDrive backend requires Google API client installation.
Please read the manpage for setup details.
Exception: {str(e)}"""
            )

        # Note Google has 2 drive methods, `Shared(previously Team) Drives` and `My Drive`
        #   both can be shared but require different addressing
        # For a Google Shared Drives folder
        # ---------------------------------
        # Share Drive ID specified as a query parameter in the backend URL.
        # Example:
        #  gdrive://developer.gserviceaccount.com/target-folder/?driveID=<SHARED DRIVE ID>
        #
        # For a Google My Drive based shared folder
        # -----------------------------------------
        # MyDrive folder ID specified as a query parameter in the backend URL
        #
        # Example
        #  export GOOGLE_SERVICE_ACCOUNT_URL=<serviceaccount-name>@<serviceaccount-name>.iam.gserviceaccount.com
        #  gdrive://${GOOGLE_SERVICE_ACCOUNT_URL}/<target-folder-name/>?myDriveFolderID=<google-myDrive-folder-id>
        #
        # both methods use a Google Services Account
        # export GOOGLE_SERVICE_JSON_FILE=<serviceaccount-credentials.json>
        # export GOOGLE_SERVICE_ACCOUNT_URL=<serviceaccount-name>@<serviceaccount-name>.iam.gserviceaccount.com
        #
        # Note that a local http server will be created on port 8080 to receive the redirect from the Google
        # OAuth service. If you are running on a remote server, you will need to port forward 8080 from the machine
        # which will do the web based authentication.

        self.shared_drive_corpora = {}
        self.shared_drive_id = {}
        self.shared_drive_flags_include = {}
        self.shared_drive_flags_support = {}
        self.shared_root_folder_id = None
        if "driveID" in parsed_url.query_args:
            self.shared_drive_corpora = {"corpora": "drive"}
            self.shared_drive_id = {"driveId": parsed_url.query_args["driveID"][0]}
            self.shared_drive_flags_include = {"includeItemsFromAllDrives": True}
            self.shared_drive_flags_support = {"supportsAllDrives": True}
        elif "myDriveFolderID" in parsed_url.query_args:
            self.shared_drive_corpora = {"corpora": "user"}
            self.shared_drive_flags_include = {"includeItemsFromAllDrives": True}
            self.shared_drive_flags_support = {"supportsAllDrives": True}
            self.shared_root_folder_id = parsed_url.query_args["myDriveFolderID"][0]
        else:
            raise BackendException(
                "gdrive: backend requires a query paramater should either be driveID or myDriveFolderID"
            )
        if parsed_url.username is not None:
            client_id = f"{parsed_url.username}@{parsed_url.hostname}"
        else:
            client_id = parsed_url.hostname

        if "GOOGLE_SERVICE_JSON_FILE" in os.environ:
            credentials = Credentials.from_service_account_file(os.environ["GOOGLE_SERVICE_JSON_FILE"])
            if credentials.service_account_email != client_id:
                raise BackendException(
                    f"Service account email in the JSON file ({credentials.service_account_email}) "
                    f"does not match the URL ({client_id})"
                )

        elif "GOOGLE_CLIENT_SECRET_JSON_FILE" in os.environ and "GOOGLE_CREDENTIALS_FILE" in os.environ:
            from google_auth_oauthlib.flow import InstalledAppFlow
            from google.auth.transport.requests import Request

            credentials = None
            if os.path.exists(os.environ["GOOGLE_CREDENTIALS_FILE"]):
                with open(os.environ["GOOGLE_CREDENTIALS_FILE"], "rb") as token:
                    credentials = pickle.load(token)

            # If there are no (valid) credentials available, let the user log in.
            if not credentials or not credentials.valid:
                if credentials and credentials.expired and credentials.refresh_token:
                    credentials.refresh(Request())
                else:
                    flow = InstalledAppFlow.from_client_secrets_file(
                        os.environ["GOOGLE_CLIENT_SECRET_JSON_FILE"],
                        ["https://www.googleapis.com/auth/drive.file"],
                    )

                    if flow.client_config["client_id"] != client_id:
                        raise BackendException(
                            f"Client ID in the JSON file ({flow.client_config['client_id']}) "
                            f"does not match the URL ({client_id})"
                        )

                    flow_args = {"open_browser": False}
                    if "GOOGLE_OAUTH_LOCAL_SERVER_PORT" in os.environ:
                        flow_args["port"] = int(os.environ["GOOGLE_OAUTH_LOCAL_SERVER_PORT"])
                    if "GOOGLE_OAUTH_LOCAL_SERVER_HOST" in os.environ:
                        flow_args["host"] = os.environ["GOOGLE_OAUTH_LOCAL_SERVER_HOST"]
                    credentials = flow.run_local_server(**flow_args)
                # Save the credentials for the next run
                with open(os.environ["GOOGLE_CREDENTIALS_FILE"], "wb") as token:
                    pickle.dump(credentials, token)

            if credentials.client_id != client_id:
                raise BackendException(
                    f"Client ID in the credentials file ({credentials.client_id}) does not match the URL ({client_id})"
                )

        else:
            raise BackendException(
                "GOOGLE_SERVICE_JSON_FILE or GOOGLE_CLIENT_SECRET_JSON_FILE environment "
                "variable not set. Please read the manpage to fix."
            )

        self.drive = build("drive", "v3", credentials=credentials)

        if self.shared_drive_id:
            parent_folder_id = self.shared_drive_id["driveId"]
        elif self.shared_root_folder_id:
            parent_folder_id = self.shared_root_folder_id
        else:
            parent_folder_id = "root"

        # Fetch destination folder entry and create hierarchy if required.
        folder_names = parsed_url.path.split("/")
        for folder_name in folder_names:
            if not folder_name:
                continue
            q = (
                "name = '"
                + folder_name
                + "' and '"
                + parent_folder_id
                + "' in parents and mimeType = 'application/vnd.google-apps.folder' and trashed=false"
            )
            results = (
                self.drive.files()
                .list(
                    q=q,
                    pageSize=1,
                    fields="files(name,id),nextPageToken",
                    **self.shared_drive_corpora,
                    **self.shared_drive_id,
                    **self.shared_drive_flags_include,
                    **self.shared_drive_flags_support,
                )
                .execute()
            )
            file_list = results.get("files", [])
            if len(file_list) == 0:
                file_metadata = {
                    "name": folder_name,
                    "mimeType": "application/vnd.google-apps.folder",
                    "parents": [parent_folder_id],
                }
                file_metadata.update(self.shared_drive_id)
                folder = (
                    self.drive.files()
                    .create(
                        body=file_metadata,
                        fields="id",
                        **self.shared_drive_flags_support,
                    )
                    .execute()
                )
            else:
                folder = file_list[0]

            parent_folder_id = folder["id"]

        self.folder = parent_folder_id
        self.id_cache = {}

    def file_by_name(self, filename):
        from googleapiclient.errors import HttpError

        filename = os.fsdecode(filename)

        if filename in self.id_cache:
            # It might since have been locally moved, renamed or deleted, so we
            # need to validate the entry.
            file_id = self.id_cache[filename]
            try:
                drive_file = (
                    self.drive.files()
                    .get(
                        fileId=file_id,
                        fields="id,size,name,parents,trashed",
                        **self.shared_drive_flags_support,
                    )
                    .execute()
                )
                if drive_file["name"] == filename and not drive_file["trashed"]:
                    for parent in drive_file["parents"]:
                        if parent == self.folder:
                            log.Info(f"GDrive backend: found file '{filename}' with id {file_id} in ID cache")
                            return drive_file
            except HttpError as error:
                # A 404 occurs if the ID is no longer valid
                if error.resp.status != 404:
                    raise
            # If we get here, the cache entry is invalid
            log.Info(f"GDrive backend: invalidating '{filename}' (previously ID {file_id}) from ID cache")
            del self.id_cache[filename]

        # Not found in the cache, so use directory listing. This is less
        # reliable because there is no strong consistency.
        q = f"name = '{filename}' and '{self.folder}' in parents and trashed = false"
        results = (
            self.drive.files()
            .list(
                q=q,
                fields="files(name,id,size),nextPageToken",
                pageSize=2,
                **self.shared_drive_corpora,
                **self.shared_drive_id,
                **self.shared_drive_flags_include,
                **self.shared_drive_flags_support,
            )
            .execute()
        )
        file_list = results.get("files", [])
        if len(file_list) > 1:
            log.FatalError(f"GDrive backend: multiple files called '{filename}'.")
        elif len(file_list) > 0:
            file_id = file_list[0]["id"]
            self.id_cache[filename] = file_list[0]["id"]
            log.Info(f"GDrive backend: found file '{filename}' with id {file_id} on server, adding to cache")
            return file_list[0]

        log.Info(f"GDrive backend: file '{filename}' not found in cache or on server")
        return None

    def id_by_name(self, filename):
        drive_file = self.file_by_name(filename)
        if drive_file is None:
            return ""
        else:
            return drive_file["id"]

    def _put(self, source_path, remote_filename):
        from googleapiclient.http import MediaFileUpload

        remote_filename = os.fsdecode(remote_filename)
        drive_file = self.file_by_name(remote_filename)
        if remote_filename.endswith(".gpg"):
            mime_type = "application/pgp-encrypted"
        else:
            mime_type = "text/plain"

        file_size = os.path.getsize(source_path.name)
        if file_size >= self.MIN_RESUMABLE_UPLOAD:
            resumable = True
            num_retries = 5
        else:
            resumable = False
            num_retries = 0

        media = MediaFileUpload(source_path.name, mimetype=mime_type, resumable=resumable)
        if drive_file is None:
            # No existing file, make a new one
            file_metadata = {"name": remote_filename, "parents": [self.folder]}
            file_metadata.update(self.shared_drive_id)
            log.Info(f"GDrive backend: creating new file '{remote_filename}'")
            drive_file = (
                self.drive.files()
                .create(
                    body=file_metadata,
                    media_body=media,
                    **self.shared_drive_flags_support,
                )
                .execute(num_retries=num_retries)
            )
        else:
            log.Info(f"GDrive backend: replacing existing file '{remote_filename}' with id '{drive_file['id']}'")
            drive_file = (
                self.drive.files()
                .update(
                    media_body=media,
                    fileId=drive_file["id"],
                    **self.shared_drive_flags_support,
                )
                .execute(num_retries=num_retries)
            )

        self.id_cache[remote_filename] = drive_file["id"]

    def _get(self, remote_filename, local_path):
        from googleapiclient.http import MediaIoBaseDownload

        drive_file = self.file_by_name(remote_filename)
        request = self.drive.files().get_media(fileId=drive_file["id"], **self.shared_drive_flags_support)
        with open(os.fsdecode(local_path.name), "wb") as fh:
            done = False
            downloader = MediaIoBaseDownload(fh, request)
            while done is False:
                status, done = downloader.next_chunk()

    def _list(self):
        page_token = None
        drive_files = []
        while True:
            response = (
                self.drive.files()
                .list(
                    q=f"'{self.folder}' in parents and trashed=false",
                    pageSize=self.PAGE_SIZE,
                    fields="files(name,id),nextPageToken",
                    pageToken=page_token,
                    **self.shared_drive_corpora,
                    **self.shared_drive_id,
                    **self.shared_drive_flags_include,
                    **self.shared_drive_flags_support,
                )
                .execute()
            )

            drive_files += response.get("files", [])

            page_token = response.get("nextPageToken", None)
            if page_token is None:
                break

        filenames = set(item["name"] for item in drive_files)
        # Check the cache as well. A file might have just been uploaded but
        # not yet appear in the listing.
        # Note: do not use iterkeys() here, because file_by_name will modify
        # the cache if it finds invalid entries.
        for filename in list(self.id_cache.keys()):
            if (filename not in filenames) and (self.file_by_name(filename) is not None):
                filenames.add(filename)
        return list(filenames)

    def _delete(self, filename):
        file_id = self.id_by_name(filename)
        if file_id == "":
            log.Warn(f"File '{os.fsdecode(filename)}' does not exist while trying to delete it")
        else:
            self.drive.files().delete(fileId=file_id, **self.shared_drive_flags_support).execute()

    def _query(self, filename):
        drive_file = self.file_by_name(filename)
        if drive_file is None:
            size = -1
        else:
            size = int(drive_file["size"])
        return {"size": size}

    def _error_code(self, operation, error):  # pylint: disable=unused-argument
        from google.auth.exceptions import RefreshError
        from googleapiclient.errors import HttpError

        if isinstance(error, HttpError):
            return log.ErrorCode.backend_not_found
        elif isinstance(error, RefreshError):
            return log.ErrorCode.backend_permission_denied
        return log.ErrorCode.backend_error


duplicity.backend.register_backend("gdrive", GDriveBackend)

duplicity.backend.uses_netloc.extend(["gdrive"])

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