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