2 namespace TYPO3\CMS\Core\Http\Observer
;
4 /***************************************************************
7 * (c) 2011 Philipp Gampe (dev.typo3@philippgampe.info)
10 * This script is part of the TYPO3 project. The TYPO3 project is
11 * free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * The GNU General Public License can be found at
17 * http://www.gnu.org/copyleft/gpl.html.
18 * A copy is found in the textfile GPL.txt and important notices to the license
19 * from the author is found in LICENSE.txt distributed with these scripts.
22 * This script is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
27 * This copyright notice MUST APPEAR in all copies of the script!
28 ***************************************************************/
30 * Observer to automatically save a http request chunk by chunk to a file.
31 * If the file already exists, it will be overwritten.
32 * This follows an example in HTTP_Request2 manual.
34 * @see http://pear.php.net/manual/en/package.http.http-request2.observers.php
35 * @author Philipp Gampe
37 class Download
implements SplObserver
{
40 * @var resource A file pointer resource
42 protected $filePointer = FALSE;
45 * @var string The full filename including the leading directory
47 protected $targetFilePath = '';
50 * @var string The name of the target directory
52 protected $targetDirectory = '';
55 * @var string The name of the target file
57 protected $targetFilename = '';
62 * @throws InvalidArgumentException if directory is not found or is not within the PATH_site
63 * @param string $directory The absolute path to the directory in which the file is saved.
64 * @param string $filename The filename - if not set, it is determined automatically.
66 public function __construct($directory, $filename = '') {
67 $this->setDirectory($directory);
68 $this->setFilename($filename);
72 * Saves current chunk to disk each time a body part is received.
73 * If the filename is empty, tries to determine it from received headers
75 * @throws \TYPO3\CMS\Core\Exception if file can not be opened
76 * @throws UnexpectedValueException if the file name is empty and can not be determined from headers
77 * @param SplSubject|HTTP_Request2 $request
80 public function update(\SplSubject
$request) {
81 $event = $request->getLastEvent();
82 switch ($event['name']) {
83 case 'receivedHeaders':
84 if ($this->targetFilename
=== '') {
85 $this->determineFilename($request, $event['data']);
89 case 'receivedBodyPart':
91 case 'receivedEncodedBodyPart':
92 fwrite($this->filePointer
, $event['data']);
103 * Sets the directory and checks whether the directory is available.
105 * @throws InvalidArgumentException if directory is not found or is not within the PATH_site
106 * @param string $directory The absolute path to the directory in which the file is saved.
109 public function setDirectory($directory) {
110 if (!is_dir($directory)) {
111 throw new \
InvalidArgumentException($directory . ' is not a directory', 1312223779);
113 if (!\TYPO3\CMS\Core\Utility\GeneralUtility
::isAllowedAbsPath($directory)) {
114 throw new \
InvalidArgumentException(($directory . ' is not within the PATH_site') . ' OR within the lockRootPath', 1328734617);
116 $this->targetDirectory
= ($directory = rtrim($directory, DIRECTORY_SEPARATOR
));
122 * If the file already exists, it will be overridden
124 * @param string $filename The filename
127 public function setFilename($filename = '') {
128 $this->targetFilename
= basename($filename);
132 * Determines the filename from either the 'content-disposition' header
133 * or from the basename of the current request.
135 * @param HTTP_Request2 $request
136 * @param HTTP_Request2_Response $response
139 protected function determineFilename(\HTTP_Request2
$request, \HTTP_Request2_Response
$response) {
141 $disposition = $response->getHeader('content-disposition');
142 if (($disposition !== NULL && 0 === strpos($disposition, 'attachment')) && 1 === preg_match('/filename="([^"]+)"/', $disposition, $matches)) {
143 $filename = basename($matches[1]);
145 $filename = basename($request->getUrl()->getPath());
147 $this->setFilename($filename);
151 * Determines the absolute path to the file by combining the directory and filename.
152 * Afterwards tries to open the file for writing.
154 * $this->filename must be set before calling this function.
156 * @throws UnexpectedValueException if $this->filename is not set
157 * @throws \TYPO3\CMS\Core\Exception if file can not be opened
160 protected function openFile() {
161 if ($this->targetFilename
=== '') {
162 throw new \
UnexpectedValueException('The file name must not be empty', 1321113658);
164 $this->targetFilePath
= ($this->targetDirectory
. DIRECTORY_SEPARATOR
) . $this->targetFilename
;
165 $this->filePointer
= @fopen
($this->targetFilePath
, 'wb');
166 if ($this->filePointer
=== FALSE) {
167 throw new \TYPO3\CMS\Core\
Exception('Cannot open target file ' . $this->targetFilePath
, 1320833203);
172 * Closes the file handler and fixes permissions.
176 protected function closeFile() {
177 fclose($this->filePointer
);
178 $this->filePointer
= FALSE;
179 \TYPO3\CMS\Core\Utility\GeneralUtility
::fixPermissions($this->targetFilePath
);