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