1: <?php
2: /**
3: * This file contains the the static file handler class.
4: *
5: * @package Core
6: * @subpackage Util
7: * @version SVN Revision $Rev:$
8: *
9: * @author Mischa Holz
10: * @copyright four for business AG <www.4fb.de>
11: * @license http://www.contenido.org/license/LIZENZ.txt
12: * @link http://www.4fb.de
13: * @link http://www.contenido.org
14: */
15: defined('CON_FRAMEWORK') || die('Illegal call: Missing framework initialization - request aborted.');
16:
17: /**
18: * Class for file handling.
19: * Provides functions for dealing with files.
20: *
21: * @package Core
22: * @subpackage Util
23: */
24: class cFileHandler {
25:
26: /**
27: * Creates a new file
28: *
29: * @param string $filename
30: * the name and path of the new file
31: * @param string $content [optional]
32: * content of the new file
33: * @return bool
34: * true on success. Otherwise false.
35: */
36: public static function create($filename, $content = '') {
37: $success = file_put_contents($filename, $content) === strlen($content);
38: if ($success) {
39: self::setDefaultFilePerms($filename);
40: }
41:
42: return $success;
43: }
44:
45: /**
46: * Reads bytes from a file
47: *
48: * @param string $filename
49: * the name and path of the file
50: * @param int $length [optional]
51: * the number of bytes to read.
52: * @param int $offset [optional]
53: * this will be the first byte which is read.
54: * @param bool $reverse [optional]
55: * if true, the function will start from the back of the file.
56: * @throws cInvalidArgumentException
57: * if the file with the given filename does not exist
58: * @return string|bool
59: * On success it returns the bytes which have been read.
60: * Otherwise false.
61: */
62: public static function read($filename, $length = 0, $offset = 0, $reverse = false) {
63: if (!cFileHandler::exists($filename)) {
64: throw new cInvalidArgumentException('The file ' . $filename . ' could not be accessed because it does not exist.');
65: }
66:
67: if ($reverse) {
68: return file_get_contents($filename, false, NULL, filesize($filename) - $length - $offset, $length);
69: } else if ($length > 0 && $offset == 0) {
70: return file_get_contents($filename, false, NULL, 0, $length);
71: } else if ($offset > 0 && $length == 0) {
72: return file_get_contents($filename, false, NULL, $offset);
73: } else if ($offset > 0 && $length > 0) {
74: return file_get_contents($filename, false, NULL, $offset, $length);
75: } else {
76: return file_get_contents($filename);
77: }
78: }
79:
80: /**
81: * Reads a file line by line
82: *
83: * @param string $filename
84: * the name and path of the file
85: * @param int $lines [optional]
86: * the number of lines to be read.
87: * @param int $lineoffset [optional]
88: * this will be the first line which is read.
89: * @throws cInvalidArgumentException
90: * if the file with the given filename does not exist
91: * @return string|array|bool
92: * If one line was read the function will return it.
93: * If more than one line was read the function will return an array
94: * containing the lines. Otherwise false is returned
95: */
96: public static function readLine($filename, $lines = 0, $lineoffset = 0) {
97: if (!cFileHandler::exists($filename)) {
98: throw new cInvalidArgumentException('The file ' . $filename . ' could not be accessed because it does not exist.');
99: }
100:
101: $f = fopen($filename, 'r');
102:
103: if ($f === false) {
104: fclose($f);
105: return false;
106: }
107: if ($lines == 0) {
108: $lines = 1;
109: }
110:
111: for ($i = 0; $i < $lineoffset; $i++) {
112: $waste = fgets($f);
113: }
114:
115: $ret = NULL;
116: if ($lines > 1) {
117: $ret = array();
118: for ($i = 0; $i < $lines; $i++) {
119: $temp = fgets($f);
120: if ($temp === false) {
121: fclose($f);
122: return false;
123: }
124: $ret[] = substr($temp, 0, strlen($temp) - 1);
125: }
126: } else {
127: $ret = fgets($f);
128: $ret = substr($ret, 0, strlen($ret) - 1);
129: }
130:
131: fclose($f);
132: return $ret;
133: }
134:
135: /**
136: * Writes data to a file
137: *
138: * @param string $filename
139: * the name and path of the file
140: * @param string $content
141: * the data which should be written
142: * @param bool $append [optional]
143: * if true the data will be appended to the file.
144: * @return bool
145: * true on success, false otherwise
146: */
147: public static function write($filename, $content, $append = false) {
148: $flag = 0;
149: if ($append && self::exists($filename)) {
150: $flag = FILE_APPEND;
151: }
152:
153: $success = file_put_contents($filename, $content, $flag);
154: if ((int) $success != 0) {
155: self::setDefaultFilePerms($filename);
156: }
157:
158: return !($success === false);
159: }
160:
161: /**
162: * Writes a line to a file (this is similar to
163: * cFileHandler::write($filename, $data."\n", $apppend)
164: *
165: * @see cFileHandler::write($filename, $content, $append)
166: * @param string $filename
167: * the name and path to the file
168: * @param string $content
169: * the data of the line
170: * @param bool $append [optional]
171: * if true the data will be appended to file.
172: * @return bool
173: * true on success, false otherwise
174: */
175: public static function writeLine($filename, $content, $append = false) {
176: return self::write($filename, $content . "\n", $append);
177: }
178:
179: /**
180: * Checks if a file exists
181: *
182: * @param string $filename
183: * the name and path of the file
184: * @return bool
185: * true if the file exists
186: */
187: public static function exists($filename) {
188: return file_exists($filename);
189: }
190:
191: /**
192: * Checks if the file is writable for the PHP user
193: *
194: * @param string $filename
195: * the name and path of the file
196: * @return bool
197: * true if the file can be written
198: */
199: public static function writeable($filename) {
200: return is_writable($filename);
201: }
202:
203: /**
204: * Checks if a file is readable for the PHP user
205: *
206: * @param string $filename
207: * the name and path of the file
208: * @throws cInvalidArgumentException
209: * if the file with the given filename does not exist
210: * @return bool
211: * true if the file is readable
212: */
213: public static function readable($filename) {
214: if (!cFileHandler::exists($filename)) {
215: throw new cInvalidArgumentException('The file ' . $filename . ' could not be accessed because it does not exist.');
216: }
217:
218: return is_readable($filename);
219: }
220:
221: /**
222: * Removes a file from the filesystem
223: *
224: * @param string $filename
225: * the name and path of the file
226: * @throws cInvalidArgumentException
227: * if the file with the given filename does not exist
228: * @return bool
229: * true on success
230: */
231: public static function remove($filename) {
232: if (!cFileHandler::exists($filename)) {
233: throw new cInvalidArgumentException('The file ' . $filename . ' could not be accessed because it does not exist.');
234: }
235:
236: return unlink($filename);
237: }
238:
239: /**
240: * Truncates a file so that it is empty
241: *
242: * @param string $filename
243: * the name and path of the file
244: * @throws cInvalidArgumentException
245: * if the file with the given filename does not exist
246: * @return bool
247: * true on success
248: */
249: public static function truncate($filename) {
250: if (!cFileHandler::exists($filename)) {
251: throw new cInvalidArgumentException('The file ' . $filename . ' could not be accessed because it does not exist.');
252: }
253: $success = file_put_contents($filename, '') === 0;
254: if ($success) {
255: self::setDefaultFilePerms($filename);
256: }
257:
258: return $success;
259: }
260:
261: /**
262: * Moves a file
263: *
264: * @param string $filename
265: * the name of the source file
266: * @param string $destination
267: * the destination. Note that the file can also be renamed in the
268: * process of moving it
269: * @throws cInvalidArgumentException
270: * if the file with the given filename does not exist
271: * @return bool
272: * true on success
273: */
274: public static function move($filename, $destination) {
275: if (!cFileHandler::exists($filename)) {
276: throw new cInvalidArgumentException('The file ' . $filename . ' could not be accessed because it does not exist.');
277: }
278: $success = rename($filename, $destination);
279: if ($success) {
280: self::setDefaultFilePerms($destination);
281: }
282:
283: return $success;
284: }
285:
286: /**
287: * Renames a file
288: *
289: * @param string $filename
290: * the name and path of the file
291: * @param string $new_filename
292: * the new name of the file
293: * @throws cInvalidArgumentException
294: * if the file with the given filename does not exist
295: * @return bool
296: * true on success
297: */
298: public static function rename($filename, $new_filename) {
299: if (!cFileHandler::exists($filename)) {
300: throw new cInvalidArgumentException('The file ' . $filename . ' could not be accessed because it does not exist.');
301: }
302: $success = rename($filename, dirname($filename) . '/' . $new_filename);
303: if ($success) {
304: self::setDefaultFilePerms(dirname($filename) . '/' . $new_filename);
305: }
306:
307: return $success;
308: }
309:
310: /**
311: * Copies a file
312: *
313: * @param string $filename
314: * the name and path of the file
315: * @param string $destination
316: * the destination. Note that existing files get overwritten
317: * @throws cInvalidArgumentException
318: * if the file with the given filename does not exist
319: * @return bool
320: * true on success
321: */
322: public static function copy($filename, $destination) {
323: if (!cFileHandler::exists($filename)) {
324: throw new cInvalidArgumentException('The file ' . $filename . ' could not be accessed because it does not exist.');
325: }
326: $success = copy($filename, $destination);
327: if ($success) {
328: self::setDefaultFilePerms($destination);
329: }
330:
331: return $success;
332: }
333:
334: /**
335: * Changes the file permissions
336: *
337: * @param string $filename
338: * the name and path of the file
339: * @param int $mode
340: * the new access mode : php chmod needs octal value
341: * @throws cInvalidArgumentException
342: * if the file with the given filename does not exist
343: * @return bool
344: * true on success
345: */
346: public static function chmod($filename, $mode) {
347: if (!cFileHandler::exists($filename)) {
348: throw new cInvalidArgumentException('The file ' . $filename . ' could not be accessed because it does not exist.');
349: }
350: // chmod needs octal value for correct execution.
351: $mode = intval($mode, 8);
352: return chmod($filename, $mode);
353: }
354:
355: /**
356: * Returns an array containing information about the file.
357: * Currently
358: * following elements are in it: 'size' - the file size (in byte) 'atime' -
359: * the time the file was last accessed (unix timestamp) 'ctime' - time the
360: * file was created (unix timestamp) 'mtime' - time the file was last
361: * modified (unix timestamp) 'perms' - permissions of the file represented
362: * in 4 octal digits 'extension' - the file extension or '' if there's no
363: * extension 'mime' - the mime type of the file
364: *
365: * @param string $filename
366: * the name and path to the file
367: * @throws cInvalidArgumentException
368: * if the file with the given filename does not exist
369: * @return array
370: * Returns an array containing information about the file
371: */
372: public static function info($filename) {
373: if (!cFileHandler::exists($filename)) {
374: throw new cInvalidArgumentException('The file ' . $filename . ' could not be accessed because it does not exist.');
375: }
376:
377: $ret = array();
378:
379: $ret['size'] = @filesize($filename);
380: $ret['atime'] = @fileatime($filename);
381: $ret['ctime'] = @filectime($filename);
382: $ret['mtime'] = @filemtime($filename);
383:
384: $temp = @decoct(fileperms($filename));
385: $ret['perms'] = substr($temp, strlen($temp) - 4);
386:
387: $ret['extension'] = substr(basename($filename), (int) strrpos(basename($filename), '.') + 1);
388: if ($ret['extension'] == basename($filename)) {
389: $ret['extension'] = '';
390: }
391:
392: if (version_compare(PHP_VERSION, '5.3', '<') && function_exists('mime_content_type')) {
393: // function is deprecated in PHP 5.3
394: $ret['mime'] = @mime_content_type($filename);
395: } else if (function_exists('finfo_open')) {
396: // extension has to be installed seperately in versions prior to 5.3
397: $finfo = @finfo_open(FILEINFO_MIME_TYPE);
398: $ret['mime'] = @finfo_file($finfo, $filename);
399: } else {
400: $ret['mime'] = '';
401: }
402:
403: return $ret;
404: }
405:
406: /**
407: * Returns the extension of passed filename
408: *
409: * @param string $basename
410: * @return string
411: */
412: public static function getExtension($basename) {
413: return pathinfo($basename, PATHINFO_EXTENSION);
414: }
415:
416: /**
417: * Sets the default file permissions on the given file.
418: *
419: * @param string $filename
420: * the name of the file
421: * @return bool
422: * true on success or false on failure
423: */
424: public static function setDefaultFilePerms($filename) {
425: $cfg = cRegistry::getConfig();
426:
427: if (isset($cfg['default_perms']['file']) === false) {
428: return false;
429: }
430:
431: $filePerms = $cfg['default_perms']['file'];
432: return cFileHandler::chmod($filename, $filePerms);
433: }
434:
435: /**
436: * Validates the given filename.
437: *
438: * @param string $filename
439: * the filename to validate
440: * @param bool $notifyAndExitOnFailure [optional]
441: * if set, function will show a notification and will exit the script
442: * @return bool
443: * true if the given filename is valid, false otherwise
444: */
445: public static function validateFilename($filename, $notifyAndExitOnFailure = true) {
446: // check if filename only contains valid characters
447: if (preg_match('/[^a-z0-9._-]/i', $filename)) {
448: // validation failure...
449: if ($notifyAndExitOnFailure) {
450: // display notification and exit
451: cRegistry::addErrorMessage(i18n('Wrong file name.'));
452: $page = new cGuiPage('generic_page');
453: $page->abortRendering();
454: $page->render();
455: exit();
456: }
457:
458: return false;
459: }
460:
461: // check if filename is empty
462: if (strlen(trim($filename)) == 0) {
463: // validation failure...
464: if ($notifyAndExitOnFailure) {
465: // display notification and exit
466: $notification = new cGuiNotification();
467: $notification->displayNotification("error", i18n("Please insert file name."));
468: exit();
469: }
470:
471: return false;
472: }
473:
474: return true;
475: }
476:
477: /**
478: * Check if given filename is either '.' or '..'.
479: *
480: * @param string $fileName
481: * @return bool
482: */
483: public static function fileNameIsDot($fileName) {
484: // bugfix: function must work with full paths of files
485: $name = end(explode('/', $fileName));
486: if ($name != '.' && $name != '..') {
487: return false;
488: } else {
489: return true;
490: }
491: }
492:
493: /**
494: * Check if file name begins with a period.
495: *
496: * @param string $fileName
497: * @return bool
498: */
499: public static function fileNameBeginsWithDot($fileName) {
500: return strpos(end(explode('/', $fileName)), ".") === 0;
501: }
502: }
503: