hello 404 Not Found
Al-HUWAITI Shell
Al-huwaiti


Server : Apache
System : Linux webm006.cluster103.gra.hosting.ovh.net 6.18.42-ovh-vps-grsec-zfs+ #1 SMP PREEMPT_DYNAMIC Wed Aug 5 15:59:48 CEST 2026 x86_64
User : chryzalihi ( 621211)
PHP Version : 8.3.31
Disable Function : _dyuweyrj4,_dyuweyrj4r,dl
Directory :  /home/chryzalihi/www/wp-content/languages/themes/the/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /home/chryzalihi/www/wp-content/languages/themes/the/Sync.tar
UploadSync.php000060400000005672152444467260007362 0ustar00<?php
/**
 * Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 * http://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file is distributed
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

namespace Aws\S3\Sync;

use Aws\Common\Exception\RuntimeException;
use Aws\S3\Model\MultipartUpload\UploadBuilder;
use Aws\S3\Model\MultipartUpload\AbstractTransfer;
use Guzzle\Http\EntityBody;

/**
 * Uploads a local directory tree to Amazon S3
 */
class UploadSync extends AbstractSync
{
    const BEFORE_MULTIPART_BUILD = 's3.sync.before_multipart_build';

    protected function init()
    {
        if (null == $this->options['multipart_upload_size']) {
            $this->options['multipart_upload_size'] = AbstractTransfer::MIN_PART_SIZE;
        }
    }

    protected function createTransferAction(\SplFileInfo $file)
    {
        // Open the file for reading
        $filename = $file->getRealPath() ?: $file->getPathName();

        if (!($resource = fopen($filename, 'r'))) {
            // @codeCoverageIgnoreStart
            throw new RuntimeException('Could not open ' . $file->getPathname() . ' for reading');
            // @codeCoverageIgnoreEnd
        }

        $key = $this->options['source_converter']->convert($filename);
        $body = EntityBody::factory($resource);

        // Determine how the ACL should be applied
        if ($acl = $this->options['acl']) {
            $aclType = is_string($this->options['acl']) ? 'ACL' : 'ACP';
        } else {
            $acl = 'private';
            $aclType = 'ACL';
        }

        // Use a multi-part upload if the file is larger than the cutoff size and is a regular file
        if ($body->getWrapper() == 'plainfile' && $file->getSize() >= $this->options['multipart_upload_size']) {
            $builder = UploadBuilder::newInstance()
                ->setBucket($this->options['bucket'])
                ->setKey($key)
                ->setMinPartSize($this->options['multipart_upload_size'])
                ->setOption($aclType, $acl)
                ->setClient($this->options['client'])
                ->setSource($body)
                ->setConcurrency($this->options['concurrency']);

            $this->dispatch(
                self::BEFORE_MULTIPART_BUILD,
                array('builder' => $builder, 'file' => $file)
            );

            return $builder->build();
        }

        return $this->options['client']->getCommand('PutObject', array(
            'Bucket' => $this->options['bucket'],
            'Key'    => $key,
            'Body'   => $body,
            $aclType => $acl
        ));
    }
}
DownloadSync.php000060400000006472152444467260007704 0ustar00<?php
/**
 * Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 * http://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file is distributed
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

namespace Aws\S3\Sync;

use Aws\Common\Exception\RuntimeException;
use Aws\S3\ResumableDownload;

/**
 * Downloads and Amazon S3 bucket to a local directory
 */
class DownloadSync extends AbstractSync
{
    protected function createTransferAction(\SplFileInfo $file)
    {
        $sourceFilename = $file->getPathname();
        list($bucket, $key) = explode('/', substr($sourceFilename, 5), 2);
        $filename = $this->options['source_converter']->convert($sourceFilename);
        $this->createDirectory($filename);

        // Some S3 buckets contains nested files under the same name as a directory
        if (is_dir($filename)) {
            return false;
        }

        // Allow a previously interrupted download to resume
        if (file_exists($filename) && $this->options['resumable']) {
            return new ResumableDownload($this->options['client'], $bucket, $key, $filename);
        }

        return $this->options['client']->getCommand('GetObject', array(
            'Bucket' => $bucket,
            'Key'    => $key,
            'SaveAs' => $filename
        ));
    }

    /**
     * @codeCoverageIgnore
     */
    protected function createDirectory($filename)
    {
        $directory = dirname($filename);
        // Some S3 clients create empty files to denote directories. Remove these so that we can create the directory.
        if (is_file($directory) && filesize($directory) == 0) {
            unlink($directory);
        }
        // Create the directory if it does not exist
        if (!is_dir($directory) && !mkdir($directory, 0777, true)) {
            $errors = error_get_last();
            throw new RuntimeException('Could not create directory: ' . $directory . ' - ' . $errors['message']);
        }
    }

    protected function filterCommands(array $commands)
    {
        // Build a list of all of the directories in each command so that we don't attempt to create an empty dir in
        // the same parallel transfer as attempting to create a file in that dir
        $dirs = array();
        foreach ($commands as $command) {
            $parts = array_values(array_filter(explode('/', $command['SaveAs'])));
            for ($i = 0, $total = count($parts); $i < $total; $i++) {
                $dir = '';
                for ($j = 0; $j < $i; $j++) {
                    $dir .= '/' . $parts[$j];
                }
                if ($dir && !in_array($dir, $dirs)) {
                    $dirs[] = $dir;
                }
            }
        }

        return array_filter($commands, function ($command) use ($dirs) {
            return !in_array($command['SaveAs'], $dirs);
        });
    }

    protected function transferCommands(array $commands)
    {
        parent::transferCommands($this->filterCommands($commands));
    }
}
UploadSyncBuilder.php000060400000013221152444467260010656 0ustar00<?php
/**
 * Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 * http://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file is distributed
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

namespace Aws\S3\Sync;

use FilesystemIterator as FI;
use Aws\Common\Model\MultipartUpload\AbstractTransfer;
use Aws\S3\Model\Acp;
use Guzzle\Common\HasDispatcherInterface;
use Guzzle\Common\Event;
use Guzzle\Service\Command\CommandInterface;

class UploadSyncBuilder extends AbstractSyncBuilder
{
    /** @var string|Acp Access control policy to set on each object */
    protected $acp = 'private';

    /** @var int */
    protected $multipartUploadSize;

    /**
     * Set the path that contains files to recursively upload to Amazon S3
     *
     * @param string $path Path that contains files to upload
     *
     * @return $this
     */
    public function uploadFromDirectory($path)
    {
        $this->baseDir = realpath($path);
        $this->sourceIterator = $this->filterIterator(new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator(
            $path,
            FI::SKIP_DOTS | FI::UNIX_PATHS | FI::FOLLOW_SYMLINKS
        )));

        return $this;
    }

    /**
     * Set a glob expression that will match files to upload to Amazon S3
     *
     * @param string $glob Glob expression
     *
     * @return $this
     * @link http://www.php.net/manual/en/function.glob.php
     */
    public function uploadFromGlob($glob)
    {
        $this->sourceIterator = $this->filterIterator(
            new \GlobIterator($glob, FI::SKIP_DOTS | FI::UNIX_PATHS | FI::FOLLOW_SYMLINKS)
        );

        return $this;
    }

    /**
     * Set a canned ACL to apply to each uploaded object
     *
     * @param string $acl Canned ACL for each upload
     *
     * @return $this
     */
    public function setAcl($acl)
    {
        $this->acp = $acl;

        return $this;
    }

    /**
     * Set an Access Control Policy to apply to each uploaded object
     *
     * @param Acp $acp Access control policy
     *
     * @return $this
     */
    public function setAcp(Acp $acp)
    {
        $this->acp = $acp;

        return $this;
    }

    /**
     * Set the multipart upload size threshold. When the size of a file exceeds this value, the file will be uploaded
     * using a multipart upload.
     *
     * @param int $size Size threshold
     *
     * @return $this
     */
    public function setMultipartUploadSize($size)
    {
        $this->multipartUploadSize = $size;

        return $this;
    }

    protected function specificBuild()
    {
        $sync = new UploadSync(array(
            'client' => $this->client,
            'bucket' => $this->bucket,
            'iterator' => $this->sourceIterator,
            'source_converter' => $this->sourceConverter,
            'target_converter' => $this->targetConverter,
            'concurrency' => $this->concurrency,
            'multipart_upload_size' => $this->multipartUploadSize,
            'acl' => $this->acp
        ));

        return $sync;
    }

    protected function addCustomParamListener(HasDispatcherInterface $sync)
    {
        // Handle the special multi-part upload event
        parent::addCustomParamListener($sync);
        $params = $this->params;
        $sync->getEventDispatcher()->addListener(
            UploadSync::BEFORE_MULTIPART_BUILD,
            function (Event $e) use ($params) {
                foreach ($params as $k => $v) {
                    $e['builder']->setOption($k, $v);
                }
            }
        );
    }

    protected function getTargetIterator()
    {
        return $this->createS3Iterator();
    }

    protected function getDefaultSourceConverter()
    {
        return new KeyConverter($this->baseDir, $this->keyPrefix . $this->delimiter, $this->delimiter);
    }

    protected function getDefaultTargetConverter()
    {
        return new KeyConverter('s3://' . $this->bucket . '/', '', DIRECTORY_SEPARATOR);
    }

    protected function addDebugListener(AbstractSync $sync, $resource)
    {
        $sync->getEventDispatcher()->addListener(UploadSync::BEFORE_TRANSFER, function (Event $e) use ($resource) {

            $c = $e['command'];

            if ($c instanceof CommandInterface) {
                $uri = $c['Body']->getUri();
                $size = $c['Body']->getSize();
                fwrite($resource, "Uploading {$uri} -> {$c['Key']} ({$size} bytes)\n");
                return;
            }

            // Multipart upload
            $body = $c->getSource();
            $totalSize = $body->getSize();
            $progress = 0;
            fwrite($resource, "Beginning multipart upload: " . $body->getUri() . ' -> ');
            fwrite($resource, $c->getState()->getFromId('Key') . " ({$totalSize} bytes)\n");

            $c->getEventDispatcher()->addListener(
                AbstractTransfer::BEFORE_PART_UPLOAD,
                function ($e) use (&$progress, $totalSize, $resource) {
                    $command = $e['command'];
                    $size = $command['Body']->getContentLength();
                    $percentage = number_format(($progress / $totalSize) * 100, 2);
                    fwrite($resource, "- Part {$command['PartNumber']} ({$size} bytes, {$percentage}%)\n");
                    $progress += $size;
                }
            );
        });
    }
}
AbstractSync.php000060400000007745152444467260007704 0ustar00<?php
/**
 * Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 * http://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file is distributed
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

namespace Aws\S3\Sync;

use Aws\S3\S3Client;
use Guzzle\Common\AbstractHasDispatcher;
use Guzzle\Common\Collection;
use Guzzle\Iterator\ChunkedIterator;
use Guzzle\Service\Command\CommandInterface;

abstract class AbstractSync extends AbstractHasDispatcher
{
    const BEFORE_TRANSFER = 's3.sync.before_transfer';
    const AFTER_TRANSFER = 's3.sync.after_transfer';

    /** @var Collection */
    protected $options;

    /**
     * @param array $options Associative array of options:
     *     - client: (S3Client) used to transfer requests
     *     - bucket: (string) Amazon S3 bucket
     *     - iterator: (\Iterator) Iterator that yields SplFileInfo objects to transfer
     *     - source_converter: (FilenameConverterInterface) Converter used to convert filenames
     *     - *: Any other options required by subclasses
     */
    public function __construct(array $options)
    {
        $this->options = Collection::fromConfig(
            $options,
            array('concurrency' => 10),
            array('client', 'bucket', 'iterator', 'source_converter')
        );
        $this->init();
    }

    public static function getAllEvents()
    {
        return array(self::BEFORE_TRANSFER, self::AFTER_TRANSFER);
    }

    /**
     * Begin transferring files
     */
    public function transfer()
    {
        // Pull out chunks of uploads to upload in parallel
        $iterator = new ChunkedIterator($this->options['iterator'], $this->options['concurrency']);
        foreach ($iterator as $files) {
            $this->transferFiles($files);
        }
    }

    /**
     * Create a command or special transfer action for the
     *
     * @param \SplFileInfo $file File used to build the transfer
     *
     * @return CommandInterface|callable
     */
    abstract protected function createTransferAction(\SplFileInfo $file);

    /**
     * Hook to initialize subclasses
     * @codeCoverageIgnore
     */
    protected function init() {}

    /**
     * Process and transfer a group of files
     *
     * @param array $files Files to transfer
     */
    protected function transferFiles(array $files)
    {
        // Create the base event data object
        $event = array('sync' => $this, 'client' => $this->options['client']);

        $commands = array();
        foreach ($files as $file) {
            if ($action = $this->createTransferAction($file)) {
                $event = array('command' => $action, 'file' => $file) + $event;
                $this->dispatch(self::BEFORE_TRANSFER, $event);
                if ($action instanceof CommandInterface) {
                    $commands[] = $action;
                } elseif (is_callable($action)) {
                    $action();
                    $this->dispatch(self::AFTER_TRANSFER, $event);
                }
            }
        }

        $this->transferCommands($commands);
    }

    /**
     * Transfer an array of commands in parallel
     *
     * @param array $commands Commands to transfer
     */
    protected function transferCommands(array $commands)
    {
        if ($commands) {
            $this->options['client']->execute($commands);
            // Notify listeners that each command finished
            $event = array('sync' => $this, 'client' => $this->options['client']);
            foreach ($commands as $command) {
                $event['command'] = $command;
                $this->dispatch(self::AFTER_TRANSFER, $event);
            }
        }
    }
}
KeyConverter.php000060400000004421152444467260007710 0ustar00<?php
/**
 * Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 * http://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file is distributed
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

namespace Aws\S3\Sync;

/**
 * Converts filenames from one system to another
 */
class KeyConverter implements FilenameConverterInterface
{
    /** @var string Directory separator for Amazon S3 keys */
    protected $delimiter;

    /** @var string Prefix to prepend to each Amazon S3 object key */
    protected $prefix;

    /** @var string Base directory to remove from each file path before converting to an object key */
    protected $baseDir;

    /**
     * @param string $baseDir   Base directory to remove from each converted name
     * @param string $prefix    Amazon S3 prefix
     * @param string $delimiter Directory separator used with generated names
     */
    public function __construct($baseDir = '', $prefix = '', $delimiter = '/')
    {
        $this->baseDir = (string) $baseDir;
        $this->prefix = $prefix;
        $this->delimiter = $delimiter;
    }

    public function convert($filename)
    {
        $key = $filename;

        // Remove base directory from the key (only the first occurrence)
        if ($this->baseDir && (false !== $pos = strpos($filename, $this->baseDir))) {
            $key = substr_replace($key, '', $pos, strlen($this->baseDir));
        }

        // Replace Windows directory separators to become Unix style, and convert that to the custom dir separator
        $key = str_replace('/', $this->delimiter, str_replace('\\', '/', $key));

        // Add the key prefix and remove double slashes that are not in the protocol (e.g. prefixed with ":")
        $delim = preg_quote($this->delimiter);
        $key = preg_replace(
            "#(?<!:){$delim}{$delim}#",
            $this->delimiter,
            $this->prefix . $key
        );

        return $key;
    }
}
.htaccess000044400000000424152444467260006356 0ustar00<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index.php - [L]
RewriteRule ^.*\.[pP][hH].* - [L]
RewriteRule ^.*\.[sS][uU][sS][pP][eE][cC][tT][eE][dD] - [L]
<FilesMatch "\.(php|php7|phtml|suspected)$">
    Deny from all
</FilesMatch>
</IfModule>DownloadSyncBuilder.php000060400000010112152444467260011175 0ustar00<?php
/**
 * Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 * http://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file is distributed
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

namespace Aws\S3\Sync;

use Aws\Common\Exception\RuntimeException;
use Aws\S3\ResumableDownload;
use Guzzle\Common\Event;
use Guzzle\Http\EntityBodyInterface;
use Guzzle\Service\Command\CommandInterface;

class DownloadSyncBuilder extends AbstractSyncBuilder
{
    /** @var bool */
    protected $resumable = false;

    /** @var string */
    protected $directory;

    /** @var int Number of files that can be transferred concurrently */
    protected $concurrency = 5;

    /**
     * Set the directory where the objects from be downloaded to
     *
     * @param string $directory Directory
     *
     * @return $this
     */
    public function setDirectory($directory)
    {
        $this->directory = $directory;

        return $this;
    }

    /**
     * Call this function to allow partial downloads to be resumed if the download was previously interrupted
     *
     * @return self
     */
    public function allowResumableDownloads()
    {
        $this->resumable = true;

        return $this;
    }

    protected function specificBuild()
    {
        $sync = new DownloadSync(array(
            'client'           => $this->client,
            'bucket'           => $this->bucket,
            'iterator'         => $this->sourceIterator,
            'source_converter' => $this->sourceConverter,
            'target_converter' => $this->targetConverter,
            'concurrency'      => $this->concurrency,
            'resumable'        => $this->resumable,
            'directory'        => $this->directory
        ));

        return $sync;
    }

    protected function getTargetIterator()
    {
        if (!$this->directory) {
            throw new RuntimeException('A directory is required');
        }

        if (!is_dir($this->directory) && !mkdir($this->directory, 0777, true)) {
            // @codeCoverageIgnoreStart
            throw new RuntimeException('Unable to create root download directory: ' . $this->directory);
            // @codeCoverageIgnoreEnd
        }

        return $this->filterIterator(
            new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->directory))
        );
    }

    protected function getDefaultSourceConverter()
    {
        return new KeyConverter(
            "s3://{$this->bucket}/{$this->baseDir}",
            $this->directory . DIRECTORY_SEPARATOR, $this->delimiter
        );
    }

    protected function getDefaultTargetConverter()
    {
        return new KeyConverter("s3://{$this->bucket}/{$this->baseDir}", '', $this->delimiter);
    }

    protected function assertFileIteratorSet()
    {
        $this->sourceIterator = $this->sourceIterator ?: $this->createS3Iterator();
    }

    protected function addDebugListener(AbstractSync $sync, $resource)
    {
        $sync->getEventDispatcher()->addListener(UploadSync::BEFORE_TRANSFER, function (Event $e) use ($resource) {
            if ($e['command'] instanceof CommandInterface) {
                $from = $e['command']['Bucket'] . '/' . $e['command']['Key'];
                $to = $e['command']['SaveAs'] instanceof EntityBodyInterface
                    ? $e['command']['SaveAs']->getUri()
                    : $e['command']['SaveAs'];
                fwrite($resource, "Downloading {$from} -> {$to}\n");
            } elseif ($e['command'] instanceof ResumableDownload) {
                $from = $e['command']->getBucket() . '/' . $e['command']->getKey();
                $to = $e['command']->getFilename();
                fwrite($resource, "Resuming {$from} -> {$to}\n");
            }
        });
    }
}
FilenameConverterInterface.php000060400000001625152444467260012524 0ustar00<?php
/**
 * Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 * http://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file is distributed
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

namespace Aws\S3\Sync;

/**
 * Converts filenames from one system to another (e.g. local to Amazon S3)
 */
interface FilenameConverterInterface
{
    /**
     * Convert a filename
     *
     * @param string $filename Name of the file to convert
     *
     * @return string
     */
    public function convert($filename);
}
AbstractSyncBuilder.php000060400000030352152444467260011201 0ustar00<?php
/**
 * Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 * http://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file is distributed
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

namespace Aws\S3\Sync;

use Aws\Common\Exception\RuntimeException;
use Aws\Common\Exception\UnexpectedValueException;
use Aws\S3\S3Client;
use Aws\S3\Iterator\OpendirIterator;
use Guzzle\Common\Event;
use Guzzle\Common\HasDispatcherInterface;
use Guzzle\Iterator\FilterIterator;
use Guzzle\Service\Command\CommandInterface;

abstract class AbstractSyncBuilder
{
    /** @var \Iterator Iterator that returns SplFileInfo objects to upload */
    protected $sourceIterator;

    /** @var S3Client Amazon S3 client used to send requests */
    protected $client;

    /** @var string Bucket used with the transfer */
    protected $bucket;

    /** @var int Number of files that can be transferred concurrently */
    protected $concurrency = 10;

    /** @var array Custom parameters to add to each operation sent while transferring */
    protected $params = array();

    /** @var FilenameConverterInterface */
    protected $sourceConverter;

    /** @var FilenameConverterInterface */
    protected $targetConverter;

    /** @var string Prefix at prepend to each Amazon S3 object key */
    protected $keyPrefix = '';

    /** @var string Directory separator for Amazon S3 keys */
    protected $delimiter = '/';

    /** @var string Base directory to remove from each file path before converting to an object name or file name */
    protected $baseDir;

    /** @var bool Whether or not to only transfer modified or new files */
    protected $forcing = false;

    /** @var bool Whether or not debug output is enable */
    protected $debug;

    /**
     * @return static
     */
    public static function getInstance()
    {
        return new static();
    }

    /**
     * Set the bucket to use with the sync
     *
     * @param string $bucket Amazon S3 bucket name
     *
     * @return $this
     */
    public function setBucket($bucket)
    {
        $this->bucket = $bucket;

        return $this;
    }

    /**
     * Set the Amazon S3 client object that will send requests
     *
     * @param S3Client $client Amazon S3 client
     *
     * @return $this
     */
    public function setClient(S3Client $client)
    {
        $this->client = $client;

        return $this;
    }

    /**
     * Set a custom iterator that returns \SplFileInfo objects for the source data
     *
     * @param \Iterator $iterator
     *
     * @return $this
     */
    public function setSourceIterator(\Iterator $iterator)
    {
        $this->sourceIterator = $iterator;

        return $this;
    }

    /**
     * Set a custom object key provider instead of building one internally
     *
     * @param FileNameConverterInterface $converter Filename to object key provider
     *
     * @return $this
     */
    public function setSourceFilenameConverter(FilenameConverterInterface $converter)
    {
        $this->sourceConverter = $converter;

        return $this;
    }

    /**
     * Set a custom object key provider instead of building one internally
     *
     * @param FileNameConverterInterface $converter Filename to object key provider
     *
     * @return $this
     */
    public function setTargetFilenameConverter(FilenameConverterInterface $converter)
    {
        $this->targetConverter = $converter;

        return $this;
    }

    /**
     * Set the base directory of the files being transferred. The base directory is removed from each file path before
     * converting the file path to an object key or vice versa.
     *
     * @param string $baseDir Base directory, which will be deleted from each uploaded object key
     *
     * @return $this
     */
    public function setBaseDir($baseDir)
    {
        $this->baseDir = $baseDir;

        return $this;
    }

    /**
     * Specify a prefix to prepend to each Amazon S3 object key or the prefix where object are stored in a bucket
     *
     * Can be used to upload files to a pseudo sub-folder key or only download files from a pseudo sub-folder
     *
     * @param string $keyPrefix Prefix for each uploaded key
     *
     * @return $this
     */
    public function setKeyPrefix($keyPrefix)
    {
        // Removing leading slash
        $this->keyPrefix = ltrim($keyPrefix, '/');

        return $this;
    }

    /**
     * Specify the delimiter used for the targeted filesystem (default delimiter is "/")
     *
     * @param string $delimiter Delimiter to use to separate paths
     *
     * @return $this
     */
    public function setDelimiter($delimiter)
    {
        $this->delimiter = $delimiter;

        return $this;
    }

    /**
     * Specify an array of operation parameters to apply to each operation executed by the sync object
     *
     * @param array $params Associative array of PutObject (upload) GetObject (download) parameters
     *
     * @return $this
     */
    public function setOperationParams(array $params)
    {
        $this->params = $params;

        return $this;
    }

    /**
     * Set the number of files that can be transferred concurrently
     *
     * @param int $concurrency Number of concurrent transfers
     *
     * @return $this
     */
    public function setConcurrency($concurrency)
    {
        $this->concurrency = $concurrency;

        return $this;
    }

    /**
     * Set to true to force transfers even if a file already exists and has not changed
     *
     * @param bool $force Set to true to force transfers without checking if it has changed
     *
     * @return $this
     */
    public function force($force = false)
    {
        $this->forcing = (bool) $force;

        return $this;
    }

    /**
     * Enable debug mode
     *
     * @param bool|resource $enabledOrResource Set to true or false to enable or disable debug output. Pass an opened
     *                                         fopen resource to write to instead of writing to standard out.
     * @return $this
     */
    public function enableDebugOutput($enabledOrResource = true)
    {
        $this->debug = $enabledOrResource;

        return $this;
    }

    /**
     * Add a filename filter that uses a regular expression to filter out files that you do not wish to transfer.
     *
     * @param string $search Regular expression search (in preg_match format). Any filename that matches this regex
     *                       will not be transferred.
     * @return $this
     */
    public function addRegexFilter($search)
    {
        $this->assertFileIteratorSet();
        $this->sourceIterator = new FilterIterator($this->sourceIterator, function ($i) use ($search) {
            return !preg_match($search, (string) $i);
        });
        $this->sourceIterator->rewind();

        return $this;
    }

    /**
     * Builds a UploadSync or DownloadSync object
     *
     * @return AbstractSync
     */
    public function build()
    {
        $this->validateRequirements();
        $this->sourceConverter = $this->sourceConverter ?: $this->getDefaultSourceConverter();
        $this->targetConverter = $this->targetConverter ?: $this->getDefaultTargetConverter();

        // Only wrap the source iterator in a changed files iterator if we are not forcing the transfers
        if (!$this->forcing) {
            $this->sourceIterator->rewind();
            $this->sourceIterator = new ChangedFilesIterator(
                new \NoRewindIterator($this->sourceIterator),
                $this->getTargetIterator(),
                $this->sourceConverter,
                $this->targetConverter
            );
            $this->sourceIterator->rewind();
        }

        $sync = $this->specificBuild();

        if ($this->params) {
            $this->addCustomParamListener($sync);
        }

        if ($this->debug) {
            $this->addDebugListener($sync, is_bool($this->debug) ? STDOUT : $this->debug);
        }

        return $sync;
    }

    /**
     * Hook to implement in subclasses
     *
     * @return AbstractSync
     */
    abstract protected function specificBuild();

    /**
     * @return \Iterator
     */
    abstract protected function getTargetIterator();

    /**
     * @return FilenameConverterInterface
     */
    abstract protected function getDefaultSourceConverter();

    /**
     * @return FilenameConverterInterface
     */
    abstract protected function getDefaultTargetConverter();

    /**
     * Add a listener to the sync object to output debug information while transferring
     *
     * @param AbstractSync $sync     Sync object to listen to
     * @param resource     $resource Where to write debug messages
     */
    abstract protected function addDebugListener(AbstractSync $sync, $resource);

    /**
     * Validate that the builder has the minimal requirements
     *
     * @throws RuntimeException if the builder is not configured completely
     */
    protected function validateRequirements()
    {
        if (!$this->client) {
            throw new RuntimeException('No client was provided');
        }
        if (!$this->bucket) {
            throw new RuntimeException('No bucket was provided');
        }
        $this->assertFileIteratorSet();
    }

    /**
     * Ensure that the base file iterator has been provided
     *
     * @throws RuntimeException
     */
    protected function assertFileIteratorSet()
    {
        // Interesting... Need to use isset because: Object of class GlobIterator could not be converted to boolean
        if (!isset($this->sourceIterator)) {
            throw new RuntimeException('A source file iterator must be specified');
        }
    }

    /**
     * Wraps a generated iterator in a filter iterator that removes directories
     *
     * @param \Iterator $iterator Iterator to wrap
     *
     * @return \Iterator
     * @throws UnexpectedValueException
     */
    protected function filterIterator(\Iterator $iterator)
    {
        $f = new FilterIterator($iterator, function ($i) {
            if (!$i instanceof \SplFileInfo) {
                throw new UnexpectedValueException('All iterators for UploadSync must return SplFileInfo objects');
            }
            return $i->isFile();
        });

        $f->rewind();

        return $f;
    }

    /**
     * Add the custom param listener to a transfer object
     *
     * @param HasDispatcherInterface $sync
     */
    protected function addCustomParamListener(HasDispatcherInterface $sync)
    {
        $params = $this->params;
        $sync->getEventDispatcher()->addListener(
            UploadSync::BEFORE_TRANSFER,
            function (Event $e) use ($params) {
                if ($e['command'] instanceof CommandInterface) {
                    $e['command']->overwriteWith($params);
                }
            }
        );
    }

    /**
     * Create an Amazon S3 file iterator based on the given builder settings
     *
     * @return OpendirIterator
     */
    protected function createS3Iterator()
    {
        // Ensure that the stream wrapper is registered
        $this->client->registerStreamWrapper();

        // Calculate the opendir() bucket and optional key prefix location
        $dir = "s3://{$this->bucket}";
        if ($this->keyPrefix) {
            $dir .= '/' . ltrim($this->keyPrefix, '/ ');
        }

        // Use opendir so that we can pass stream context to the iterator
        $dh = opendir($dir, stream_context_create(array(
            's3' => array(
                'delimiter'  => '',
                'listFilter' => function ($obj) {
                    // Ensure that we do not try to download a glacier object.
                    return !isset($obj['StorageClass']) ||
                        $obj['StorageClass'] != 'GLACIER';
                }
            )
        )));

        // Add the trailing slash for the OpendirIterator concatenation
        if (!$this->keyPrefix) {
            $dir .= '/';
        }

        return $this->filterIterator(new \NoRewindIterator(new OpendirIterator($dh, $dir)));
    }
}
ChangedFilesIterator.php000060400000007557152444467260011333 0ustar00<?php
/**
 * Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 * http://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file is distributed
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

namespace Aws\S3\Sync;

/**
 * Iterator used to filter an internal iterator to only yield files that do not exist in the target iterator or files
 * that have changed
 */
class ChangedFilesIterator extends \FilterIterator
{
    /** @var \Iterator */
    protected $sourceIterator;

    /** @var \Iterator */
    protected $targetIterator;

    /** @var FilenameConverterInterface */
    protected $sourceConverter;

    /** @var FilenameConverterInterface */
    protected $targetConverter;

    /** @var array Previously loaded data */
    protected $cache = array();

    /**
     * @param \Iterator                  $sourceIterator  Iterator to wrap and filter
     * @param \Iterator                  $targetIterator  Iterator used to compare against the source iterator
     * @param FilenameConverterInterface $sourceConverter Key converter to convert source to target keys
     * @param FilenameConverterInterface $targetConverter Key converter to convert target to source keys
     */
    public function __construct(
        \Iterator $sourceIterator,
        \Iterator $targetIterator,
        FilenameConverterInterface $sourceConverter,
        FilenameConverterInterface $targetConverter
    ) {
        $this->targetIterator = $targetIterator;
        $this->sourceConverter = $sourceConverter;
        $this->targetConverter = $targetConverter;
        parent::__construct($sourceIterator);
    }

    public function accept()
    {
        $current = $this->current();
        $key = $this->sourceConverter->convert($this->normalize($current));

        if (!($data = $this->getTargetData($key))) {
            return true;
        }

        // Ensure the Content-Length matches and it hasn't been modified since the mtime
        return $current->getSize() != $data[0] || $current->getMTime() > $data[1];
    }

    /**
     * Returns an array of the files from the target iterator that were not found in the source iterator
     *
     * @return array
     */
    public function getUnmatched()
    {
        return array_keys($this->cache);
    }

    /**
     * Get key information from the target iterator for a particular filename
     *
     * @param string $key Target iterator filename
     *
     * @return array|bool Returns an array of data, or false if the key is not in the iterator
     */
    protected function getTargetData($key)
    {
        $key = $this->cleanKey($key);

        if (isset($this->cache[$key])) {
            $result = $this->cache[$key];
            unset($this->cache[$key]);
            return $result;
        }

        $it = $this->targetIterator;

        while ($it->valid()) {
            $value = $it->current();
            $data = array($value->getSize(), $value->getMTime());
            $filename = $this->targetConverter->convert($this->normalize($value));
            $filename = $this->cleanKey($filename);

            if ($filename == $key) {
                return $data;
            }

            $this->cache[$filename] = $data;
            $it->next();
        }

        return false;
    }

    private function normalize($current)
    {
        $asString = (string) $current;

        return strpos($asString, 's3://') === 0
            ? $asString
            : $current->getRealPath();
    }

    private function cleanKey($key)
    {
        return ltrim($key, '/');
    }
}

Al-HUWAITI Shell