You are here

class BrowserDownloadDestination in Backup and Migrate 8.4

Class BrowserDownloadDestination.

@package BackupMigrate\Core\Destination

Hierarchy

Expanded class hierarchy of BrowserDownloadDestination

1 file declares its use of BrowserDownloadDestination
DrupalBrowserDownloadDestination.php in src/Destination/DrupalBrowserDownloadDestination.php

File

lib/backup_migrate_core/src/Destination/BrowserDownloadDestination.php, line 15

Namespace

BackupMigrate\Core\Destination
View source
class BrowserDownloadDestination extends StreamDestination implements WritableDestinationInterface, PluginCallerInterface {
  use PluginCallerTrait;

  /**
   * {@inheritdoc}
   */
  function saveFile(BackupFileReadableInterface $file) {

    // Set some default download headers.
    $headers = [
      [
        'key' => 'Content-Disposition',
        'value' => 'attachment; filename="' . $file
          ->getFullName() . '"',
      ],
      [
        'key' => 'Cache-Control',
        'value' => 'no-cache',
      ],
    ];

    // Set a mime-type header.
    if ($mime = $file
      ->getMeta('mimetype')) {
      $headers[] = [
        'key' => 'Content-Type',
        'value' => $mime,
      ];
    }
    else {

      // Get the mime type for this file if possible.
      $mime = 'application/octet-stream';
      $mime = $this
        ->plugins()
        ->call('alterMime', $mime, [
        'ext' => $file
          ->getExtLast(),
      ]);
      $headers[] = [
        'key' => 'Content-Type',
        'value' => $mime,
      ];
    }

    // In some circumstances, web-servers will double compress gzipped files.
    // This may help aleviate that issue by disabling mod-deflate.
    if ($file
      ->getMeta('mimetype') == 'application/x-gzip') {
      if (function_exists('apache_setenv')) {
        apache_setenv('no-gzip', '1');
      }
      $headers[] = [
        'key' => 'Content-Encoding',
        'value' => 'gzip',
      ];
    }
    if ($size = $file
      ->getMeta('filesize')) {
      $headers[] = [
        'key' => 'Content-Length',
        'value' => $size,
      ];
    }

    // Suppress the warning you get when the buffer is empty.
    @ob_end_clean();
    if ($file
      ->openForRead()) {
      foreach ($headers as $header) {

        // To prevent HTTP header injection, we delete new lines that are
        // not followed by a space or a tab.
        // See http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2
        $header['value'] = preg_replace('/\\r?\\n(?!\\t| )/', '', $header['value']);
        header($header['key'] . ': ' . $header['value']);
      }

      // Transfer file in 1024 byte chunks to save memory usage.
      while ($data = $file
        ->readBytes(1024 * 512)) {
        print $data;
      }
      $file
        ->close();
    }

    // @TODO Throw exception.
  }

  /**
   * {@inheritdoc}
   */
  public function checkWritable() {

    // Check that we're running as a web process via a browser.
    // @TODO: we could check if the 'HTTP_ACCEPT' header contains the right mime but that is probably overkill.
    if (!isset($_SERVER['REQUEST_METHOD'])) {
      throw new DestinationNotWritableException("The download destination only works when accessed through a http client.");
    }
  }

}

Members

Namesort descending Modifiers Type Description Overrides
BrowserDownloadDestination::checkWritable public function Overrides StreamDestination::checkWritable
BrowserDownloadDestination::saveFile function Save a file to the destination. Overrides StreamDestination::saveFile 1
ConfigurableTrait::$config protected property The object's configuration object.
ConfigurableTrait::$init protected property The initial configuration. These configuration options can be overriden by the config options but will not be overwritten. If the object is re-configured after construction any missing configuration options will revert to these values.
ConfigurableTrait::confGet public function Get a specific value from the configuration.
ConfigurableTrait::config public function Get the configuration object for this item.
ConfigurableTrait::configDefaults public function Get the default values for the plugin. 10
ConfigurableTrait::configErrors public function Get any validation errors in the config.
ConfigurableTrait::configSchema public function Get a default (blank) schema. 10
ConfigurableTrait::setConfig public function Set the configuration for all plugins. 1
ConfigurableTrait::__construct public function 2
PluginBase::opWeight public function What is the weight of the given operation for this plugin. Overrides PluginInterface::opWeight
PluginBase::supportedOps public function Get a list of supported operations and their weight. Overrides PluginInterface::supportedOps 8
PluginBase::supportsOp public function Does this plugin implement the given operation. Overrides PluginInterface::supportsOp
PluginCallerTrait::$plugins protected property
PluginCallerTrait::plugins public function Get the plugin manager.
PluginCallerTrait::setPluginManager public function Inject the plugin manager.
StreamDestination::getFile public function
StreamDestination::loadFileForReading public function
StreamDestination::loadFileMetadata public function
TranslatableTrait::$translator protected property
TranslatableTrait::setTranslator public function
TranslatableTrait::t public function Translate the given string if there is a translator service available.