'application/vnd.oasis.opendocument.text', 'odp' => 'application/vnd.oasis.opendocument.presentation', 'ods' => 'application/vnd.oasis.opendocument.spreadsheet', 'sxw' => 'application/vnd.sun.xml.writer', 'sxc' => 'application/vnd.sun.xml.calc', 'sxi' => 'application/vnd.sun.xml.impress', 'ppt' => 'application/mspowerpoint', 'doc' => 'application/msword', 'xls' => 'application/msexcel', 'rtf' => 'application/rtf', 'pdf' => 'application/pdf', 'ps' => 'application/postscript', 'ai' => 'application/postscript', 'eps' => 'application/postscript', 'json' => 'application/json', 'xml' => 'application/xml', 'bin' => 'application/octet-stream', 'exe' => 'application/octet-stream', 'bz2' => 'application/x-bzip', 'deb' => 'application/x-debian-package', 'gz' => 'application/x-gzip', 'jar' => 'application/x-java-archive', 'rar' => 'application/rar', 'rpm' => 'application/x-redhat-package-manager', 'tar' => 'application/x-tar', 'tgz' => 'application/x-gtar', 'zip' => 'application/zip', 'aiff' => 'audio/x-aiff', 'ua' => 'audio/basic', 'mp3' => 'audio/mpeg3', 'mid' => 'audio/x-midi', 'midi' => 'audio/x-midi', 'ogg' => 'application/ogg', 'ra' => 'audio/x-pn-realaudio', 'ram' => 'audio/x-pn-realaudio', 'wav' => 'audio/x-wav', 'wma' => 'audio/x-ms-wma', 'swf' => 'application/x-shockwave-flash', 'swfl' => 'application/x-shockwave-flash', 'js' => 'application/javascript', 'bmp' => 'image/bmp', 'gif' => 'image/gif', 'ico' => 'image/vnd.microsoft.icon', 'jpeg' => 'image/jpeg', 'jpg' => 'image/jpeg', 'jpe' => 'image/jpeg', 'png' => 'image/png', 'svg' => 'image/svg+xml', 'tiff' => 'image/tiff', 'tif' => 'image/tiff', 'webp' => 'image/webp', 'xbm' => 'image/x-xbitmap', 'css' => 'text/css', 'csv' => 'text/csv', 'html' => 'text/html', 'htm' => 'text/html', 'txt' => 'text/plain', 'rtf' => 'text/richtext', 'rtx' => 'text/richtext', 'mpg' => 'video/mpeg', 'mpeg' => 'video/mpeg', 'mpe' => 'video/mpeg', 'ogv' => 'video/ogg', 'viv' => 'video/vnd.vivo', 'vivo' => 'video/vnd.vivo', 'qt' => 'video/quicktime', 'mov' => 'video/quicktime', 'mp4' => 'video/mp4', 'm4v' => 'video/x-m4v', 'flv' => 'video/x-flv', 'avi' => 'video/x-msvideo', 'wmv' => 'video/x-ms-wmv' ]; /** * Directory scanning * * Returns a directory child files and directories. * * @param string $d Path to scan * @param boolean $order Order results * @return array */ public static function scandir($d, $order = true) { $res = []; $dh = @opendir($d); if ($dh === false) { throw new Exception(__('Unable to open directory.')); } while (($f = readdir($dh)) !== false) { $res[] = $f; } closedir($dh); if ($order) { sort($res); } return $res; } /** * File extension * * Returns a file extension. * * @param string $f File name * @return string */ public static function getExtension($f) { if (function_exists('pathinfo')) { return strtolower(pathinfo($f, PATHINFO_EXTENSION)); } else { $f = explode('.', basename($f)); if (count($f) <= 1) {return '';} return strtolower($f[count($f) - 1]); } } /** * MIME type * * Returns a file MIME type, based on static var {@link $mimeType} * * @param string $f File name * @return string */ public static function getMimeType($f) { $ext = self::getExtension($f); $types = self::mimeTypes(); if (isset($types[$ext])) { return $types[$ext]; } else { return 'application/octet-stream'; } } /** * MIME types * * Returns all defined MIME types. * * @return array */ public static function mimeTypes() { return self::$mimeType; } /** * New MIME types * * Append new MIME types to defined MIME types. * * @param array $tab New MIME types. */ public static function registerMimeTypes($tab) { self::$mimeType = array_merge(self::$mimeType, $tab); } /** * Is a file or directory deletable. * * Returns true if $f is a file or directory and is deletable. * * @param string $f File or directory * @return boolean */ public static function isDeletable($f) { if (is_file($f)) { return is_writable(dirname($f)); } elseif (is_dir($f)) { return (is_writable(dirname($f)) && count(files::scandir($f)) <= 2); } return false; } /** * Recursive removal * * Remove recursively a directory. * * @param string $dir Directory patch * @return boolean */ public static function deltree($dir) { $current_dir = opendir($dir); while ($entryname = readdir($current_dir)) { if (is_dir($dir . '/' . $entryname) and ($entryname != '.' and $entryname != '..')) { if (!files::deltree($dir . '/' . $entryname)) { return false; } } elseif ($entryname != '.' and $entryname != '..') { if (!@unlink($dir . '/' . $entryname)) { return false; } } } closedir($current_dir); return @rmdir($dir); } /** * Touch file * * Set file modification time to now. * * @param string $f File to change */ public static function touch($f) { if (is_writable($f)) { if (function_exists('touch')) { @touch($f); } else { # Very bad hack @file_put_contents($f, file_get_contents($f)); } } } /** * Directory creation. * * Creates directory $f. If $r is true, attempts to create needed parents * directories. * * @param string $f Directory to create * @param boolean $r Create parent directories */ public static function makeDir($f, $r = false) { if (empty($f)) { return; } if (DIRECTORY_SEPARATOR == '\\') { $f = str_replace('/', '\\', $f); } if (is_dir($f)) { return; } if ($r) { $dir = path::real($f, false); $dirs = []; while (!is_dir($dir)) { array_unshift($dirs, basename($dir)); $dir = dirname($dir); } foreach ($dirs as $d) { $dir .= DIRECTORY_SEPARATOR . $d; if ($d != '' && !is_dir($dir)) { self::makeDir($dir); } } } else { if (@mkdir($f) === false) { throw new Exception(__('Unable to create directory.')); } self::inheritChmod($f); } } /** * Mode inheritage * * Sets file or directory mode according to its parent. * * @param string $file File to change */ public static function inheritChmod($file) { if (!function_exists('fileperms') || !function_exists('chmod')) { return false; } if (self::$dir_mode != null) { return @chmod($file, self::$dir_mode); } else { return @chmod($file, fileperms(dirname($file))); } } /** * Changes file content. * * Writes $f_content into $f file. * * @param string $f File to edit * @param string $f_content Content to write */ public static function putContent($f, $f_content) { if (file_exists($f) && !is_writable($f)) { throw new Exception(__('File is not writable.')); } $fp = @fopen($f, 'w'); if ($fp === false) { throw new Exception(__('Unable to open file.')); } fwrite($fp, $f_content, strlen($f_content)); fclose($fp); return true; } /** * Human readable file size. * * @param integer $size Bytes * @return string */ public static function size($size) { $kb = 1024; $mb = 1024 * $kb; $gb = 1024 * $mb; $tb = 1024 * $gb; if ($size < $kb) { return $size . " B"; } else if ($size < $mb) { return round($size / $kb, 2) . " KB"; } else if ($size < $gb) { return round($size / $mb, 2) . " MB"; } else if ($size < $tb) { return round($size / $gb, 2) . " GB"; } else { return round($size / $tb, 2) . " TB"; } } /** * Converts a human readable file size to bytes. * * @param string $v Size * @return integer */ public static function str2bytes($v) { $v = trim($v); $last = strtolower(substr($v, -1, 1)); $v = (float) substr($v, 0, -1); switch ($last) { case 'g': $v *= 1024; case 'm': $v *= 1024; case 'k': $v *= 1024; } return $v; } /** * Upload status * * Returns true if upload status is ok, throws an exception instead. * * @param array $file File array as found in $_FILES * @return boolean */ public static function uploadStatus($file) { if (!isset($file['error'])) { throw new Exception(__('Not an uploaded file.')); } switch ($file['error']) { case UPLOAD_ERR_OK: return true; case UPLOAD_ERR_INI_SIZE: case UPLOAD_ERR_FORM_SIZE: throw new Exception(__('The uploaded file exceeds the maximum file size allowed.')); return false; case UPLOAD_ERR_PARTIAL: throw new Exception(__('The uploaded file was only partially uploaded.')); return false; case UPLOAD_ERR_NO_FILE: throw new Exception(__('No file was uploaded.')); return false; case UPLOAD_ERR_NO_TMP_DIR: throw new Exception(__('Missing a temporary folder.')); return false; case UPLOAD_ERR_CANT_WRITE: throw new Exception(__('Failed to write file to disk.')); return false; case UPLOAD_ERR_EXTENSION: throw new Exception(__('A PHP extension stopped the file upload.')); return false; default: return true; } } # Packages generation methods # /** * Recursive directory scanning * * Returns an array of a given directory's content. The array contains * two arrays: dirs and files. Directory's content is fetched recursively. * * @param string $dirName Directory name * @param array $contents Contents array. Leave it empty * @return array */ public static function getDirList($dirName, &$contents = null) { if (!$contents) { $contents = ['dirs' => [], 'files' => []]; } $exclude_list = ['.', '..', '.svn']; $dirName = preg_replace('|/$|', '', $dirName); if (!is_dir($dirName)) { throw new Exception(sprintf(__('%s is not a directory.'), $dirName)); } $contents['dirs'][] = $dirName; $d = @dir($dirName); if ($d === false) { throw new Exception(__('Unable to open directory.')); } while ($entry = $d->read()) { if (!in_array($entry, $exclude_list)) { if (is_dir($dirName . '/' . $entry)) { files::getDirList($dirName . '/' . $entry, $contents); } else { $contents['files'][] = $dirName . '/' . $entry; } } } $d->close(); return $contents; } /** * Filename cleanup * * Removes unwanted characters in a filename. * * @param string $n Filename * @return string */ public static function tidyFileName($n) { $n = text::deaccent($n); $n = preg_replace('/^[.]/u', '', $n); return preg_replace('/[^A-Za-z0-9._-]/u', '_', $n); } } /** * @class path * @brief Path manipulation utilities * * @package Clearbricks * @subpackage Common */ class path { /** * Returns the real path of a file. * * If parameter $strict is true, file should exist. Returns false if * file does not exist. * * @param string $p Filename * @param boolean $strict File should exists * @return string */ public static function real($p, $strict = true) { $os = (DIRECTORY_SEPARATOR == '\\') ? 'win' : 'nix'; # Absolute path? if ($os == 'win') { $_abs = preg_match('/^\w+:/', $p); } else { $_abs = substr($p, 0, 1) == '/'; } # Standard path form if ($os == 'win') { $p = str_replace('\\', '/', $p); } # Adding root if !$_abs if (!$_abs) { $p = dirname($_SERVER['SCRIPT_FILENAME']) . '/' . $p; } # Clean up $p = preg_replace('|/+|', '/', $p); if (strlen($p) > 1) { $p = preg_replace('|/$|', '', $p); } $_start = ''; if ($os == 'win') { list($_start, $p) = explode(':', $p); $_start .= ':/'; } else { $_start = '/'; } $p = substr($p, 1); # Go through $P = explode('/', $p); $res = []; for ($i = 0; $i < count($P); $i++) { if ($P[$i] == '.') { continue; } if ($P[$i] == '..') { if (count($res) > 0) { array_pop($res); } } else { array_push($res, $P[$i]); } } $p = $_start . implode('/', $res); if ($strict && !@file_exists($p)) { return false; } return $p; } /** * Returns a clean file path * * @param string $p File path * @return string */ public static function clean($p) { $p = str_replace('..', '', $p); $p = preg_replace('|/{2,}|', '/', $p); $p = preg_replace('|/$|', '', $p); return $p; } /** * Path information * * Returns an array of information: * - dirname * - basename * - extension * - base (basename without extension) * * @param string $f File path */ public static function info($f) { $p = pathinfo($f); $res = []; $res['dirname'] = $p['dirname']; $res['basename'] = $p['basename']; $res['extension'] = isset($p['extension']) ? $p['extension'] : ''; $res['base'] = preg_replace('/\.' . preg_quote($res['extension'], '/') . '$/', '', $res['basename']); return $res; } /** * Full path with root * * Returns a path with root concatenation unless path begins with a slash * * @param string $p File path * @param string $root Root path * @return string */ public static function fullFromRoot($p, $root) { if (substr($p, 0, 1) == '/') { return $p; } return $root . '/' . $p; } }