gradelib MDL-19376 Fixed full view link
[moodle.git] / lib / file / stored_file.php
CommitLineData
16a95e8f 1<?php
2
3// This file is part of Moodle - http://moodle.org/
4//
5// Moodle is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// Moodle is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
17
18
19/**
20 * Class representing filesin Moodle file storage.
21 *
64a19b38 22 * @package moodlecore
23 * @subpackage file-storage
24 * @copyright 2008 Petr Skoda (http://skodak.org)
25 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
16a95e8f 26 */
27
28require_once("$CFG->libdir/file/stored_file.php");
172dd12c 29
30/**
31 * Class representing local files stored in sha1 file pool
32 */
33class stored_file {
34 private $fs;
35 private $file_record;
36
37 /**
38 * Constructor
39 * @param object $fs file storage instance
40 * @param object $file_record description of file
41 */
42 public function __construct($fs, $file_record) {
43 $this->fs = $fs;
44 $this->file_record = clone($file_record);
45 }
46
47 /**
48 * Is this a directory?
49 * @return bool
50 */
51 public function is_directory() {
52 return $this->file_record->filename === '.';
53 }
54
55 /**
56 * Delete file
57 * @return success
58 */
59 public function delete() {
60 global $DB;
61 $this->fs->mark_delete_candidate($this->file_record->contenthash);
62 return $DB->delete_records('files', array('id'=>$this->file_record->id));
63 }
64
65 /**
6c0e2d08 66 * Protected - developers must not gain direct access to this function
17d9269f 67 * NOTE: do not make this public, we must not modify or delete the pool files directly! ;-)
68 * @return ful path to pool file with file content
172dd12c 69 **/
70 protected function get_content_file_location() {
744b64ff 71 $filedir = $this->fs->get_filedir();
17d9269f 72 $contenthash = $this->file_record->contenthash;
73 $l1 = $contenthash[0].$contenthash[1];
74 $l2 = $contenthash[2].$contenthash[3];
75 $l3 = $contenthash[4].$contenthash[5];
76 return "$filedir/$l1/$l2/$l3/$contenthash";
172dd12c 77 }
78
5035a8b4 79 /**
80 * adds this file path to a curl request (POST only)
81 *
82 * @param curl $curlrequest the curl request object
83 * @param string $key what key to use in the POST request
84 */
85 public function add_to_curl_request(&$curlrequest, $key) {
86 $curlrequest->_tmp_file_post_params[$key] = '@' . $this->get_content_file_location();
87 }
88
172dd12c 89 /**
90 * Returns file handle - read only mode, no writing allowed into pool files!
91 * @return file handle
92 */
93 public function get_content_file_handle() {
94 $path = $this->get_content_file_location();
95 if (!is_readable($path)) {
145a0a31 96 throw new file_exception('storedfilecannotread');
172dd12c 97 }
98 return fopen($path, 'rb'); //binary reading only!!
99 }
100
101 /**
102 * Dumps file content to page
103 * @return file handle
104 */
105 public function readfile() {
106 $path = $this->get_content_file_location();
107 if (!is_readable($path)) {
145a0a31 108 throw new file_exception('storedfilecannotread');
172dd12c 109 }
110 readfile($path);
111 }
112
113 /**
114 * Returns file content as string
115 * @return string content
116 */
117 public function get_content() {
118 $path = $this->get_content_file_location();
119 if (!is_readable($path)) {
145a0a31 120 throw new file_exception('storedfilecannotread');
172dd12c 121 }
122 return file_get_contents($this->get_content_file_location());
123 }
124
6c0e2d08 125 /**
126 * Copy content of file to give npathname
17d9269f 127 * @param string $pathnema rela path to new file
6c0e2d08 128 * @return bool success
129 */
130 public function copy_content_to($pathname) {
131 $path = $this->get_content_file_location();
132 if (!is_readable($path)) {
145a0a31 133 throw new file_exception('storedfilecannotread');
6c0e2d08 134 }
135 return copy($path, $pathname);
136 }
137
17d9269f 138 /**
c78a0558 139 * List contents of archive
140 * @param object $file_packer
141 * @return array of file infos
142 */
143 public function list_files(file_packer $packer) {
144 $archivefile = $this->get_content_file_location();
145 return $packer->list_files($archivefile);
146 }
147
148 /**
149 * Extract file to given file path (real OS filesystem), existing files are overwrited
0b0bfa93 150 * @param object $file_packer
151 * @param string $pathname target directory
17d9269f 152 * @return mixed list of processed files; false if error
153 */
0b0bfa93 154 public function extract_to_pathname(file_packer $packer, $pathname) {
155 $archivefile = $this->get_content_file_location();
156 return $packer->extract_to_pathname($archivefile, $pathname);
17d9269f 157 }
158
159 /**
c78a0558 160 * Extract file to given file path (real OS filesystem), existing files are overwrited
0b0bfa93 161 * @param object $file_packer
17d9269f 162 * @param int $contextid
163 * @param string $filearea
164 * @param int $itemid
165 * @param string $pathbase
166 * @param int $userid
167 * @return mixed list of processed files; false if error
168 */
0b0bfa93 169 public function extract_to_storage(file_packer $packer, $contextid, $filearea, $itemid, $pathbase, $userid=null) {
170 $archivefile = $this->get_content_file_location();
171 return $packer->extract_to_storage($archivefile, $contextid, $filearea, $itemid, $pathbase);
17d9269f 172 }
173
b1897a6d 174 /**
c78a0558 175 * Add file/directory into archive
176 * @param object $filearch
177 * @param string $archivepath pathname in archive
b1897a6d 178 * @return bool success
179 */
0b0bfa93 180 public function archive_file(file_archive $filearch, $archivepath) {
b1897a6d 181 if ($this->is_directory()) {
0b0bfa93 182 return $filearch->add_directory($archivepath);
b1897a6d 183 } else {
184 $path = $this->get_content_file_location();
185 if (!is_readable($path)) {
186 return false;
187 }
0b0bfa93 188 return $filearch->add_file_from_pathname($archivepath, $path);
b1897a6d 189 }
190 }
191
797f19e8 192 /**
193 * Returns information about image,
194 * information is determined from the file content
195 * @return mixed array with width, height and mimetype; false if not an image
196 */
197 public function get_imageinfo() {
198 if (!$imageinfo = getimagesize($this->get_content_file_location())) {
199 return false;
200 }
201 $image = array('width'=>$imageinfo[0], 'height'=>$imageinfo[1], 'mimetype'=>image_type_to_mime_type($imageinfo[2]));
202 if (empty($image['width']) or empty($image['height']) or empty($image['mimetype'])) {
203 // gd can not parse it, sorry
204 return false;
205 }
206 return $image;
207 }
208
209 /**
210 * Verifies the file is a valid web image - gif, png and jpeg only.
211 * It should be ok to serve this image from server without any other security workarounds.
212 * @return bool true if file ok
213 */
214 public function is_valid_image() {
215 $mimetype = $this->get_mimetype();
216 if ($mimetype !== 'image/gif' and $mimetype !== 'image/jpeg' and $mimetype !== 'image/png') {
217 return false;
218 }
219 if (!$info = $this->get_imageinfo()) {
220 return false;
221 }
222 if ($info['mimetype'] !== $mimetype) {
223 return false;
224 }
225 // ok, GD likes this image
226 return true;
227 }
228
4b6b5ce7 229 /**
230 * Returns parent directory, creates missing parents if needed
231 * @return object stored_file
232 */
233 public function get_parent_directory() {
234 if ($this->file_record->filepath === '/' and $this->file_record->filename === '.') {
235 //root dir does not have parent
236 return null;
237 }
238
239 if ($this->file_record->filename !== '.') {
240 return $this->fs->create_directory($this->file_record->contextid, $this->file_record->filearea, $this->file_record->itemid, $this->file_record->filepath);
241 }
242
243 $filepath = $this->file_record->filepath;
244 $filepath = trim($filepath, '/');
245 $dirs = explode('/', $filepath);
246 array_pop($dirs);
247 $filepath = implode('/', $dirs);
248 $filepath = ($filepath === '') ? '/' : "/$filepath/";
249
250 return $this->fs->create_directory($this->file_record->contextid, $this->file_record->filearea, $this->file_record->itemid, $filepath);
251 }
252
16a95e8f 253 /**
254 * Returns context id of the file
255 * @return int context id
256 */
172dd12c 257 public function get_contextid() {
258 return $this->file_record->contextid;
259 }
260
16a95e8f 261 /**
262 * Returns file area name, the areas do not have to be unique,
263 * but usually have form pluginname_typeofarea such as forum_attachments
264 * @return string
265 */
172dd12c 266 public function get_filearea() {
267 return $this->file_record->filearea;
268 }
269
16a95e8f 270 /**
271 * Returns returns item id of file
272 * @return int
273 */
172dd12c 274 public function get_itemid() {
275 return $this->file_record->itemid;
276 }
277
16a95e8f 278 /**
279 * Returns file path - starts and ends with /, \ are not allowed.
280 * @return string
281 */
172dd12c 282 public function get_filepath() {
283 return $this->file_record->filepath;
284 }
285
16a95e8f 286 /**
287 * Returns file name or '.' in case of directories.
288 * @return string
289 */
172dd12c 290 public function get_filename() {
291 return $this->file_record->filename;
292 }
293
16a95e8f 294 /**
295 * Returns id of user who created the file.
296 * @return int
297 */
172dd12c 298 public function get_userid() {
299 return $this->file_record->userid;
300 }
301
16a95e8f 302 /**
303 * Returns the size of file in bytes.
304 * @return int bytes
305 */
172dd12c 306 public function get_filesize() {
307 return $this->file_record->filesize;
308 }
309
16a95e8f 310 /**
311 * Returns mime type of file
312 * @return string
313 */
172dd12c 314 public function get_mimetype() {
315 return $this->file_record->mimetype;
316 }
317
16a95e8f 318 /**
319 * Returns unix timestamp of file creation date
320 * @return int
321 */
172dd12c 322 public function get_timecreated() {
323 return $this->file_record->timecreated;
324 }
325
16a95e8f 326 /**
327 * Returns unix timestamp of last file modification
328 * @return int
329 */
172dd12c 330 public function get_timemodified() {
331 return $this->file_record->timemodified;
332 }
6c0e2d08 333
16a95e8f 334 /**
335 * Returns file status flag
336 * @return int 0 means file OK, anything else is a problem and file can not be used
337 */
6c0e2d08 338 public function get_status() {
339 return $this->file_record->status;
340 }
ee03a651 341
16a95e8f 342 /**
343 * Returns file id
344 * @return int
345 */
ee03a651 346 public function get_id() {
347 return $this->file_record->id;
348 }
4284e1cc 349
16a95e8f 350 /**
351 * Returns sha1 hash of file content
352 * @return string
353 */
4284e1cc 354 public function get_contenthash() {
355 return $this->file_record->contenthash;
356 }
6ed19c74 357
16a95e8f 358 /**
359 * Returns sha1 hash of all file path components sha1(contextid/filearea/itemid/dir/dir/filename.ext)
360 * @return string
361 */
6ed19c74 362 public function get_pathnamehash() {
363 return $this->file_record->pathnamehash;
364 }
172dd12c 365}