[BUGFIX] Fix Http_Request after namespace changes
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Http / Observer / Download.php
1 <?php
2 namespace TYPO3\CMS\Core\Http\Observer;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 2011-2012 Philipp Gampe <philipp.gampe@typo3.org>
8 * All rights reserved
9 *
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.
15 *
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.
20 *
21 *
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.
26 *
27 * This copyright notice MUST APPEAR in all copies of the script!
28 ***************************************************************/
29 /**
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.
33 *
34 * @see http://pear.php.net/manual/en/package.http.http-request2.observers.php
35 * @author Philipp Gampe
36 */
37 class Download implements \SplObserver {
38
39 /**
40 * @var resource A file pointer resource
41 */
42 protected $filePointer = FALSE;
43
44 /**
45 * @var string The full filename including the leading directory
46 */
47 protected $targetFilePath = '';
48
49 /**
50 * @var string The name of the target directory
51 */
52 protected $targetDirectory = '';
53
54 /**
55 * @var string The name of the target file
56 */
57 protected $targetFilename = '';
58
59 /**
60 * Constructor
61 *
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.
65 */
66 public function __construct($directory, $filename = '') {
67 $this->setDirectory($directory);
68 $this->setFilename($filename);
69 }
70
71 /**
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
74 *
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
78 * @return void
79 */
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']);
86 }
87 $this->openFile();
88 break;
89 case 'receivedBodyPart':
90
91 case 'receivedEncodedBodyPart':
92 fwrite($this->filePointer, $event['data']);
93 break;
94 case 'receivedBody':
95 $this->closeFile();
96 break;
97 default:
98
99 }
100 }
101
102 /**
103 * Sets the directory and checks whether the directory is available.
104 *
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.
107 * @return void
108 */
109 public function setDirectory($directory) {
110 if (!is_dir($directory)) {
111 throw new \InvalidArgumentException($directory . ' is not a directory', 1312223779);
112 }
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);
115 }
116 $this->targetDirectory = ($directory = rtrim($directory, DIRECTORY_SEPARATOR));
117 }
118
119 /**
120 * Sets the filename.
121 *
122 * If the file already exists, it will be overridden
123 *
124 * @param string $filename The filename
125 * @return void
126 */
127 public function setFilename($filename = '') {
128 $this->targetFilename = basename($filename);
129 }
130
131 /**
132 * Determines the filename from either the 'content-disposition' header
133 * or from the basename of the current request.
134 *
135 * @param \HTTP_Request2 $request
136 * @param \HTTP_Request2_Response $response
137 * @return void
138 */
139 protected function determineFilename(\HTTP_Request2 $request, \HTTP_Request2_Response $response) {
140 $matches = array();
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]);
144 } else {
145 $filename = basename($request->getUrl()->getPath());
146 }
147 $this->setFilename($filename);
148 }
149
150 /**
151 * Determines the absolute path to the file by combining the directory and filename.
152 * Afterwards tries to open the file for writing.
153 *
154 * $this->filename must be set before calling this function.
155 *
156 * @throws \UnexpectedValueException if $this->filename is not set
157 * @throws \TYPO3\CMS\Core\Exception if file can not be opened
158 * @return void
159 */
160 protected function openFile() {
161 if ($this->targetFilename === '') {
162 throw new \UnexpectedValueException('The file name must not be empty', 1321113658);
163 }
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);
168 }
169 }
170
171 /**
172 * Closes the file handler and fixes permissions.
173 *
174 * @return void
175 */
176 protected function closeFile() {
177 fclose($this->filePointer);
178 $this->filePointer = FALSE;
179 \TYPO3\CMS\Core\Utility\GeneralUtility::fixPermissions($this->targetFilePath);
180 }
181
182 }
183
184 ?>