first commit
This commit is contained in:
@@ -0,0 +1,261 @@
|
||||
<?php
|
||||
/**
|
||||
* Akeeba Engine
|
||||
*
|
||||
* @package akeebaengine
|
||||
* @copyright Copyright (c)2006-2022 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @license GNU General Public License version 3, or later
|
||||
*/
|
||||
|
||||
namespace Akeeba\Engine\Postproc;
|
||||
|
||||
defined('AKEEBAENGINE') || die();
|
||||
|
||||
use Akeeba\Engine\Platform;
|
||||
use Akeeba\Engine\Postproc\Exception\BadConfiguration;
|
||||
use Akeeba\Engine\Postproc\Exception\DeleteNotSupported;
|
||||
use Akeeba\Engine\Postproc\Exception\DownloadToBrowserNotSupported;
|
||||
use Akeeba\Engine\Postproc\Exception\DownloadToServerNotSupported;
|
||||
use Akeeba\Engine\Postproc\Exception\OAuthNotSupported;
|
||||
use Akeeba\Engine\Util\FileCloseAware;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Akeeba Engine post-processing abstract class. Provides the default implementation of most of the PostProcInterface
|
||||
* methods.
|
||||
*/
|
||||
abstract class Base implements PostProcInterface
|
||||
{
|
||||
use FileCloseAware;
|
||||
|
||||
/**
|
||||
* Should we break the step before post-processing?
|
||||
*
|
||||
* The only engine which does not require a step break before is the None engine.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $recommendsBreakBefore = true;
|
||||
|
||||
/**
|
||||
* Should we break the step after post-processing?
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $recommendsBreakAfter = true;
|
||||
|
||||
/**
|
||||
* Does this engine processes the files in a way that makes deleting the originals safe?
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $advisesDeletionAfterProcessing = true;
|
||||
|
||||
/**
|
||||
* Does this engine support remote file deletes?
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $supportsDelete = false;
|
||||
|
||||
/**
|
||||
* Does this engine support downloads to files?
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $supportsDownloadToFile = false;
|
||||
|
||||
/**
|
||||
* Does this engine support downloads to browser?
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $supportsDownloadToBrowser = false;
|
||||
|
||||
/**
|
||||
* Does this engine push raw data to the browser when downloading a file?
|
||||
*
|
||||
* Set to true if raw data will be dumped to the browser when downloading the file to the browser. Set to false if
|
||||
* a URL is returned instead.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $inlineDownloadToBrowser = false;
|
||||
|
||||
/**
|
||||
* The remote absolute path to the file which was just processed. Leave null if the file is meant to
|
||||
* be non-retrievable, i.e. sent to email or any other one way service.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $remotePath = null;
|
||||
|
||||
/**
|
||||
* Whitelist of method names you can call using customAPICall().
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $allowedCustomAPICallMethods = ['oauthCallback'];
|
||||
|
||||
/**
|
||||
* The connector object for this post-processing engine
|
||||
*
|
||||
* @var object|null
|
||||
*/
|
||||
private $connector;
|
||||
|
||||
public function delete($path)
|
||||
{
|
||||
throw new DeleteNotSupported();
|
||||
}
|
||||
|
||||
public function downloadToFile($remotePath, $localFile, $fromOffset = null, $length = null)
|
||||
{
|
||||
throw new DownloadToServerNotSupported();
|
||||
}
|
||||
|
||||
public function downloadToBrowser($remotePath)
|
||||
{
|
||||
throw new DownloadToBrowserNotSupported();
|
||||
}
|
||||
|
||||
public final function customAPICall($method, $params = [])
|
||||
{
|
||||
if (!in_array($method, $this->allowedCustomAPICallMethods) || !method_exists($this, $method))
|
||||
{
|
||||
header('HTTP/1.0 501 Not Implemented');
|
||||
|
||||
exit();
|
||||
}
|
||||
|
||||
return call_user_func_array([$this, $method], [$params]);
|
||||
}
|
||||
|
||||
public function oauthOpen($params = [])
|
||||
{
|
||||
$callback = $params['callbackURI'] . '&method=oauthCallback';
|
||||
|
||||
$url = $this->getOAuth2HelperUrl();
|
||||
$url .= (strpos($url, '?') !== false) ? '&' : '?';
|
||||
$url .= 'callback=' . urlencode($callback);
|
||||
$url .= '&dlid=' . urlencode(Platform::getInstance()->get_platform_configuration_option('update_dlid', ''));
|
||||
|
||||
Platform::getInstance()->redirect($url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the authentication token from the OAuth helper script, after you've run the first step of the OAuth
|
||||
* authentication process. Must be overridden in subclasses.
|
||||
*
|
||||
* @param array $params
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws OAuthNotSupported
|
||||
*/
|
||||
public function oauthCallback(array $params)
|
||||
{
|
||||
throw new OAuthNotSupported();
|
||||
}
|
||||
|
||||
public function recommendsBreakBefore()
|
||||
{
|
||||
return $this->recommendsBreakBefore;
|
||||
}
|
||||
|
||||
public function recommendsBreakAfter()
|
||||
{
|
||||
return $this->recommendsBreakAfter;
|
||||
}
|
||||
|
||||
public function isFileDeletionAfterProcessingAdvisable()
|
||||
{
|
||||
return $this->advisesDeletionAfterProcessing;
|
||||
}
|
||||
|
||||
public function supportsDelete()
|
||||
{
|
||||
return $this->supportsDelete;
|
||||
}
|
||||
|
||||
public function supportsDownloadToFile()
|
||||
{
|
||||
return $this->supportsDownloadToFile;
|
||||
}
|
||||
|
||||
public function supportsDownloadToBrowser()
|
||||
{
|
||||
return $this->supportsDownloadToBrowser;
|
||||
}
|
||||
|
||||
public function doesInlineDownloadToBrowser()
|
||||
{
|
||||
return $this->inlineDownloadToBrowser;
|
||||
}
|
||||
|
||||
public function getRemotePath()
|
||||
{
|
||||
return $this->remotePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the URL to the OAuth2 helper script. Used by the oauthOpen method. Must be overridden in subclasses.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws OAuthNotSupported
|
||||
*/
|
||||
protected function getOAuth2HelperUrl()
|
||||
{
|
||||
throw new OAuthNotSupported();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an instance of the connector object.
|
||||
*
|
||||
* @param bool $forceNew Should I force the creation of a new connector object?
|
||||
*
|
||||
* @return object The connector object
|
||||
*
|
||||
* @throws BadConfiguration If there is a configuration error which prevents creating a connector object.
|
||||
* @throws Exception
|
||||
*/
|
||||
final protected function getConnector($forceNew = false)
|
||||
{
|
||||
if ($forceNew)
|
||||
{
|
||||
$this->resetConnector();
|
||||
}
|
||||
|
||||
if (empty($this->connector))
|
||||
{
|
||||
$this->connector = $this->makeConnector();
|
||||
}
|
||||
|
||||
return $this->connector;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the connector.
|
||||
*
|
||||
* If the connector requires any special handling upon destruction you must handle it in its __destruct method.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
final protected function resetConnector()
|
||||
{
|
||||
$this->connector = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new connector object based on the engine configuration stored in the backup profile.
|
||||
*
|
||||
* Do not use this method directly. Use getConnector() instead.
|
||||
*
|
||||
* @return object The connector object
|
||||
*
|
||||
* @throws BadConfiguration If there is a configuration error which prevents creating a connector object.
|
||||
* @throws Exception Any other error when creating or initializing the connector object.
|
||||
*/
|
||||
protected abstract function makeConnector();
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
/**
|
||||
* Akeeba Engine
|
||||
*
|
||||
* @package akeebaengine
|
||||
* @copyright Copyright (c)2006-2022 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @license GNU General Public License version 3, or later
|
||||
*/
|
||||
|
||||
namespace Akeeba\Engine\Postproc;
|
||||
|
||||
defined('AKEEBAENGINE') || die();
|
||||
|
||||
use Akeeba\Engine\Factory;
|
||||
use Akeeba\Engine\Platform;
|
||||
use Akeeba\Engine\Postproc\Exception\BadConfiguration;
|
||||
use Awf\Text\Text;
|
||||
use Joomla\CMS\Language\Text as JText;
|
||||
use RuntimeException;
|
||||
|
||||
class Email extends Base
|
||||
{
|
||||
public function processPart($localFilepath, $remoteBaseName = null)
|
||||
{
|
||||
// Retrieve engine configuration data
|
||||
$config = Factory::getConfiguration();
|
||||
$address = trim($config->get('engine.postproc.email.address', ''));
|
||||
$subject = $config->get('engine.postproc.email.subject', '0');
|
||||
|
||||
// Sanity checks
|
||||
if (empty($address))
|
||||
{
|
||||
throw new BadConfiguration('You have not set up a recipient\'s email address for the backup files');
|
||||
}
|
||||
|
||||
// Send the file
|
||||
$basename = empty($remoteBaseName) ? basename($localFilepath) : $remoteBaseName;
|
||||
|
||||
Factory::getLog()->info(sprintf("Preparing to email %s to %s", $basename, $address));
|
||||
|
||||
if (empty($subject))
|
||||
{
|
||||
$subject = "You have a new backup part";
|
||||
|
||||
if (class_exists('\Awf\Text\Text'))
|
||||
{
|
||||
$subject = Text::_('COM_AKEEBA_COMMON_EMAIL_DEAFULT_SUBJECT');
|
||||
|
||||
if ($subject === 'COM_AKEEBA_COMMON_EMAIL_DEAFULT_SUBJECT')
|
||||
{
|
||||
$subject = JText::_('COM_AKEEBABACKUP_COMMON_EMAIL_DEAFULT_SUBJECT');
|
||||
}
|
||||
}
|
||||
elseif (class_exists('\Joomla\CMS\Language\Text'))
|
||||
{
|
||||
$subject = JText::_('COM_AKEEBA_COMMON_EMAIL_DEAFULT_SUBJECT');
|
||||
|
||||
if ($subject === 'COM_AKEEBA_COMMON_EMAIL_DEAFULT_SUBJECT')
|
||||
{
|
||||
$subject = JText::_('COM_AKEEBABACKUP_COMMON_EMAIL_DEAFULT_SUBJECT');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$body = "Emailing $basename";
|
||||
|
||||
Factory::getLog()->debug("Subject: $subject");
|
||||
Factory::getLog()->debug("Body: $body");
|
||||
|
||||
$result = Platform::getInstance()->send_email($address, $subject, $body, $localFilepath);
|
||||
|
||||
// Return the result
|
||||
if ($result !== true)
|
||||
{
|
||||
// An error occurred
|
||||
throw new RuntimeException($result);
|
||||
}
|
||||
|
||||
// Return success
|
||||
Factory::getLog()->info("Email sent successfully");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function makeConnector()
|
||||
{
|
||||
/**
|
||||
* This method does not use a connector.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
/**
|
||||
* Akeeba Engine
|
||||
*
|
||||
* @package akeebaengine
|
||||
* @copyright Copyright (c)2006-2022 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @license GNU General Public License version 3, or later
|
||||
*/
|
||||
|
||||
namespace Akeeba\Engine\Postproc\Exception;
|
||||
|
||||
defined('AKEEBAENGINE') || die();
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
/**
|
||||
* Indicates an error with the post-processing engine's configuration
|
||||
*/
|
||||
class BadConfiguration extends RuntimeException
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
/**
|
||||
* Akeeba Engine
|
||||
*
|
||||
* @package akeebaengine
|
||||
* @copyright Copyright (c)2006-2022 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @license GNU General Public License version 3, or later
|
||||
*/
|
||||
|
||||
namespace Akeeba\Engine\Postproc\Exception;
|
||||
|
||||
defined('AKEEBAENGINE') || die();
|
||||
|
||||
/**
|
||||
* Indicates that the post-processing engine does not support deleting remotely stored files.
|
||||
*/
|
||||
class DeleteNotSupported extends EngineException
|
||||
{
|
||||
protected $messagePrototype = 'The %s post-processing engine does not support deletion of backup archives.';
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
/**
|
||||
* Akeeba Engine
|
||||
*
|
||||
* @package akeebaengine
|
||||
* @copyright Copyright (c)2006-2022 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @license GNU General Public License version 3, or later
|
||||
*/
|
||||
|
||||
namespace Akeeba\Engine\Postproc\Exception;
|
||||
|
||||
defined('AKEEBAENGINE') || die();
|
||||
|
||||
/**
|
||||
* Indicates that the post-processing engine does not support downloading remotely stored files to the user's browser.
|
||||
*/
|
||||
class DownloadToBrowserNotSupported extends EngineException
|
||||
{
|
||||
protected $messagePrototype = 'The %s post-processing engine does not support downloading of backup archives to the browser.';
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
/**
|
||||
* Akeeba Engine
|
||||
*
|
||||
* @package akeebaengine
|
||||
* @copyright Copyright (c)2006-2022 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @license GNU General Public License version 3, or later
|
||||
*/
|
||||
|
||||
namespace Akeeba\Engine\Postproc\Exception;
|
||||
|
||||
defined('AKEEBAENGINE') || die();
|
||||
|
||||
/**
|
||||
* Indicates that the post-processing engine does not support downloading remotely stored files to the server
|
||||
*/
|
||||
class DownloadToServerNotSupported extends EngineException
|
||||
{
|
||||
protected $messagePrototype = 'The %s post-processing engine does not support downloading of backup archives to the server.';
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
/**
|
||||
* Akeeba Engine
|
||||
*
|
||||
* @package akeebaengine
|
||||
* @copyright Copyright (c)2006-2022 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @license GNU General Public License version 3, or later
|
||||
*/
|
||||
|
||||
namespace Akeeba\Engine\Postproc\Exception;
|
||||
|
||||
defined('AKEEBAENGINE') || die();
|
||||
|
||||
use Akeeba\Engine\Postproc\Base;
|
||||
use Exception;
|
||||
use RuntimeException;
|
||||
use Throwable;
|
||||
|
||||
class EngineException extends RuntimeException
|
||||
{
|
||||
protected $messagePrototype = 'The %s post-processing engine has experienced an unspecified error.';
|
||||
|
||||
/**
|
||||
* Construct the exception. If a message is not defined the default message for the exception will be used.
|
||||
*
|
||||
* @param string $message [optional] The Exception message to throw.
|
||||
* @param int $code [optional] The Exception code.
|
||||
* @param Exception|Throwable $previous [optional] The previous throwable used for the exception chaining.
|
||||
*/
|
||||
public function __construct($message = "", $code = 0, $previous = null)
|
||||
{
|
||||
if (empty($message))
|
||||
{
|
||||
$engineName = $this->getEngineKeyFromBacktrace();
|
||||
$message = sprintf($this->messagePrototype, $engineName);
|
||||
}
|
||||
|
||||
parent::__construct($message, $code, $previous);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the engine name (class name without the namespace) from the PHP execution backtrace.
|
||||
*
|
||||
* @return mixed|string
|
||||
*/
|
||||
protected function getEngineKeyFromBacktrace()
|
||||
{
|
||||
// Make sure the backtrace is at least 3 levels deep
|
||||
$backtrace = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT, 5);
|
||||
|
||||
// We need to be at least two levels deep
|
||||
if (count($backtrace) < 2)
|
||||
{
|
||||
return 'current';
|
||||
}
|
||||
|
||||
for ($i = 1; $i < count($backtrace); $i++)
|
||||
{
|
||||
// Get the fully qualified class
|
||||
$object = $backtrace[$i]['object'];
|
||||
|
||||
// We need a backtrace element with an object attached.
|
||||
if (!is_object($object))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the object is not a Postproc\Base object go to the next entry.
|
||||
if (!($object instanceof Base))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get the bare class name
|
||||
$fqnClass = $backtrace[$i]['class'];
|
||||
$parts = explode('\\', $fqnClass);
|
||||
$bareClass = array_pop($parts);
|
||||
|
||||
// Do not return the base object!
|
||||
if ($bareClass == 'Base')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
return $bareClass;
|
||||
}
|
||||
|
||||
return 'current';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
/**
|
||||
* Akeeba Engine
|
||||
*
|
||||
* @package akeebaengine
|
||||
* @copyright Copyright (c)2006-2022 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @license GNU General Public License version 3, or later
|
||||
*/
|
||||
|
||||
namespace Akeeba\Engine\Postproc\Exception;
|
||||
|
||||
defined('AKEEBAENGINE') || die();
|
||||
|
||||
/**
|
||||
* Indicates that the post-processing engine does not support OAuth2 or similar redirection-based authentication with
|
||||
* the remote storage provider.
|
||||
*/
|
||||
class OAuthNotSupported extends EngineException
|
||||
{
|
||||
protected $messagePrototype = 'The %s post-processing engine does not support opening an authentication window to the remote storage provider.';
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
/**
|
||||
* Akeeba Engine
|
||||
*
|
||||
* @package akeebaengine
|
||||
* @copyright Copyright (c)2006-2022 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @license GNU General Public License version 3, or later
|
||||
*/
|
||||
|
||||
namespace Akeeba\Engine\Postproc\Exception;
|
||||
|
||||
defined('AKEEBAENGINE') || die();
|
||||
|
||||
/**
|
||||
* Indicates that the post-processing engine does not support range downloads.
|
||||
*/
|
||||
class RangeDownloadNotSupported extends EngineException
|
||||
{
|
||||
protected $messagePrototype = 'The %s post-processing engine does not support range downloads of backup archives to the server.';
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
/**
|
||||
* Akeeba Engine
|
||||
*
|
||||
* @package akeebaengine
|
||||
* @copyright Copyright (c)2006-2022 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @license GNU General Public License version 3, or later
|
||||
*/
|
||||
|
||||
namespace Akeeba\Engine\Postproc;
|
||||
|
||||
defined('AKEEBAENGINE') || die();
|
||||
|
||||
class None extends Base
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
// No point in breaking the step; we simply do nothing :)
|
||||
$this->recommendsBreakAfter = false;
|
||||
$this->recommendsBreakBefore = false;
|
||||
$this->advisesDeletionAfterProcessing = false;
|
||||
}
|
||||
|
||||
public function processPart($localFilepath, $remoteBaseName = null)
|
||||
{
|
||||
// Really nothing to do!!
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function makeConnector()
|
||||
{
|
||||
// I have to return an object to satisfy the definition.
|
||||
return (object) [
|
||||
'foo' => 'bar',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
<?php
|
||||
/**
|
||||
* Akeeba Engine
|
||||
*
|
||||
* @package akeebaengine
|
||||
* @copyright Copyright (c)2006-2022 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @license GNU General Public License version 3, or later
|
||||
*/
|
||||
|
||||
namespace Akeeba\Engine\Postproc;
|
||||
|
||||
defined('AKEEBAENGINE') || die();
|
||||
|
||||
use Akeeba\Engine\Postproc\Exception\DeleteNotSupported;
|
||||
use Akeeba\Engine\Postproc\Exception\DownloadToBrowserNotSupported;
|
||||
use Akeeba\Engine\Postproc\Exception\DownloadToServerNotSupported;
|
||||
use Akeeba\Engine\Postproc\Exception\OAuthNotSupported;
|
||||
use Akeeba\Engine\Postproc\Exception\RangeDownloadNotSupported;
|
||||
use Exception;
|
||||
|
||||
interface PostProcInterface
|
||||
{
|
||||
/**
|
||||
* This function takes care of post-processing a file (typically a backup archive part file).
|
||||
*
|
||||
* If the process has ran to completion it returns true.
|
||||
*
|
||||
* If more work is required (the file has only been partially uploaded) it returns false.
|
||||
*
|
||||
* It the process has failed an Exception is thrown.
|
||||
*
|
||||
* @param string $localFilepath Absolute path to the part we'll have to process
|
||||
* @param string|null $remoteBaseName Base name of the uploaded file, skip to use $absolute_filename's
|
||||
*
|
||||
* @return bool True on success, false if more work is required
|
||||
*
|
||||
* @throws Exception When an error occurred during post-processing
|
||||
*/
|
||||
public function processPart($localFilepath, $remoteBaseName = null);
|
||||
|
||||
/**
|
||||
* Deletes a remote file
|
||||
*
|
||||
* @param string $path The absolute, remote storage path to the file we're deleting
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws DeleteNotSupported When this feature is not supported at all.
|
||||
* @throws Exception When an engine error occurs
|
||||
*/
|
||||
public function delete($path);
|
||||
|
||||
/**
|
||||
* Downloads a remotely stored file back to the site's server. It can optionally do a range download. If range
|
||||
* downloads are not supported we throw a RangeDownloadNotSupported exception. Any other type of Exception means
|
||||
* that the download failed.
|
||||
*
|
||||
* @param string $remotePath The path to the remote file
|
||||
* @param string $localFile The absolute path to the local file we're writing to
|
||||
* @param int|null $fromOffset The offset (in bytes) to start downloading from
|
||||
* @param int|null $length The amount of data (in bytes) to download
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws DownloadToServerNotSupported When this feature is not supported at all.
|
||||
* @throws RangeDownloadNotSupported When range downloads are not supported.
|
||||
* @throws Exception On failure.
|
||||
*/
|
||||
public function downloadToFile($remotePath, $localFile, $fromOffset = null, $length = null);
|
||||
|
||||
/**
|
||||
* Downloads a remotely stored file to the user's browser, without storing it on the site's web server first.
|
||||
*
|
||||
* If $this->inlineDownloadToBrowser is true the method outputs a byte stream to the browser and returns null.
|
||||
*
|
||||
* If $this->inlineDownloadToBrowser is false it returns a string containing a public download URL. The user's
|
||||
* browser will be redirected to that URL.
|
||||
*
|
||||
* If this feature is not supported a DownloadToBrowserNotSupported exception will be thrown.
|
||||
*
|
||||
* Any other Exception indicates an error while trying to download to browser such as file not found, problem with
|
||||
* the remote service etc.
|
||||
*
|
||||
* @param string $remotePath The absolute, remote storage path to the file we want to download
|
||||
*
|
||||
* @return string|null
|
||||
*
|
||||
* @throws DownloadToBrowserNotSupported When this feature is not supported at all.
|
||||
* @throws Exception When an error occurs.
|
||||
*/
|
||||
public function downloadToBrowser($remotePath);
|
||||
|
||||
/**
|
||||
* A proxy which allows us to execute arbitrary methods in this engine. Used for AJAX calls, typically to update UI
|
||||
* elements with information fetched from the remote storage service.
|
||||
*
|
||||
* For security reasons, only methods whitelisted in the $this->allowedCustomAPICallMethods array can be called.
|
||||
*
|
||||
* @param string $method The method to call.
|
||||
* @param array $params Any parameters to send to the method, in array format
|
||||
*
|
||||
* @return mixed The return value of the method.
|
||||
*/
|
||||
public function customAPICall($method, $params = []);
|
||||
|
||||
/**
|
||||
* Opens an OAuth window (performs an HTTP redirection).
|
||||
*
|
||||
* @param array $params Any parameters required to launch OAuth
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws OAuthNotSupported When not supported.
|
||||
* @throws Exception When an error occurred.
|
||||
*/
|
||||
public function oauthOpen($params = []);
|
||||
|
||||
/**
|
||||
* Fetches the authentication token from the OAuth helper script, after you've run the first step of the OAuth
|
||||
* authentication process. Must be overridden in subclasses.
|
||||
*
|
||||
* @param array $params
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws OAuthNotSupported
|
||||
*/
|
||||
public function oauthCallback(array $params);
|
||||
|
||||
/**
|
||||
* Does the engine recommend doing a step break before post-processing backup archives with it?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function recommendsBreakBefore();
|
||||
|
||||
/**
|
||||
* Does the engine recommend doing a step break after post-processing backup archives with it?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function recommendsBreakAfter();
|
||||
|
||||
/**
|
||||
* Is it advisable to delete files successfully post-processed by this post-processing engine?
|
||||
*
|
||||
* Currently only the “None” method advises against deleting successfully post-processed files for the simple reason
|
||||
* that it does absolutely nothing with the files. The only copy is still on the server.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isFileDeletionAfterProcessingAdvisable();
|
||||
|
||||
/**
|
||||
* Does this engine support deleting remotely stored files?
|
||||
*
|
||||
* Most engines support deletion. However, some engines such as “Send by email”, do not have a way to find files
|
||||
* already processed and delete them. Or it may be that we are sending the file to a write-only storage service
|
||||
* which does not support deletions.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function supportsDelete();
|
||||
|
||||
/**
|
||||
* Does this engine support downloading backup archives back to the site's web server?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function supportsDownloadToFile();
|
||||
|
||||
/**
|
||||
* Does this engine support downloading backup archives directly to the user's browser?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function supportsDownloadToBrowser();
|
||||
|
||||
/**
|
||||
* Does this engine return a bytestream when asked to download backup archives directly to the user's browser?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function doesInlineDownloadToBrowser();
|
||||
|
||||
/**
|
||||
* Returns the remote absolute path to the file which was just processed.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getRemotePath();
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
/**
|
||||
* Akeeba Engine
|
||||
*
|
||||
* @package akeebaengine
|
||||
* @copyright Copyright (c)2006-2022 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @license GNU General Public License version 3, or later
|
||||
*/
|
||||
|
||||
namespace Akeeba\Engine\Postproc;
|
||||
|
||||
use Akeeba\Engine\Platform;
|
||||
|
||||
trait ProxyAware
|
||||
{
|
||||
/**
|
||||
* Apply the platform proxy configuration to the cURL resource.
|
||||
*
|
||||
* @param resource $ch The cURL resource, returned by curl_init();
|
||||
*/
|
||||
protected function applyProxySettingsToCurl($ch)
|
||||
{
|
||||
if (defined('AKEEBA_NO_PROXY_AWARE'))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
$proxySettings = Platform::getInstance()->getProxySettings();
|
||||
|
||||
if (!$proxySettings['enabled'])
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
curl_setopt($ch, CURLOPT_PROXY, $proxySettings['host'] . ':' . $proxySettings['port']);
|
||||
|
||||
if (empty($proxySettings['user']))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
curl_setopt($ch, CURLOPT_PROXYUSERPWD, $proxySettings['user'] . ':' . $proxySettings['pass']);
|
||||
}
|
||||
|
||||
protected function getProxyStreamContext()
|
||||
{
|
||||
if (defined('AKEEBA_NO_PROXY_AWARE'))
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
$ret = [];
|
||||
$proxySettings = Platform::getInstance()->getProxySettings();
|
||||
|
||||
if (!$proxySettings['enabled'])
|
||||
{
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$ret['http'] = [
|
||||
'proxy' => $proxySettings['host'] . ':' . $proxySettings['port'],
|
||||
'request_fulluri' => true,
|
||||
];
|
||||
$ret['ftp'] = [
|
||||
'proxy' => $proxySettings['host'] . ':' . $proxySettings['port'],
|
||||
// So, request_fulluri isn't documented for the FTP transport but seems to be required...?!
|
||||
'request_fulluri' => true,
|
||||
];
|
||||
|
||||
if (empty($proxySettings['user']))
|
||||
{
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$ret['http']['header'] = ['Proxy-Authorization: Basic ' . base64_encode($proxySettings['user'] . ':' . $proxySettings['pass'])];
|
||||
$ret['ftp']['header'] = ['Proxy-Authorization: Basic ' . base64_encode($proxySettings['user'] . ':' . $proxySettings['pass'])];
|
||||
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"_information": {
|
||||
"title": "COM_AKEEBA_CONFIG_ENGINE_POSTPROC_EMAIL_TITLE",
|
||||
"description": "COM_AKEEBA_CONFIG_ENGINE_POSTPROC_EMAIL_DESCRIPTION"
|
||||
},
|
||||
"engine.postproc.common.after_part": {
|
||||
"default": "0",
|
||||
"type": "bool",
|
||||
"title": "COM_AKEEBA_CONFIG_POSTPROCPARTS_TITLE",
|
||||
"description": "COM_AKEEBA_CONFIG_POSTPROCPARTS_DESCRIPTION"
|
||||
},
|
||||
"engine.postproc.common.delete_after": {
|
||||
"default": "1",
|
||||
"type": "bool",
|
||||
"title": "COM_AKEEBA_CONFIG_DELETEAFTER_TITLE",
|
||||
"description": "COM_AKEEBA_CONFIG_DELETEAFTER_DESCRIPTION"
|
||||
},
|
||||
"engine.postproc.email.address": {
|
||||
"default": "",
|
||||
"type": "string",
|
||||
"title": "COM_AKEEBA_CONFIG_PROCEMAIL_ADDRESS_TITLE",
|
||||
"description": "COM_AKEEBA_CONFIG_PROCEMAIL_ADDRESS_DESCRIPTION"
|
||||
},
|
||||
"engine.postproc.email.subject": {
|
||||
"default": "",
|
||||
"type": "string",
|
||||
"title": "COM_AKEEBA_CONFIG_PROCEMAIL_SUBJECT_TITLE",
|
||||
"description": "COM_AKEEBA_CONFIG_PROCEMAIL_SUBJECT_DESCRIPTION"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"_information": {
|
||||
"title": "COM_AKEEBA_CONFIG_ENGINE_POSTPROC_NONE_TITLE",
|
||||
"description": "COM_AKEEBA_CONFIG_ENGINE_POSTPROC_NONE_DESCRIPTION"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user