XylotrechusZ
<?php
defined("ABSPATH") or die("");
use Duplicator\Models\Storages\GDriveStorage;
use Duplicator\Models\SystemGlobalEntity;
use Duplicator\Utils\Crypt\CryptBlowfish;
require_once(DUPLICATOR____PATH . '/lib/google/apiclient/autoload.php');
require_once(DUPLICATOR____PATH . '/lib/google/class.enhanced.google.media.file.upload.php');
class DUP_PRO_GDriveClient_UploadInfo
{
/** @var string */
public $resume_uri = '';
/** @var int */
public $next_offset = 0;
/** @var ?string */
public $error_details = null;
/** @var bool */
public $is_complete = false;
}
class DUP_PRO_GDrive_U
{
const RedirectUri = "https://snapcreek.com/misc/gdrive/auth_callback.php";
const UploadChunkSizeBytes = 1048576; // 2097152;
// These are requested scopes, possibly can be different than required scopes
const SCOPES = array(
"openid",
"https://www.googleapis.com/auth/userinfo.profile",
"https://www.googleapis.com/auth/userinfo.email",
// The drive.file scope limits access to just those files created by the plugin
"https://www.googleapis.com/auth/drive.file",
);
const REQUIRED_SCOPES = array(
"openid",
"https://www.googleapis.com/auth/userinfo.profile",
"https://www.googleapis.com/auth/userinfo.email",
// The drive.file scope limits access to just those files created by the plugin
"https://www.googleapis.com/auth/drive.file",
);
/**
* Get directory view link
*
* @param Duplicator_Pro_Google_Service_Drive $google_service_drive Google service drive
* @param string $directory Directory
*
* @return string|null
*/
public static function get_directory_view_link(Duplicator_Pro_Google_Service_Drive $google_service_drive, $directory)
{
$directory_id = DUP_PRO_GDrive_U::get_directory_id($google_service_drive, $directory);
if ($directory_id != null) {
$directory_metadata = DUP_PRO_GDrive_U::get_file_metadata_by_id($google_service_drive, $directory_id);
if ($directory_metadata != null) {
DUP_PRO_Log::trace("Directory link = " . $directory_metadata->alternateLink); // @phpstan-ignore-line
return $directory_metadata->alternateLink; // @phpstan-ignore-line
} else {
DUP_PRO_Log::trace("Directory link for $directory not found");
return null;
}
} else {
DUP_PRO_Log::trace("Directory id for $directory not found");
return null;
}
}
/**
* Get file metada
*
* @param Duplicator_Pro_Google_Service_Drive $google_service_drive Google service drive
* @param string $file_id File id
*
* @return false|Duplicator_Pro_Google_Service_Drive_DriveFile false on failure
*/
public static function get_file_metadata_by_id(Duplicator_Pro_Google_Service_Drive $google_service_drive, $file_id)
{
try {
$file_metadata = $google_service_drive->files->get($file_id);
} catch (Exception $ex) {
DUP_PRO_Log::trace("Problems retrieving metadata for file $file_id");
return false;
}
return $file_metadata;
}
/**
* Delete file
*
* @param Duplicator_Pro_Google_Service_Drive $google_service_drive Google service drive
* @param string $file_id File id
*
* @return bool
*/
public static function delete_file(Duplicator_Pro_Google_Service_Drive $google_service_drive, $file_id)
{
$success = false;
try {
$google_service_drive->files->delete($file_id);
$success = true;
DUP_PRO_Log::trace("Delete of Google Drive file $file_id succeeded");
} catch (Exception $ex) {
DUP_PRO_Log::trace("Exception when trying to delete Google Drive file id $file_id");
}
return $success;
}
/**
* Retrieve files in a given directory orderd by creation date
*
* @param Duplicator_Pro_Google_Service_Drive $google_service_drive Google service drive
* @param string $directory_id Directory id
*
* @return null|object[]
*/
public static function get_files_in_directory(Duplicator_Pro_Google_Service_Drive $google_service_drive, $directory_id)
{
$file_items = null;
$parameters = array(
'orderBy' => 'createdTime',
'q' => "'$directory_id' in parents and trashed=false",
);
try {
$file_list = $google_service_drive->files->listFiles($parameters);
$file_items = $file_list->getFiles();
} catch (Exception $ex) {
DUP_PRO_Log::trace("Error retrieving file list for directory ID $directory_id " . $ex->getMessage());
}
return $file_items;
}
/**
* Get file
*
* @param Duplicator_Pro_Google_Service_Drive $google_service_drive Google service drive
* @param string $filename Filename
* @param string $directory_id Directory id
*
* @return null|string
*/
public static function get_file(
Duplicator_Pro_Google_Service_Drive $google_service_drive,
$filename,
$directory_id
) {
DUP_PRO_Log::trace("get_file for $filename $directory_id");
$file_id = null;
$file_items = self::get_files_in_directory($google_service_drive, $directory_id);
if ($file_items != null) {
foreach ($file_items as $drive_file) {
/* @var $drive_file Duplicator_Pro_Google_Service_Drive_DriveFile */
$google_filename = $drive_file->getName();
if ($google_filename == $filename) {
$file_id = $drive_file->getId();
break;
}
}
} else {
DUP_PRO_Log::trace("files in directory $directory_id are null");
}
return $file_id;
}
/**
* Get directory id
*
* @param Duplicator_Pro_Google_Service_Drive $google_service_drive Google service drive
* @param string $path Path
* @param bool $autocreate Autocreate
*
* @return null|string
*/
public static function get_directory_id(
Duplicator_Pro_Google_Service_Drive $google_service_drive,
$path,
$autocreate = true
) {
$parent_id = 'root';
$path = str_replace('\\', '/', $path);
$path = trim(trim($path), '/'); // Remove whitespaces and slashes from both ends of path
$path = preg_replace('#/+#', '/', $path); // Replace all duplicated slashes with a single slash
if ($path == "") {
return $parent_id;
}
$directory_parts = explode('/', $path);
try {
foreach ($directory_parts as $subdirectory) {
$parameters = array();
$parameters['q'] = "'$parent_id' in parents and mimeType = 'application/vnd.google-apps.folder' and trashed=false";
$file_list = $google_service_drive->files->listFiles($parameters);
$folder_id = '';
//DUP_PRO_Log::traceObject('#### file_list', $file_list);
//$items = $file_list->getItems();
$items = $file_list->getFiles();
foreach ($items as $drive_file) {
/* @var $drive_file Duplicator_Pro_Google_Service_Drive_DriveFile */
if ($drive_file->name == $subdirectory) {
$folder_id = $drive_file->id;
break;
} else {
DUP_PRO_Log::trace("{$drive_file->name} doesnt equal $subdirectory");
}
}
if ($folder_id == '') {
if ($autocreate) {
DUP_PRO_Log::trace("Creating new folder " . $subdirectory);
// Folder wasn't present so we have to create one
$folder_file = new Duplicator_Pro_Google_Service_Drive_DriveFile();
$folder_file->setName($subdirectory);
$folder_file->setMimeType('application/vnd.google-apps.folder');
$folder_file->setParents(array($parent_id));
$created_file = $google_service_drive->files->create($folder_file, array('mimeType' => 'application/vnd.google-apps.folder'));
$folder_id = $created_file->id;
} else {
// Doesn't exist
$parent_id = null;
}
}
$parent_id = $folder_id;
}
} catch (Exception $ex) {
DUP_PRO_Log::trace("Got error when trying to get directory id for $path: " . $ex->getMessage());
$parent_id = null;
}
return $parent_id;
}
/**
* Upload file
*
* @param Duplicator_Pro_Google_Client $google_client Google client
* @param string $src_file_path Source file path
* @param string $parent_file_id Parent file id
* @param string $dest_file_name Destination file name
*
* @return null|Duplicator_Pro_Google_Service_Drive_DriveFile
*/
public static function upload_file(
Duplicator_Pro_Google_Client $google_client,
$src_file_path,
$parent_file_id,
$dest_file_name = ''
) {
/* @var $google_Client Duplicator_Pro_Google_Client */
$drive_file = null;
/* @var $google_service_drive Duplicator_Pro_Google_Service_Drive */
try {
$mime_type = 'application/octet-stream';
$google_service_drive = new Duplicator_Pro_Google_Service_Drive($google_client);
$upload_file = new Duplicator_Pro_Google_Service_Drive_DriveFile();
//$upload_file->setTitle(basename($src_file_path));
if (empty($dest_file_name)) {
$dest_file_name = basename($src_file_path);
}
$upload_file->setName($dest_file_name);
$upload_file->setMimeType($mime_type);
$upload_file->setParents(array($parent_file_id));
try {
$data = file_get_contents($src_file_path);
if ($data !== false) {
// DUP_PRO_Log::traceObject("file to upload", $upload_file)
/* @var $drive_file Duplicator_Pro_Google_Service_Drive_DriveFile */
$drive_file = $google_service_drive->files->create($upload_file, array('data' => $data, 'uploadType' => 'media'));
} else {
DUP_PRO_Log::trace("Couldn't read file contents from $src_file_path when attempting Google Drive Upload");
}
} catch (Exception $ex) {
DUP_PRO_Log::trace("Exception from Google drive insert of $src_file_path " . $ex->getMessage());
}
if (isset($drive_file) == false) {
DUP_PRO_Log::trace("File returned from Google drive insert of $src_file_path is null.");
}
} catch (Exception $ex) {
DUP_PRO_Log::trace("Error uploading $src_file_path to Google Drive");
}
return $drive_file;
}
/**
* Upload file chunk
*
* @param Duplicator_Pro_Google_Client $google_client Google client
* @param string $src_file_path Source file path
* @param string $parent_file_id Parent file id
* @param int $upload_chunk_size Upload chunk size
* @param int $max_upload_time_in_sec Max upload time in sec
* @param int $next_offset Next offset
* @param string $resume_uri Resume uri
* @param int $server_load_delay Server load delay
*
* @return DUP_PRO_GDriveClient_UploadInfo
*/
public static function upload_file_chunk(
Duplicator_Pro_Google_Client $google_client,
$src_file_path,
$parent_file_id,
$upload_chunk_size = self::UploadChunkSizeBytes,
$max_upload_time_in_sec = 10,
$next_offset = 0,
$resume_uri = null,
$server_load_delay = 0
) {
$upload_info = new DUP_PRO_GDriveClient_UploadInfo();
try {
if (file_exists($src_file_path) == false) {
$upload_info->error_details = "$src_file_path doesn't exist!";
}
$google_service_drive = new Duplicator_Pro_Google_Service_Drive($google_client);
$google_client->setDefer(true);
$upload_file = new Duplicator_Pro_Google_Service_Drive_DriveFile();
$upload_file->name = basename($src_file_path);
$upload_file->setMimeType('application/octet-stream');
$upload_file->setParents(array($parent_file_id));
$request = $google_service_drive->files->create($upload_file);
if ($resume_uri == null) {
$resume_uri = false;
}
$media_file_upload = new DUP_Pro_EnhancedGoogleMediaFileUpload(
$google_client,
$request,
'binary/octet-stream',
null,
true,
$upload_chunk_size,
false,
$next_offset,
$resume_uri
);
$media_file_upload->setFileSize(filesize($src_file_path));
// Upload the various chunks. $status will be false until the process is complete.
$handle = fopen($src_file_path, "rb");
if ($handle != false) {
fseek($handle, $next_offset);
$start_time = time();
$time_passed = 0;
while (!$upload_info->is_complete && !feof($handle) && ($time_passed < $max_upload_time_in_sec)) {
if ($server_load_delay !== 0) {
usleep($server_load_delay);
}
$chunk = self::read_file_chunk($handle, $upload_chunk_size);
$upload_info->is_complete = ($media_file_upload->nextChunk($chunk) !== false);
$upload_info->resume_uri = $media_file_upload->resumeUri;
$upload_info->next_offset = $media_file_upload->getNextOffset();
fseek($handle, $upload_info->next_offset);
$time_passed = time() - $start_time;
}
if ($upload_info->is_complete) {
DUP_PRO_Log::trace("Upload info is complete!");
}
fclose($handle);
} else {
$upload_info->error_details = "Error opening $src_file_path";
}
} catch (Exception $ex) {
$message = $ex->getMessage();
$upload_info->error_details = "Error uploading to Google Drive: " . $message;
if (DUP_PRO_STR::contains($message, 'storage quota has been exceeded')) {
$system_global = SystemGlobalEntity::getInstance();
$system_global->addTextFix(
esc_html__('Google Drive out of storage space', "duplicator-pro"),
esc_html__('Free up space on Google Drive or increase storage quota.', "duplicator-pro")
);
}
}
$google_client->setDefer(false);
return $upload_info;
}
/**
* Download file
*
* @param Duplicator_Pro_Google_Client $google_client Google client
* @param Duplicator_Pro_Google_Service_Drive_DriveFile $google_file Google file
* @param string $local_filepath Local filepath
* @param bool $overwrite_local Overwrite local
*
* @return bool
*/
public static function download_file(
Duplicator_Pro_Google_Client $google_client,
Duplicator_Pro_Google_Service_Drive_DriveFile $google_file,
$local_filepath,
$overwrite_local = true
) {
$success = false;
if ($overwrite_local || (file_exists($local_filepath) === false)) {
$google_service_drive = new Duplicator_Pro_Google_Service_Drive($google_client);
$file_contents = $google_service_drive->files->get($google_file->id, array('alt' => 'media'));
if (@file_put_contents($local_filepath, $file_contents) === false) {
DUP_PRO_Log::trace("Problem writing downloaded file to $local_filepath!");
} else {
$success = true;
}
} else {
DUP_PRO_Log::trace("Attempted to download a file to $local_filepath but that file already exists!");
}
return $success;
}
/**
* Read file chunk
*
* @param resource $handle Handle
* @param int $chunk_size Chunk size
*
* @return string
*/
public static function read_file_chunk($handle, $chunk_size)
{
$byte_count = 0;
$giant_chunk = "";
while (!feof($handle)) {
// fread will never return more than 8192 bytes if the stream is read buffered and it does not represent a plain file
$chunk = fread($handle, 8192);
$byte_count += strlen($chunk);
$giant_chunk .= $chunk;
if ($byte_count >= $chunk_size) {
return $giant_chunk;
}
}
return $giant_chunk;
}
/**
* Return user info
*
* @param Duplicator_Pro_Google_Client $google_client Google client
*
* @return ?Duplicator_Pro_Google_Service_Oauth2_Userinfoplus
*/
public static function get_user_info(Duplicator_Pro_Google_Client $google_client)
{
$userInfoService = new Duplicator_Pro_Google_Service_Oauth2($google_client);
$userInfo = null;
try {
$userInfo = $userInfoService->userinfo->get();
} catch (Duplicator_Pro_Google_Exception $e) {
DUP_PRO_Log::trace("Error retrieving user information");
}
if ($userInfo->getId() == null) {
$userInfo = null;
}
return $userInfo;
}
/**
* Returns binary self value
*
* @return string
*/
public static function get_binary_self_value()
{
return 'jfds2!x4';
}
/**
* Returns binary extraction value
*
* @return string
*/
public static function get_binary_extraction_value()
{
return 'kkd23p';
}
/**
* Returns true if all required scopes are permitted, else returns false
*
* @param string $scopesToCheck Scopes to check, delimiter is space
*
* @return boolean
*/
public static function checkScopes($scopesToCheck)
{
$scopesToCheck = preg_split('~\s+~', $scopesToCheck, -1, PREG_SPLIT_NO_EMPTY);
if ($scopesToCheck == false) {
return false;
}
$ok = true;
foreach (self::REQUIRED_SCOPES as $requiredScope) {
if (!in_array($requiredScope, $scopesToCheck)) {
$ok = false;
break;
}
}
return $ok;
}
/**
* Get google client
*
* @param int $gdrive_client_number Gdrive client number
*
* @return Duplicator_Pro_Google_Client
*/
public static function get_raw_google_client($gdrive_client_number = null)
{
$global = DUP_PRO_Global_Entity::getInstance();
$client = new Duplicator_Pro_Google_Client();
if ($global->gdrive_transfer_mode == DUP_PRO_Google_Drive_Transfer_Mode::FOpen_URL) {
$io = new Duplicator_Pro_Google_IO_Stream($client);
$client->setIo($io);
}
$io = $client->getIo();
$setopts = array();
if (is_a($io, 'Duplicator_Pro_Google_IO_Curl')) {
$setopts[CURLOPT_SSL_VERIFYPEER] = $global->ssl_disableverify ? false : true;
$setopts[CURLOPT_SSL_VERIFYHOST] = $global->ssl_disableverify ? 0 : 2;
if (!$global->ssl_useservercerts) {
$setopts[CURLOPT_CAINFO] = DUPLICATOR_PRO_CERT_PATH;
$setopts[CURLOPT_CAPATH] = DUPLICATOR_PRO_CERT_PATH;
}
// Raise the timeout from the default of 15
$setopts[CURLOPT_TIMEOUT] = 360;
$setopts[CURLOPT_CONNECTTIMEOUT] = 180;
if ($global->ipv4_only) {
$setopts[CURLOPT_IPRESOLVE] = CURL_IPRESOLVE_V4;
}
} elseif (is_a($io, 'Duplicator_Pro_Google_IO_Stream')) {
$setopts['timeout'] = 360;
// https://wiki.php.net/rfc/tls-peer-verification - before PHP 5.6, there is no default CA file
if (!$global->ssl_useservercerts || (version_compare(PHP_VERSION, '5.6.0', '<'))) {
$setopts['cafile'] = DUPLICATOR_PRO_CERT_PATH;
}
if ($global->ssl_disableverify) {
$setopts['disable_verify_peer'] = true;
}
}
$io->setOptions($setopts);
$sv = self::get_binary_self_value();
$ev = self::get_binary_extraction_value();
$ci = CryptBlowfish::decrypt('EQNJ53++6/40fuF5ke+IaQ==', $sv);
$cs = CryptBlowfish::decrypt('ui25chqoBexPt6QDi9qmGg==', $ev);
$ci = trim($ci);
$cs = trim($cs);
switch ($gdrive_client_number) {
case GDriveStorage::GDRIVE_CLIENT_NATIVE:
if (($ci != $cs) || ($ci != "x93fdf8")) {
$ci = self::get_cj1() . self::get_cj2();
$cs = self::get_ct1() . self::get_ct2();
}
break;
case GDriveStorage::GDRIVE_CLIENT_WEB0722:
case GDriveStorage::GDRIVE_CLIENT_LATEST:
default:
if (($ci != $cs) || ($ci != "x93fdf8")) {
$ci = self::get_cj3() . self::get_cj4();
$cs = self::get_ct3() . self::get_ct4();
}
}
$client->setClientId($ci);
$client->setAccessType('offline');
$client->setClientSecret($cs);
$client->setScopes(self::SCOPES);
$client->setRedirectUri(self::RedirectUri);
return $client;
}
/**
* Returns part of ci
*
* @return string
*/
private static function get_cj1()
{
return base64_decode('MTMwOTA5MDkxOTkzLTZlMzFpNHN2cW9uaG9iMmRz');
}
/**
* Returns part of ci
*
* @return string
*/
private static function get_cj2()
{
return base64_decode('a2Zkc2R2cThvbWxnN3RlLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29t');
}
/**
* Returns part of ci
*
* @return string
*/
private static function get_cj3()
{
return base64_decode('MTMwOTA5MDkxOTkzLWVwbWY2aHBjZnNmbDduZW5p');
}
/**
* Returns part of ci
*
* @return string
*/
private static function get_cj4()
{
return base64_decode('MzV0cjNjb2VvcXRvcDhjLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29t');
}
/**
* Returns part of cs
*
* @return string
*/
private static function get_ct1()
{
return base64_decode('SVltaThQVnlzblFNbGo3');
}
/**
* Returns part of cs
*
* @return string
*/
private static function get_ct2()
{
return base64_decode('dHhuakgzN09t');
}
/**
* Returns part of cs
*
* @return string
*/
private static function get_ct3()
{
return base64_decode('R09DU1BYLWlIU3VZYnY1VHZa');
}
/**
* Returns part of cs
*
* @return string
*/
private static function get_ct4()
{
return base64_decode('SmJLVUIxa1VCclBIeG1JNGs=');
}
}