Current oav website
This commit is contained in:
640
dotclear._no/inc/libs/clearbricks/common/lib.files.php
Normal file
640
dotclear._no/inc/libs/clearbricks/common/lib.files.php
Normal file
@ -0,0 +1,640 @@
|
||||
<?php
|
||||
/**
|
||||
* @class files
|
||||
* @brief Files manipulation utilities
|
||||
*
|
||||
* @package Clearbricks
|
||||
* @subpackage Common
|
||||
*
|
||||
* @copyright Olivier Meunier & Association Dotclear
|
||||
* @copyright GPL-2.0-only
|
||||
*/
|
||||
|
||||
class files
|
||||
{
|
||||
public static $dir_mode = null; ///< Default directories mode
|
||||
|
||||
public static $mimeType = ///< MIME types
|
||||
[
|
||||
'odt' => '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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user