added elfinder module
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
order deny,allow
|
||||
deny from all
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
define('ELFINDER_PHP_ROOT_PATH', dirname(__FILE__));
|
||||
|
||||
function elFinderAutoloader($name) {
|
||||
$map = array(
|
||||
'elFinder' => 'elFinder.class.php',
|
||||
'elFinderConnector' => 'elFinderConnector.class.php',
|
||||
'elFinderEditor' => 'editors/editor.php',
|
||||
'elFinderLibGdBmp' => 'libs/GdBmp.php',
|
||||
'elFinderPlugin' => 'elFinderPlugin.php',
|
||||
'elFinderPluginAutoResize' => 'plugins/AutoResize/plugin.php',
|
||||
'elFinderPluginAutoRotate' => 'plugins/AutoRotate/plugin.php',
|
||||
'elFinderPluginNormalizer' => 'plugins/Normalizer/plugin.php',
|
||||
'elFinderPluginSanitizer' => 'plugins/Sanitizer/plugin.php',
|
||||
'elFinderPluginWatermark' => 'plugins/Watermark/plugin.php',
|
||||
'elFinderSession' => 'elFinderSession.php',
|
||||
'elFinderSessionInterface' => 'elFinderSessionInterface.php',
|
||||
'elFinderVolumeDriver' => 'elFinderVolumeDriver.class.php',
|
||||
'elFinderVolumeDropbox2' => 'elFinderVolumeDropbox2.class.php',
|
||||
'elFinderVolumeFTP' => 'elFinderVolumeFTP.class.php',
|
||||
'elFinderVolumeFlysystemGoogleDriveCache' => 'elFinderFlysystemGoogleDriveNetmount.php',
|
||||
'elFinderVolumeFlysystemGoogleDriveNetmount' => 'elFinderFlysystemGoogleDriveNetmount.php',
|
||||
'elFinderVolumeGoogleDrive' => 'elFinderVolumeGoogleDrive.class.php',
|
||||
'elFinderVolumeGroup' => 'elFinderVolumeGroup.class.php',
|
||||
'elFinderVolumeLocalFileSystem' => 'elFinderVolumeLocalFileSystem.class.php',
|
||||
'elFinderVolumeMySQL' => 'elFinderVolumeMySQL.class.php',
|
||||
'elFinderVolumeTrash' => 'elFinderVolumeTrash.class.php',
|
||||
);
|
||||
if (isset($map[$name])) {
|
||||
return include_once(ELFINDER_PHP_ROOT_PATH . '/' . $map[$name]);
|
||||
}
|
||||
$prefix = substr($name, 0, 14);
|
||||
if (substr($prefix, 0, 8) === 'elFinder') {
|
||||
if ($prefix === 'elFinderVolume') {
|
||||
$file = ELFINDER_PHP_ROOT_PATH . '/' . $name . '.class.php';
|
||||
return (is_file($file) && include_once($file));
|
||||
} else if ($prefix === 'elFinderPlugin') {
|
||||
$file = ELFINDER_PHP_ROOT_PATH . '/plugins/' . substr($name, 14) . '/plugin.php';
|
||||
return (is_file($file) && include_once($file));
|
||||
} else if ($prefix === 'elFinderEditor') {
|
||||
$file = ELFINDER_PHP_ROOT_PATH . '/editors/' . substr($name, 14) . '/editor.php';
|
||||
return (is_file($file) && include_once($file));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (version_compare(PHP_VERSION, '5.3', '<')) {
|
||||
spl_autoload_register('elFinderAutoloader');
|
||||
} else {
|
||||
spl_autoload_register('elFinderAutoloader', true, true);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
<?php
|
||||
|
||||
error_reporting(0); // Set E_ALL for debuging
|
||||
|
||||
// // To Enable(true) handling of PostScript files by ImageMagick
|
||||
// // It is disabled by default as a countermeasure
|
||||
// // of Ghostscript multiple -dSAFER sandbox bypass vulnerabilities
|
||||
// // see https://www.kb.cert.org/vuls/id/332928
|
||||
// define('ELFINDER_IMAGEMAGICK_PS', true);
|
||||
// ===============================================
|
||||
|
||||
// load composer autoload before load elFinder autoload If you need composer
|
||||
//require './vendor/autoload.php';
|
||||
|
||||
// elFinder autoload
|
||||
require './autoload.php';
|
||||
// ===============================================
|
||||
|
||||
// Enable FTP connector netmount
|
||||
elFinder::$netDrivers['ftp'] = 'FTP';
|
||||
// ===============================================
|
||||
|
||||
// // Required for Dropbox network mount
|
||||
// // Installation by composer
|
||||
// // `composer require kunalvarma05/dropbox-php-sdk`
|
||||
// // Enable network mount
|
||||
// elFinder::$netDrivers['dropbox2'] = 'Dropbox2';
|
||||
// // Dropbox2 Netmount driver need next two settings. You can get at https://www.dropbox.com/developers/apps
|
||||
// // AND reuire regist redirect url to "YOUR_CONNECTOR_URL?cmd=netmount&protocol=dropbox2&host=1"
|
||||
// define('ELFINDER_DROPBOX_APPKEY', '');
|
||||
// define('ELFINDER_DROPBOX_APPSECRET', '');
|
||||
// ===============================================
|
||||
|
||||
// // Required for Google Drive network mount
|
||||
// // Installation by composer
|
||||
// // `composer require google/apiclient:^2.0`
|
||||
// // Enable network mount
|
||||
// elFinder::$netDrivers['googledrive'] = 'GoogleDrive';
|
||||
// // GoogleDrive Netmount driver need next two settings. You can get at https://console.developers.google.com
|
||||
// // AND reuire regist redirect url to "YOUR_CONNECTOR_URL?cmd=netmount&protocol=googledrive&host=1"
|
||||
// define('ELFINDER_GOOGLEDRIVE_CLIENTID', '');
|
||||
// define('ELFINDER_GOOGLEDRIVE_CLIENTSECRET', '');
|
||||
// // Required case of without composer
|
||||
// define('ELFINDER_GOOGLEDRIVE_GOOGLEAPICLIENT', '/path/to/google-api-php-client/vendor/autoload.php');
|
||||
// ===============================================
|
||||
|
||||
// // Required for Google Drive network mount with Flysystem
|
||||
// // Installation by composer
|
||||
// // `composer require nao-pon/flysystem-google-drive:~1.1 nao-pon/elfinder-flysystem-driver-ext`
|
||||
// // Enable network mount
|
||||
// elFinder::$netDrivers['googledrive'] = 'FlysystemGoogleDriveNetmount';
|
||||
// // GoogleDrive Netmount driver need next two settings. You can get at https://console.developers.google.com
|
||||
// // AND reuire regist redirect url to "YOUR_CONNECTOR_URL?cmd=netmount&protocol=googledrive&host=1"
|
||||
// define('ELFINDER_GOOGLEDRIVE_CLIENTID', '');
|
||||
// define('ELFINDER_GOOGLEDRIVE_CLIENTSECRET', '');
|
||||
// ===============================================
|
||||
|
||||
// // Required for One Drive network mount
|
||||
// // * cURL PHP extension required
|
||||
// // * HTTP server PATH_INFO supports required
|
||||
// // Enable network mount
|
||||
// elFinder::$netDrivers['onedrive'] = 'OneDrive';
|
||||
// // GoogleDrive Netmount driver need next two settings. You can get at https://dev.onedrive.com
|
||||
// // AND reuire regist redirect url to "YOUR_CONNECTOR_URL/netmount/onedrive/1"
|
||||
// define('ELFINDER_ONEDRIVE_CLIENTID', '');
|
||||
// define('ELFINDER_ONEDRIVE_CLIENTSECRET', '');
|
||||
// ===============================================
|
||||
|
||||
// // Required for Box network mount
|
||||
// // * cURL PHP extension required
|
||||
// // Enable network mount
|
||||
// elFinder::$netDrivers['box'] = 'Box';
|
||||
// // Box Netmount driver need next two settings. You can get at https://developer.box.com
|
||||
// // AND reuire regist redirect url to "YOUR_CONNECTOR_URL"
|
||||
// define('ELFINDER_BOX_CLIENTID', '');
|
||||
// define('ELFINDER_BOX_CLIENTSECRET', '');
|
||||
// ===============================================
|
||||
|
||||
|
||||
// // Zoho Office Editor APIKey
|
||||
// // https://www.zoho.com/docs/help/office-apis.html
|
||||
// define('ELFINDER_ZOHO_OFFICE_APIKEY', '');
|
||||
// ===============================================
|
||||
|
||||
// // Online converter (online-convert.com) APIKey
|
||||
// // https://apiv2.online-convert.com/docs/getting_started/api_key.html
|
||||
// define('ELFINDER_ONLINE_CONVERT_APIKEY', '');
|
||||
// ===============================================
|
||||
|
||||
// // Zip Archive editor
|
||||
// // Installation by composer
|
||||
// // `composer require nao-pon/elfinder-flysystem-ziparchive-netmount`
|
||||
// define('ELFINDER_DISABLE_ZIPEDITOR', false); // set `true` to disable zip editor
|
||||
// ===============================================
|
||||
|
||||
/**
|
||||
* Simple function to demonstrate how to control file access using "accessControl" callback.
|
||||
* This method will disable accessing files/folders starting from '.' (dot)
|
||||
*
|
||||
* @param string $attr attribute name (read|write|locked|hidden)
|
||||
* @param string $path absolute file path
|
||||
* @param string $data value of volume option `accessControlData`
|
||||
* @param object $volume elFinder volume driver object
|
||||
* @param bool|null $isDir path is directory (true: directory, false: file, null: unknown)
|
||||
* @param string $relpath file path relative to volume root directory started with directory separator
|
||||
* @return bool|null
|
||||
**/
|
||||
function access($attr, $path, $data, $volume, $isDir, $relpath) {
|
||||
$basename = basename($path);
|
||||
return $basename[0] === '.' // if file/folder begins with '.' (dot)
|
||||
&& strlen($relpath) !== 1 // but with out volume root
|
||||
? !($attr == 'read' || $attr == 'write') // set read+write to false, other (locked+hidden) set to true
|
||||
: null; // else elFinder decide it itself
|
||||
}
|
||||
|
||||
|
||||
// Documentation for connector options:
|
||||
// https://github.com/Studio-42/elFinder/wiki/Connector-configuration-options
|
||||
$opts = array(
|
||||
// 'debug' => true,
|
||||
'roots' => array(
|
||||
// Items volume
|
||||
array(
|
||||
'driver' => 'LocalFileSystem', // driver for accessing file system (REQUIRED)
|
||||
'path' => '../files/', // path to files (REQUIRED)
|
||||
'URL' => dirname($_SERVER['PHP_SELF']) . '/../files/', // URL to files (REQUIRED)
|
||||
'trashHash' => 't1_Lw', // elFinder's hash of trash folder
|
||||
'winHashFix' => DIRECTORY_SEPARATOR !== '/', // to make hash same to Linux one on windows too
|
||||
'uploadDeny' => array('all'), // All Mimetypes not allowed to upload
|
||||
'uploadAllow' => array('image/x-ms-bmp', 'image/gif', 'image/jpeg', 'image/png', 'image/x-icon', 'text/plain'), // Mimetype `image` and `text/plain` allowed to upload
|
||||
'uploadOrder' => array('deny', 'allow'), // allowed Mimetype `image` and `text/plain` only
|
||||
'accessControl' => 'access' // disable and hide dot starting files (OPTIONAL)
|
||||
),
|
||||
// Trash volume
|
||||
array(
|
||||
'id' => '1',
|
||||
'driver' => 'Trash',
|
||||
'path' => '../files/.trash/',
|
||||
'tmbURL' => dirname($_SERVER['PHP_SELF']) . '/../files/.trash/.tmb/',
|
||||
'winHashFix' => DIRECTORY_SEPARATOR !== '/', // to make hash same to Linux one on windows too
|
||||
'uploadDeny' => array('all'), // Recomend the same settings as the original volume that uses the trash
|
||||
'uploadAllow' => array('image/x-ms-bmp', 'image/gif', 'image/jpeg', 'image/png', 'image/x-icon', 'text/plain'), // Same as above
|
||||
'uploadOrder' => array('deny', 'allow'), // Same as above
|
||||
'accessControl' => 'access', // Same as above
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
// run elFinder
|
||||
$connector = new elFinderConnector(new elFinder($opts));
|
||||
$connector->run();
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
<?php
|
||||
|
||||
class elFinderEditorOnlineConvert extends elFinderEditor
|
||||
{
|
||||
protected $allowed = array('init', 'api');
|
||||
|
||||
public function enabled()
|
||||
{
|
||||
return !defined('ELFINDER_DISABLE_ONLINE_CONVERT') || !ELFINDER_DISABLE_ONLINE_CONVERT;
|
||||
}
|
||||
|
||||
public function init()
|
||||
{
|
||||
return array('api' => defined('ELFINDER_ONLINE_CONVERT_APIKEY') && ELFINDER_ONLINE_CONVERT_APIKEY && function_exists('curl_init'));
|
||||
}
|
||||
|
||||
public function api()
|
||||
{
|
||||
// return array('apires' => array('message' => 'Currently disabled for developping...'));
|
||||
$endpoint = 'https://api2.online-convert.com/jobs';
|
||||
$category = $this->argValue('category');
|
||||
$convert = $this->argValue('convert');
|
||||
$options = $this->argValue('options');
|
||||
$source = $this->argValue('source');
|
||||
$filename = $this->argValue('filename');
|
||||
$mime = $this->argValue('mime');
|
||||
$jobid = $this->argValue('jobid');
|
||||
$string_method = '';
|
||||
$options = array();
|
||||
// Currently these converts are make error with API call. I don't know why.
|
||||
$nonApi = array('android','blackberry','dpg','ipad','iphone','ipod','nintendo-3ds','nintendo-ds','ps3','psp','wii','xbox');
|
||||
if (in_array($convert, $nonApi)) {
|
||||
return array('apires' => array());
|
||||
}
|
||||
$ch = null;
|
||||
if ($convert && $source) {
|
||||
$request = array(
|
||||
'input' => array(array(
|
||||
'type' => 'remote',
|
||||
'source' => $source
|
||||
)),
|
||||
'conversion' => array(array(
|
||||
'target' => $convert
|
||||
))
|
||||
);
|
||||
|
||||
if ($filename !== '') {
|
||||
$request['input'][0]['filename'] = $filename;
|
||||
}
|
||||
|
||||
if ($mime !== '') {
|
||||
$request['input'][0]['content_type'] = $mime;
|
||||
}
|
||||
|
||||
if ($category) {
|
||||
$request['conversion'][0]['category'] = $category;
|
||||
}
|
||||
|
||||
if ($options && $options !== 'null') {
|
||||
$options = json_decode($options, true);
|
||||
}
|
||||
if (!is_array($options)) {
|
||||
$options = array();
|
||||
}
|
||||
if ($options) {
|
||||
$request['conversion'][0]['options'] = $options;
|
||||
}
|
||||
|
||||
$ch = curl_init($endpoint);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($request));
|
||||
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
|
||||
'X-Oc-Api-Key: ' . ELFINDER_ONLINE_CONVERT_APIKEY,
|
||||
'Content-Type: application/json',
|
||||
'cache-control: no-cache'
|
||||
));
|
||||
} else if ($jobid) {
|
||||
$ch = curl_init($endpoint . '/' . $jobid);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
|
||||
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
|
||||
'X-Oc-Api-Key: ' . ELFINDER_ONLINE_CONVERT_APIKEY,
|
||||
'cache-control: no-cache'
|
||||
));
|
||||
}
|
||||
|
||||
if ($ch) {
|
||||
$response = curl_exec($ch);
|
||||
$info = curl_getinfo($ch);
|
||||
$error = curl_error($ch);
|
||||
curl_close($ch);
|
||||
|
||||
if (! empty($error)) {
|
||||
$res = array('error' => $error);
|
||||
} else {
|
||||
$data = json_decode($response, true);
|
||||
if (isset($data['status']) && isset($data['status']['code']) && $data['status']['code'] === 'completed') {
|
||||
$session = $this->elfinder->getSession();
|
||||
$urlContentSaveIds = $session->get('urlContentSaveIds', array());
|
||||
$urlContentSaveIds['OnlineConvert-'.$data['id']] = true;
|
||||
$session->set('urlContentSaveIds', $urlContentSaveIds);
|
||||
}
|
||||
$res = array('apires' => $data);
|
||||
}
|
||||
|
||||
return $res;
|
||||
} else {
|
||||
return array('error' => array('errCmdParams', 'editor.OnlineConvert.api'));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
class elFinderEditorZipArchive extends elFinderEditor
|
||||
{
|
||||
public function enabled()
|
||||
{
|
||||
return (!defined('ELFINDER_DISABLE_ZIPEDITOR') || !ELFINDER_DISABLE_ZIPEDITOR) &&
|
||||
class_exists('Barryvdh\elFinderFlysystemDriver\Driver') &&
|
||||
class_exists('League\Flysystem\Filesystem') &&
|
||||
class_exists('League\Flysystem\ZipArchive\ZipArchiveAdapter');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
<?php
|
||||
|
||||
class elFinderEditorZohoOffice extends elFinderEditor
|
||||
{
|
||||
private static $curlTimeout = 20;
|
||||
|
||||
protected $allowed = array('init', 'save');
|
||||
|
||||
private $urls = array(
|
||||
'writer' => 'https://writer.zoho.com/writer/remotedoc.im',
|
||||
'sheet' => 'https://sheet.zoho.com/sheet/remotedoc.im',
|
||||
'show' => 'https://show.zoho.com/show/remotedoc.im',
|
||||
);
|
||||
|
||||
private $srvs = array(
|
||||
'application/msword' => 'writer',
|
||||
'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => 'writer',
|
||||
'application/pdf' => 'writer',
|
||||
'application/vnd.oasis.opendocument.text' => 'writer',
|
||||
'application/rtf' => 'writer',
|
||||
'text/html' => 'writer',
|
||||
'application/vnd.ms-excel' => 'sheet',
|
||||
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => 'sheet',
|
||||
'application/vnd.oasis.opendocument.spreadsheet' => 'sheet',
|
||||
'application/vnd.sun.xml.calc' => 'sheet',
|
||||
'text/csv' => 'sheet',
|
||||
'text/tab-separated-values' => 'sheet',
|
||||
'application/vnd.ms-powerpoint' => 'show',
|
||||
'application/vnd.openxmlformats-officedocument.presentationml.presentation' => 'show',
|
||||
'application/vnd.openxmlformats-officedocument.presentationml.slideshow' => 'show',
|
||||
'application/vnd.oasis.opendocument.presentation' => 'show',
|
||||
'application/vnd.sun.xml.impress' => 'show',
|
||||
);
|
||||
|
||||
public function enabled()
|
||||
{
|
||||
return defined('ELFINDER_ZOHO_OFFICE_APIKEY') && ELFINDER_ZOHO_OFFICE_APIKEY && function_exists('curl_init');
|
||||
}
|
||||
|
||||
public function init()
|
||||
{
|
||||
if (!defined('ELFINDER_ZOHO_OFFICE_APIKEY') || !function_exists('curl_init')) {
|
||||
return array('error', array(elFinder::ERROR_CONF, '`ELFINDER_ZOHO_OFFICE_APIKEY` or curl extension'));
|
||||
}
|
||||
if (!empty($this->args['target'])) {
|
||||
$fp = $cfile = null;
|
||||
$hash = $this->args['target'];
|
||||
if (($srcVol = $this->elfinder->getVolume($hash)) && ($file = $srcVol->file($hash))) {
|
||||
if ($size = $file['size']) {
|
||||
$src = $srcVol->open($hash);
|
||||
$fp = tmpfile();
|
||||
stream_copy_to_stream($src, $fp);
|
||||
$srcVol->close($src, $hash);
|
||||
$info = stream_get_meta_data($fp);
|
||||
if ($info && !empty($info['uri'])) {
|
||||
$srcFile = $info['uri'];
|
||||
if (class_exists('CURLFile')) {
|
||||
$cfile = new CURLFile($srcFile);
|
||||
$cfile->setPostFilename($file['name']);
|
||||
$cfile->setMimeType($file['mime']);
|
||||
} else {
|
||||
$cfile = '@'.$srcFile;
|
||||
}
|
||||
}
|
||||
}
|
||||
//$srv = $this->args['service'];
|
||||
$format = $srcVol->getExtentionByMime($file['mime']);
|
||||
if (!$format) {
|
||||
$format = substr($file['name'], strrpos($file['name'], '.') * -1);
|
||||
}
|
||||
$cdata = empty($this->args['cdata']) ? '' : $this->args['cdata'];
|
||||
$lang = $this->args['lang'];
|
||||
if ($lang === 'jp') {
|
||||
$lang = 'ja';
|
||||
}
|
||||
$srvsName = $this->srvs[$file['mime']];
|
||||
$data = array(
|
||||
'apikey' => ELFINDER_ZOHO_OFFICE_APIKEY,
|
||||
'output' => 'url',
|
||||
'mode' => 'normaledit',
|
||||
'filename' => $file['name'],
|
||||
'id' => $hash,
|
||||
'format' => $format,
|
||||
'lang' => $lang,
|
||||
'saveurl' => elFinder::getConnectorUrl().'?cmd=editor&name=ZohoOffice&method=save'.$cdata,
|
||||
);
|
||||
if ($cfile) {
|
||||
$data['content'] = $cfile;
|
||||
}
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $this->urls[$srvsName]);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, self::$curlTimeout);
|
||||
curl_setopt($ch, CURLOPT_HEADER, 0);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($ch, CURLOPT_POST, 1);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
|
||||
$res = curl_exec($ch);
|
||||
$error = curl_error($ch);
|
||||
curl_close($ch);
|
||||
|
||||
$fp && fclose($fp);
|
||||
|
||||
if ($res) {
|
||||
if (strpos($res, 'RESULT=TRUE') !== false) {
|
||||
list(, $url) = explode('URL=', $res);
|
||||
preg_match('/URL=([^\s]+)/', $res, $m);
|
||||
|
||||
return array('zohourl' => $m[1]);
|
||||
} else {
|
||||
$error = $res;
|
||||
}
|
||||
}
|
||||
|
||||
if ($error) {
|
||||
return array('error' => preg_split('/[\r\n]+/', $error));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return array('error' => array('errCmdParams', 'editor.ZohoOffice.init'));
|
||||
}
|
||||
|
||||
public function save()
|
||||
{
|
||||
if (isset($_POST) && ! empty($_POST['id'])) {
|
||||
$hash = $_POST['id'];
|
||||
if ($volume = $this->elfinder->getVolume($hash)) {
|
||||
$content = file_get_contents($_FILES['content']['tmp_name']);
|
||||
if ($volume->putContents($hash, $content)) {
|
||||
return array('raw' => true, 'error' => '', 'header' => 'HTTP/1.1 200 OK');
|
||||
}
|
||||
}
|
||||
}
|
||||
return array('raw' => true, 'error' => '', 'header' => 'HTTP/1.1 500 Internal Server Error');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
/**
|
||||
* Abstract class of editor plugins.
|
||||
*
|
||||
* @author Naoki Sawada
|
||||
*/
|
||||
class elFinderEditor
|
||||
{
|
||||
/**
|
||||
* Array of allowed method by request from client side.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $allowed = array();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param object $elfinder
|
||||
* @param array $args
|
||||
*/
|
||||
public function __construct($elfinder, $args)
|
||||
{
|
||||
$this->elfinder = $elfinder;
|
||||
$this->args = $args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return boolean that this plugin is enabled.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function enabled()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return boolean that $name method is allowed.
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isAllowedMethod($name)
|
||||
{
|
||||
$checker = array_flip($this->allowed);
|
||||
|
||||
return isset($checker[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return $this->args value of the key
|
||||
*
|
||||
* @param string $key target key
|
||||
* @param string $empty empty value
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function argValue($key, $empty = '')
|
||||
{
|
||||
return isset($this->args[$key])? $this->args[$key] : $empty;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,355 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Default elFinder connector
|
||||
*
|
||||
* @author Dmitry (dio) Levashov
|
||||
**/
|
||||
class elFinderConnector {
|
||||
/**
|
||||
* elFinder instance
|
||||
*
|
||||
* @var elFinder
|
||||
**/
|
||||
protected $elFinder;
|
||||
|
||||
/**
|
||||
* Options
|
||||
*
|
||||
* @var aray
|
||||
**/
|
||||
protected $options = array();
|
||||
|
||||
/**
|
||||
* Must be use output($data) $data['header']
|
||||
*
|
||||
* @var string
|
||||
* @deprecated
|
||||
**/
|
||||
protected $header = '';
|
||||
|
||||
/**
|
||||
* HTTP request method
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $reqMethod = '';
|
||||
|
||||
/**
|
||||
* Content type of output JSON
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected static $contentType = 'Content-Type: application/json; charset=utf-8';
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param $elFinder
|
||||
* @param bool $debug
|
||||
* @author Dmitry (dio) Levashov
|
||||
*/
|
||||
public function __construct($elFinder, $debug=false) {
|
||||
|
||||
$this->elFinder = $elFinder;
|
||||
$this->reqMethod = strtoupper($_SERVER["REQUEST_METHOD"]);
|
||||
if ($debug) {
|
||||
self::$contentType = 'Content-Type: text/plain; charset=utf-8';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute elFinder command and output result
|
||||
*
|
||||
* @return void
|
||||
* @author Dmitry (dio) Levashov
|
||||
**/
|
||||
public function run() {
|
||||
$isPost = $this->reqMethod === 'POST';
|
||||
$src = $isPost ? array_merge($_GET, $_POST) : $_GET;
|
||||
$maxInputVars = (! $src || isset($src['targets']))? ini_get('max_input_vars') : null;
|
||||
if ((! $src || $maxInputVars) && $rawPostData = file_get_contents('php://input')) {
|
||||
// for max_input_vars and supports IE XDomainRequest()
|
||||
$parts = explode('&', $rawPostData);
|
||||
if (! $src || $maxInputVars < count($parts)) {
|
||||
$src = array();
|
||||
foreach($parts as $part) {
|
||||
list($key, $value) = array_pad(explode('=', $part), 2, '');
|
||||
$key = rawurldecode($key);
|
||||
if (preg_match('/^(.+?)\[([^\[\]]*)\]$/', $key, $m)) {
|
||||
$key = $m[1];
|
||||
$idx = $m[2];
|
||||
if (!isset($src[$key])) {
|
||||
$src[$key] = array();
|
||||
}
|
||||
if ($idx) {
|
||||
$src[$key][$idx] = rawurldecode($value);
|
||||
} else {
|
||||
$src[$key][] = rawurldecode($value);
|
||||
}
|
||||
} else {
|
||||
$src[$key] = rawurldecode($value);
|
||||
}
|
||||
}
|
||||
$_POST = $this->input_filter($src);
|
||||
$_REQUEST = $this->input_filter(array_merge_recursive($src, $_REQUEST));
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($src['targets']) && $this->elFinder->maxTargets && count($src['targets']) > $this->elFinder->maxTargets) {
|
||||
$error = $this->elFinder->error(elFinder::ERROR_MAX_TARGTES);
|
||||
$this->output(array('error' => $this->elFinder->error(elFinder::ERROR_MAX_TARGTES)));
|
||||
}
|
||||
|
||||
$cmd = isset($src['cmd']) ? $src['cmd'] : '';
|
||||
$args = array();
|
||||
|
||||
if (!function_exists('json_encode')) {
|
||||
$error = $this->elFinder->error(elFinder::ERROR_CONF, elFinder::ERROR_CONF_NO_JSON);
|
||||
$this->output(array('error' => '{"error":["'.implode('","', $error).'"]}', 'raw' => true));
|
||||
}
|
||||
|
||||
if (!$this->elFinder->loaded()) {
|
||||
$this->output(array('error' => $this->elFinder->error(elFinder::ERROR_CONF, elFinder::ERROR_CONF_NO_VOL), 'debug' => $this->elFinder->mountErrors));
|
||||
}
|
||||
|
||||
// telepat_mode: on
|
||||
if (!$cmd && $isPost) {
|
||||
$this->output(array('error' => $this->elFinder->error(elFinder::ERROR_UPLOAD, elFinder::ERROR_UPLOAD_TOTAL_SIZE), 'header' => 'Content-Type: text/html'));
|
||||
}
|
||||
// telepat_mode: off
|
||||
|
||||
if (!$this->elFinder->commandExists($cmd)) {
|
||||
$this->output(array('error' => $this->elFinder->error(elFinder::ERROR_UNKNOWN_CMD)));
|
||||
}
|
||||
|
||||
// collect required arguments to exec command
|
||||
$hasFiles = false;
|
||||
foreach ($this->elFinder->commandArgsList($cmd) as $name => $req) {
|
||||
if ($name === 'FILES') {
|
||||
if (isset($_FILES)) {
|
||||
$hasFiles = true;
|
||||
} elseif ($req) {
|
||||
$this->output(array('error' => $this->elFinder->error(elFinder::ERROR_INV_PARAMS, $cmd)));
|
||||
}
|
||||
} else {
|
||||
$arg = isset($src[$name])? $src[$name] : '';
|
||||
|
||||
if (!is_array($arg) && $req !== '') {
|
||||
$arg = trim($arg);
|
||||
}
|
||||
if ($req && $arg === '') {
|
||||
$this->output(array('error' => $this->elFinder->error(elFinder::ERROR_INV_PARAMS, $cmd)));
|
||||
}
|
||||
$args[$name] = $arg;
|
||||
}
|
||||
}
|
||||
|
||||
$args['debug'] = isset($src['debug']) ? !!$src['debug'] : false;
|
||||
|
||||
$args = $this->input_filter($args);
|
||||
if ($hasFiles) {
|
||||
$args['FILES'] = $_FILES;
|
||||
}
|
||||
|
||||
try {
|
||||
$this->output($this->elFinder->exec($cmd, $args));
|
||||
} catch (elFinderAbortException $e) {
|
||||
// connection aborted
|
||||
// unlock session data for multiple access
|
||||
$this->elFinder->getSession()->close();
|
||||
// HTTP response code
|
||||
header('HTTP/1.0 204 No Content');
|
||||
// clear output buffer
|
||||
while(ob_get_level() && ob_end_clean()){}
|
||||
exit();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Output json
|
||||
*
|
||||
* @param array data to output
|
||||
* @return void
|
||||
* @author Dmitry (dio) Levashov
|
||||
**/
|
||||
protected function output(array $data) {
|
||||
// unlock session data for multiple access
|
||||
$this->elFinder->getSession()->close();
|
||||
// client disconnect should abort
|
||||
ignore_user_abort(false);
|
||||
|
||||
if ($this->header) {
|
||||
self::sendHeader($this->header);
|
||||
}
|
||||
|
||||
if (isset($data['pointer'])) {
|
||||
// set time limit to 0
|
||||
elFinder::extendTimeLimit(0);
|
||||
|
||||
// send optional header
|
||||
if (!empty($data['header'])) {
|
||||
self::sendHeader($data['header']);
|
||||
}
|
||||
|
||||
// clear output buffer
|
||||
while(ob_get_level() && ob_end_clean()){}
|
||||
|
||||
$toEnd = true;
|
||||
$fp = $data['pointer'];
|
||||
$sendData = !($this->reqMethod === 'HEAD' || !empty($data['info']['xsendfile']));
|
||||
if (($this->reqMethod === 'GET' || !$sendData)
|
||||
&& elFinder::isSeekableStream($fp)
|
||||
&& (array_search('Accept-Ranges: none', headers_list()) === false)) {
|
||||
header('Accept-Ranges: bytes');
|
||||
$psize = null;
|
||||
if (!empty($_SERVER['HTTP_RANGE'])) {
|
||||
$size = $data['info']['size'];
|
||||
$start = 0;
|
||||
$end = $size - 1;
|
||||
if (preg_match('/bytes=(\d*)-(\d*)(,?)/i', $_SERVER['HTTP_RANGE'], $matches)) {
|
||||
if (empty($matches[3])) {
|
||||
if (empty($matches[1]) && $matches[1] !== '0') {
|
||||
$start = $size - $matches[2];
|
||||
} else {
|
||||
$start = intval($matches[1]);
|
||||
if (!empty($matches[2])) {
|
||||
$end = intval($matches[2]);
|
||||
if ($end >= $size) {
|
||||
$end = $size - 1;
|
||||
}
|
||||
$toEnd = ($end == ($size - 1));
|
||||
}
|
||||
}
|
||||
$psize = $end - $start + 1;
|
||||
|
||||
header('HTTP/1.1 206 Partial Content');
|
||||
header('Content-Length: ' . $psize);
|
||||
header('Content-Range: bytes ' . $start . '-' . $end . '/' . $size);
|
||||
|
||||
// Apache mod_xsendfile dose not support range request
|
||||
if (isset($data['info']['xsendfile']) && strtolower($data['info']['xsendfile']) === 'x-sendfile') {
|
||||
if (function_exists('header_remove')) {
|
||||
header_remove($data['info']['xsendfile']);
|
||||
} else {
|
||||
header($data['info']['xsendfile'] . ':');
|
||||
}
|
||||
unset($data['info']['xsendfile']);
|
||||
if ($this->reqMethod !== 'HEAD') {
|
||||
$sendData = true;
|
||||
}
|
||||
}
|
||||
|
||||
$sendData && fseek($fp, $start);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($sendData && is_null($psize)){
|
||||
elFinder::rewind($fp);
|
||||
}
|
||||
} else {
|
||||
header('Accept-Ranges: none');
|
||||
if (isset($data['info']) && ! $data['info']['size']) {
|
||||
if (function_exists('header_remove')) {
|
||||
header_remove('Content-Length');
|
||||
} else {
|
||||
header('Content-Length:');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($sendData) {
|
||||
if ($toEnd) {
|
||||
// PHP < 5.6 has a bug of fpassthru
|
||||
// see https://bugs.php.net/bug.php?id=66736
|
||||
if (version_compare(PHP_VERSION, '5.6', '<')) {
|
||||
file_put_contents('php://output', $fp);
|
||||
} else {
|
||||
fpassthru($fp);
|
||||
}
|
||||
} else {
|
||||
$out = fopen('php://output', 'wb');
|
||||
stream_copy_to_stream($fp, $out, $psize);
|
||||
fclose($out);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($data['volume'])) {
|
||||
$data['volume']->close($data['pointer'], $data['info']['hash']);
|
||||
}
|
||||
exit();
|
||||
} else {
|
||||
self::outputJson($data);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove null & stripslashes applies on "magic_quotes_gpc"
|
||||
*
|
||||
* @param mixed $args
|
||||
* @return mixed
|
||||
* @author Naoki Sawada
|
||||
*/
|
||||
protected function input_filter($args) {
|
||||
static $magic_quotes_gpc = NULL;
|
||||
|
||||
if ($magic_quotes_gpc === NULL)
|
||||
$magic_quotes_gpc = (version_compare(PHP_VERSION, '5.4', '<') && get_magic_quotes_gpc());
|
||||
|
||||
if (is_array($args)) {
|
||||
return array_map(array(& $this, 'input_filter'), $args);
|
||||
}
|
||||
$res = str_replace("\0", '', $args);
|
||||
$magic_quotes_gpc && ($res = stripslashes($res));
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send HTTP header
|
||||
*
|
||||
* @param string|array $header optional header
|
||||
*/
|
||||
protected static function sendHeader($header = null) {
|
||||
if ($header) {
|
||||
if (is_array($header)) {
|
||||
foreach ($header as $h) {
|
||||
header($h);
|
||||
}
|
||||
} else {
|
||||
header($header);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Output JSON
|
||||
*
|
||||
* @param array $data
|
||||
*/
|
||||
public static function outputJson($data) {
|
||||
// send header
|
||||
$header = isset($data['header']) ? $data['header'] : self::$contentType;
|
||||
self::sendHeader($header);
|
||||
|
||||
unset($data['header']);
|
||||
|
||||
if (!empty($data['raw']) && isset($data['error'])) {
|
||||
$out = $data['error'];
|
||||
} else {
|
||||
if (isset($data['debug']) && isset($data['debug']['phpErrors'])) {
|
||||
$data['debug']['phpErrors'] = array_merge($data['debug']['phpErrors'], elFinder::$phpErrors);
|
||||
}
|
||||
$out = json_encode($data);
|
||||
}
|
||||
|
||||
// clear output buffer
|
||||
while(ob_get_level() && ob_end_clean()){}
|
||||
|
||||
header('Content-Length: ' . strlen($out));
|
||||
|
||||
echo $out;
|
||||
|
||||
flush();
|
||||
}
|
||||
}// END class
|
||||
@@ -0,0 +1,334 @@
|
||||
<?php
|
||||
|
||||
use League\Flysystem\Filesystem;
|
||||
use League\Flysystem\Adapter\Local;
|
||||
use League\Flysystem\Cached\CachedAdapter;
|
||||
use League\Flysystem\Cached\Storage\Adapter as ACache;
|
||||
use Hypweb\Flysystem\GoogleDrive\GoogleDriveAdapter;
|
||||
use Hypweb\Flysystem\Cached\Extra\Hasdir;
|
||||
use Hypweb\Flysystem\Cached\Extra\DisableEnsureParentDirectories;
|
||||
use Hypweb\elFinderFlysystemDriverExt\Driver as ExtDriver;
|
||||
|
||||
elFinder::$netDrivers['googledrive'] = 'FlysystemGoogleDriveNetmount';
|
||||
|
||||
if (! class_exists('elFinderVolumeFlysystemGoogleDriveCache', false)) {
|
||||
class elFinderVolumeFlysystemGoogleDriveCache extends ACache
|
||||
{
|
||||
use Hasdir;
|
||||
use DisableEnsureParentDirectories;
|
||||
}
|
||||
}
|
||||
|
||||
class elFinderVolumeFlysystemGoogleDriveNetmount extends ExtDriver
|
||||
{
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$opts = array(
|
||||
'acceptedName' => '#^[^/\\?*:|"<>]*[^./\\?*:|"<>]$#',
|
||||
'rootCssClass' => 'elfinder-navbar-root-googledrive',
|
||||
'gdAlias' => '%s@GDrive',
|
||||
'gdCacheDir' => __DIR__ . '/.tmp',
|
||||
'gdCachePrefix' => 'gd-',
|
||||
'gdCacheExpire' => 600
|
||||
);
|
||||
|
||||
$this->options = array_merge($this->options, $opts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare driver before mount volume.
|
||||
* Return true if volume is ready.
|
||||
*
|
||||
* @return bool
|
||||
**/
|
||||
protected function init()
|
||||
{
|
||||
if (empty($this->options['icon'])) {
|
||||
$this->options['icon'] = true;
|
||||
}
|
||||
if ($res = parent::init()) {
|
||||
if ($this->options['icon'] === true) {
|
||||
unset($this->options['icon']);
|
||||
}
|
||||
// enable command archive
|
||||
$this->options['useRemoteArchive'] = true;
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare
|
||||
* Call from elFinder::netmout() before volume->mount()
|
||||
*
|
||||
* @param $options
|
||||
* @return Array
|
||||
* @author Naoki Sawada
|
||||
*/
|
||||
public function netmountPrepare($options)
|
||||
{
|
||||
if (empty($options['client_id']) && defined('ELFINDER_GOOGLEDRIVE_CLIENTID')) {
|
||||
$options['client_id'] = ELFINDER_GOOGLEDRIVE_CLIENTID;
|
||||
}
|
||||
if (empty($options['client_secret']) && defined('ELFINDER_GOOGLEDRIVE_CLIENTSECRET')) {
|
||||
$options['client_secret'] = ELFINDER_GOOGLEDRIVE_CLIENTSECRET;
|
||||
}
|
||||
|
||||
if (! isset($options['pass'])) {
|
||||
$options['pass'] = '';
|
||||
}
|
||||
|
||||
try {
|
||||
$client = new \Google_Client();
|
||||
$client->setClientId($options['client_id']);
|
||||
$client->setClientSecret($options['client_secret']);
|
||||
|
||||
if ($options['pass'] === 'reauth') {
|
||||
$options['pass'] = '';
|
||||
$this->session->set('GoogleDriveAuthParams', [])->set('GoogleDriveTokens', []);
|
||||
} else if ($options['pass'] === 'googledrive') {
|
||||
$options['pass'] = '';
|
||||
}
|
||||
|
||||
$options = array_merge($this->session->get('GoogleDriveAuthParams', []), $options);
|
||||
|
||||
if (! isset($options['access_token'])) {
|
||||
$options['access_token'] = $this->session->get('GoogleDriveTokens', []);
|
||||
$this->session->remove('GoogleDriveTokens');
|
||||
}
|
||||
$aToken = $options['access_token'];
|
||||
|
||||
$rootObj = $service = null;
|
||||
if ($aToken) {
|
||||
try {
|
||||
$client->setAccessToken($aToken);
|
||||
if ($client->isAccessTokenExpired()) {
|
||||
$aToken = array_merge($aToken, $client->fetchAccessTokenWithRefreshToken());
|
||||
$client->setAccessToken($aToken);
|
||||
}
|
||||
$service = new \Google_Service_Drive($client);
|
||||
$rootObj = $service->files->get('root');
|
||||
|
||||
$options['access_token'] = $aToken;
|
||||
$this->session->set('GoogleDriveAuthParams', $options);
|
||||
|
||||
} catch (Exception $e) {
|
||||
$aToken = [];
|
||||
$options['access_token'] = [];
|
||||
if ($options['user'] !== 'init') {
|
||||
$this->session->set('GoogleDriveAuthParams', $options);
|
||||
return array('exit' => true, 'error' => elFinder::ERROR_REAUTH_REQUIRE);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ($options['user'] === 'init') {
|
||||
if (empty($options['url'])) {
|
||||
$options['url'] = elFinder::getConnectorUrl();
|
||||
}
|
||||
|
||||
$callback = $options['url']
|
||||
. '?cmd=netmount&protocol=googledrive&host=1';
|
||||
$client->setRedirectUri($callback);
|
||||
|
||||
if (! $aToken && empty($_GET['code'])) {
|
||||
$client->setScopes([ Google_Service_Drive::DRIVE ]);
|
||||
if (! empty($options['offline'])) {
|
||||
$client->setApprovalPrompt('force');
|
||||
$client->setAccessType('offline');
|
||||
}
|
||||
$url = $client->createAuthUrl();
|
||||
|
||||
$html = '<input id="elf-volumedriver-googledrive-host-btn" class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only" value="{msg:btnApprove}" type="button" onclick="window.open(\''.$url.'\')">';
|
||||
$html .= '<script>
|
||||
$("#'.$options['id'].'").elfinder("instance").trigger("netmount", {protocol: "googledrive", mode: "makebtn"});
|
||||
</script>';
|
||||
if (empty($options['pass']) && $options['host'] !== '1') {
|
||||
$options['pass'] = 'return';
|
||||
$this->session->set('GoogleDriveAuthParams', $options);
|
||||
return array('exit' => true, 'body' => $html);
|
||||
} else {
|
||||
$out = array(
|
||||
'node' => $options['id'],
|
||||
'json' => '{"protocol": "googledrive", "mode": "makebtn", "body" : "'.str_replace($html, '"', '\\"').'", "error" : "'.elFinder::ERROR_ACCESS_DENIED.'"}',
|
||||
'bind' => 'netmount'
|
||||
);
|
||||
return array('exit' => 'callback', 'out' => $out);
|
||||
}
|
||||
} else {
|
||||
if (! empty($_GET['code'])) {
|
||||
$aToken = $client->fetchAccessTokenWithAuthCode($_GET['code']);
|
||||
$options['access_token'] = $aToken;
|
||||
$this->session->set('GoogleDriveTokens', $aToken)->set('GoogleDriveAuthParams', $options);
|
||||
$out = array(
|
||||
'node' => $options['id'],
|
||||
'json' => '{"protocol": "googledrive", "mode": "done", "reset": 1}',
|
||||
'bind' => 'netmount'
|
||||
);
|
||||
return array('exit' => 'callback', 'out' => $out);
|
||||
}
|
||||
$folders = [];
|
||||
foreach($service->files->listFiles([
|
||||
'pageSize' => 1000,
|
||||
'q' => 'trashed = false and mimeType = "application/vnd.google-apps.folder"'
|
||||
]) as $f) {
|
||||
$folders[$f->getId()] = $f->getName();
|
||||
}
|
||||
natcasesort($folders);
|
||||
$folders = ['root' => $rootObj->getName()] + $folders;
|
||||
$folders = json_encode($folders);
|
||||
$json = '{"protocol": "googledrive", "mode": "done", "folders": '.$folders.'}';
|
||||
$options['pass'] = 'return';
|
||||
$html = 'Google.com';
|
||||
$html .= '<script>
|
||||
$("#'.$options['id'].'").elfinder("instance").trigger("netmount", '.$json.');
|
||||
</script>';
|
||||
$this->session->set('GoogleDriveAuthParams', $options);
|
||||
return array('exit' => true, 'body' => $html);
|
||||
}
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$this->session->remove('GoogleDriveAuthParams')->remove('GoogleDriveTokens');
|
||||
if (empty($options['pass'])) {
|
||||
return array('exit' => true, 'body' => '{msg:'.elFinder::ERROR_ACCESS_DENIED.'}'.' '.$e->getMessage());
|
||||
} else {
|
||||
return array('exit' => true, 'error' => [elFinder::ERROR_ACCESS_DENIED, $e->getMessage()]);
|
||||
}
|
||||
}
|
||||
|
||||
if (! $aToken) {
|
||||
return array('exit' => true, 'error' => elFinder::ERROR_REAUTH_REQUIRE);
|
||||
}
|
||||
|
||||
if ($options['path'] === '/') {
|
||||
$options['path'] = 'root';
|
||||
}
|
||||
|
||||
try {
|
||||
$file = $service->files->get($options['path']);
|
||||
$options['alias'] = sprintf($this->options['gdAlias'], $file->getName());
|
||||
} catch (Google_Service_Exception $e) {
|
||||
$err = json_decode($e->getMessage(), true);
|
||||
if (isset($err['error']) && $err['error']['code'] == 404) {
|
||||
return array('exit' => true, 'error' => [elFinder::ERROR_TRGDIR_NOT_FOUND, $options['path']]);
|
||||
} else {
|
||||
return array('exit' => true, 'error' => $e->getMessage());
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
return array('exit' => true, 'error' => $e->getMessage());
|
||||
}
|
||||
|
||||
foreach(['host', 'user', 'pass', 'id', 'offline'] as $key) {
|
||||
unset($options[$key]);
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* process of on netunmount
|
||||
* Drop table `dropbox` & rm thumbs
|
||||
*
|
||||
* @param $netVolumes
|
||||
* @param $key
|
||||
* @return bool
|
||||
* @internal param array $options
|
||||
*/
|
||||
public function netunmount($netVolumes, $key)
|
||||
{
|
||||
$cache = $this->options['gdCacheDir'] . DIRECTORY_SEPARATOR . $this->options['gdCachePrefix'].$this->netMountKey;
|
||||
if (file_exists($cache) && is_writeable($cache)) {
|
||||
unlink($cache);
|
||||
}
|
||||
if ($tmbs = glob($this->tmbPath . DIRECTORY_SEPARATOR . $this->netMountKey . '*')) {
|
||||
foreach($tmbs as $file) {
|
||||
unlink($file);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* "Mount" volume.
|
||||
* Return true if volume available for read or write,
|
||||
* false - otherwise
|
||||
*
|
||||
* @param array $opts
|
||||
* @return bool
|
||||
* @author Naoki Sawada
|
||||
*/
|
||||
public function mount(array $opts)
|
||||
{
|
||||
$creds = null;
|
||||
if (isset($opts['access_token'])) {
|
||||
$this->netMountKey = md5(join('-', array('googledrive', $opts['path'], (isset($opts['access_token']['refresh_token'])? $opts['access_token']['refresh_token'] : $opts['access_token']['access_token']))));
|
||||
}
|
||||
|
||||
$client = new \Google_Client();
|
||||
$client->setClientId($opts['client_id']);
|
||||
$client->setClientSecret($opts['client_secret']);
|
||||
|
||||
if (!empty($opts['access_token'])) {
|
||||
$client->setAccessToken($opts['access_token']);
|
||||
}
|
||||
if ($client->isAccessTokenExpired()) {
|
||||
try {
|
||||
$creds = $client->fetchAccessTokenWithRefreshToken();
|
||||
} catch (LogicException $e) {
|
||||
$this->session->remove('GoogleDriveAuthParams');
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
$service = new \Google_Service_Drive($client);
|
||||
|
||||
// If path is not set, use the root
|
||||
if (!isset($opts['path']) || $opts['path'] === '') {
|
||||
$opts['path'] = 'root';
|
||||
}
|
||||
|
||||
$googleDrive = new GoogleDriveAdapter($service, $opts['path'], [ 'useHasDir' => true ]);
|
||||
|
||||
$opts['fscache'] = null;
|
||||
if ($this->options['gdCacheDir'] && is_writeable($this->options['gdCacheDir'])) {
|
||||
if ($this->options['gdCacheExpire']) {
|
||||
$opts['fscache'] = new elFinderVolumeFlysystemGoogleDriveCache(new Local($this->options['gdCacheDir']), $this->options['gdCachePrefix'].$this->netMountKey, $this->options['gdCacheExpire']);
|
||||
}
|
||||
}
|
||||
if ($opts['fscache']) {
|
||||
$filesystem = new Filesystem(new CachedAdapter($googleDrive, $opts['fscache']));
|
||||
} else {
|
||||
$filesystem = new Filesystem($googleDrive);
|
||||
}
|
||||
|
||||
$opts['driver'] = 'FlysystemExt';
|
||||
$opts['filesystem'] = $filesystem;
|
||||
$opts['separator'] = '/';
|
||||
$opts['checkSubfolders'] = true;
|
||||
if (! isset($opts['alias'])) {
|
||||
$opts['alias'] = 'GoogleDrive';
|
||||
}
|
||||
|
||||
if ($res = parent::mount($opts)) {
|
||||
// update access_token of session data
|
||||
if ($creds) {
|
||||
$netVolumes = $this->session->get('netvolume');
|
||||
$netVolumes[$this->netMountKey]['access_token'] = array_merge($netVolumes[$this->netMountKey]['access_token'], $creds);
|
||||
$this->session->set('netvolume', $netVolumes);
|
||||
}
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function tmbname($stat) {
|
||||
return $this->netMountKey.substr(substr($stat['hash'], strlen($this->id)), -38).$stat['ts'].'.png';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
/**
|
||||
* elFinder Plugin Abstract
|
||||
*
|
||||
* @package elfinder
|
||||
* @author Naoki Sawada
|
||||
* @license New BSD
|
||||
*/
|
||||
class elFinderPlugin {
|
||||
|
||||
/**
|
||||
* This plugin's options
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $opts = array();
|
||||
|
||||
/**
|
||||
* Get current volume's options
|
||||
*
|
||||
* @param object $volume
|
||||
* @return array options
|
||||
*/
|
||||
protected function getCurrentOpts($volume) {
|
||||
$name = substr(get_class($this), 14); // remove "elFinderPlugin"
|
||||
$opts = $this->opts;
|
||||
if (is_object($volume)) {
|
||||
$volOpts = $volume->getOptionsPlugin($name);
|
||||
if (is_array($volOpts)) {
|
||||
$opts = array_merge($opts, $volOpts);
|
||||
}
|
||||
}
|
||||
return $opts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is enabled with options
|
||||
*
|
||||
* @param array $opts
|
||||
* @return boolean
|
||||
*/
|
||||
protected function iaEnabled($opts, $elfinder = null) {
|
||||
if (! $opts['enable']) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// check post var 'contentSaveId' to disable this plugin
|
||||
if ($elfinder && !empty($opts['disableWithContentSaveId'])) {
|
||||
$session = $elfinder->getSession();
|
||||
$urlContentSaveIds = $session->get('urlContentSaveIds', array());
|
||||
if (!empty(elFinder::$currentArgs['contentSaveId']) && ($contentSaveId = elFinder::$currentArgs['contentSaveId'])) {
|
||||
if (!empty($urlContentSaveIds[$contentSaveId])) {
|
||||
$elfinder->removeUrlContentSaveId($contentSaveId);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($opts['onDropWith']) && !is_null($opts['onDropWith'])) {
|
||||
// plugin disabled by default, enabled only if given key is pressed
|
||||
if (isset($_REQUEST['dropWith']) && $_REQUEST['dropWith']) {
|
||||
$onDropWith = $opts['onDropWith'];
|
||||
$action = (int)$_REQUEST['dropWith'];
|
||||
if (!is_array($onDropWith)) {
|
||||
$onDropWith = array($onDropWith);
|
||||
}
|
||||
foreach($onDropWith as $key) {
|
||||
$key = (int)$key;
|
||||
if (($action & $key) === $key) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isset($opts['offDropWith']) && ! is_null($opts['offDropWith']) && isset($_REQUEST['dropWith'])) {
|
||||
// plugin enabled by default, disabled only if given key is pressed
|
||||
$offDropWith = $opts['offDropWith'];
|
||||
$action = (int)$_REQUEST['dropWith'];
|
||||
if (! is_array($offDropWith)) {
|
||||
$offDropWith = array($offDropWith);
|
||||
}
|
||||
$res = true;
|
||||
foreach($offDropWith as $key) {
|
||||
$key = (int)$key;
|
||||
if ($key === 0) {
|
||||
if ($action === 0) {
|
||||
$res = false;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (($action & $key) === $key) {
|
||||
$res = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (! $res) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,237 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* elFinder - file manager for web.
|
||||
* Session Wrapper Class.
|
||||
*
|
||||
* @package elfinder
|
||||
* @author Naoki Sawada
|
||||
**/
|
||||
|
||||
class elFinderSession implements elFinderSessionInterface
|
||||
{
|
||||
protected $started = false;
|
||||
|
||||
protected $keys = array();
|
||||
|
||||
protected $base64encode = false;
|
||||
|
||||
protected $opts = array(
|
||||
'base64encode' => false,
|
||||
'keys' => array(
|
||||
'default' => 'elFinderCaches',
|
||||
'netvolume' => 'elFinderNetVolumes'
|
||||
)
|
||||
);
|
||||
|
||||
public function __construct($opts)
|
||||
{
|
||||
$this->opts = array_merge($this->opts, $opts);
|
||||
$this->base64encode = !empty($this->opts['base64encode']);
|
||||
$this->keys = $this->opts['keys'];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function start()
|
||||
{
|
||||
if (version_compare(PHP_VERSION, '5.4.0', '>=')) {
|
||||
if (session_status() !== PHP_SESSION_ACTIVE) {
|
||||
session_start();
|
||||
}
|
||||
} else {
|
||||
set_error_handler(array($this, 'session_start_error'), E_NOTICE);
|
||||
session_start();
|
||||
restore_error_handler();
|
||||
}
|
||||
$this->started = session_id()? true : false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
if ($this->started) {
|
||||
session_write_close();
|
||||
}
|
||||
$this->started = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function get($key, $empty = null)
|
||||
{
|
||||
$closed = false;
|
||||
if (! $this->started) {
|
||||
$closed = true;
|
||||
$this->start();
|
||||
}
|
||||
|
||||
$data = null;
|
||||
|
||||
if ($this->started) {
|
||||
$session =& $this->getSessionRef($key);
|
||||
$data = $session;
|
||||
if ($data && $this->base64encode) {
|
||||
$data = $this->decodeData($data);
|
||||
}
|
||||
}
|
||||
|
||||
$checkFn = null;
|
||||
if (! is_null($empty)) {
|
||||
if (is_string($empty)) {
|
||||
$checkFn = 'is_string';
|
||||
} elseif (is_array($empty)) {
|
||||
$checkFn = 'is_array';
|
||||
} elseif (is_object($empty)) {
|
||||
$checkFn = 'is_object';
|
||||
} elseif (is_float($empty)) {
|
||||
$checkFn = 'is_float';
|
||||
} elseif (is_int($empty)) {
|
||||
$checkFn = 'is_int';
|
||||
}
|
||||
}
|
||||
|
||||
if (is_null($data) || ($checkFn && ! $checkFn($data))) {
|
||||
$session = $data = $empty;
|
||||
}
|
||||
|
||||
if ($closed) {
|
||||
$this->close();
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function set($key, $data)
|
||||
{
|
||||
$closed = false;
|
||||
if (! $this->started) {
|
||||
$closed = true;
|
||||
$this->start();
|
||||
}
|
||||
$session =& $this->getSessionRef($key);
|
||||
if ($this->base64encode) {
|
||||
$data = $this->encodeData($data);
|
||||
}
|
||||
$session = $data;
|
||||
|
||||
if ($closed) {
|
||||
$this->close();
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function remove($key)
|
||||
{
|
||||
$closed = false;
|
||||
if (! $this->started) {
|
||||
$closed = true;
|
||||
$this->start();
|
||||
}
|
||||
|
||||
list($cat, $name) = array_pad(explode('.', $key, 2), 2, null);
|
||||
if (is_null($name)) {
|
||||
if (! isset($this->keys[$cat])) {
|
||||
$name = $cat;
|
||||
$cat = 'default';
|
||||
}
|
||||
}
|
||||
if (isset($this->keys[$cat])) {
|
||||
$cat = $this->keys[$cat];
|
||||
} else {
|
||||
$name = $cat . '.' . $name;
|
||||
$cat = $this->keys['default'];
|
||||
}
|
||||
if (is_null($name)) {
|
||||
unset($_SESSION[$cat]);
|
||||
} else {
|
||||
if (isset($_SESSION[$cat]) && is_array($_SESSION[$cat])) {
|
||||
unset($_SESSION[$cat][$name]);
|
||||
}
|
||||
}
|
||||
|
||||
if ($closed) {
|
||||
$this->close();
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function & getSessionRef($key)
|
||||
{
|
||||
$session = null;
|
||||
if ($this->started) {
|
||||
list($cat, $name) = array_pad(explode('.', $key, 2), 2, null);
|
||||
if (is_null($name)) {
|
||||
if (! isset($this->keys[$cat])) {
|
||||
$name = $cat;
|
||||
$cat = 'default';
|
||||
}
|
||||
}
|
||||
if (isset($this->keys[$cat])) {
|
||||
$cat = $this->keys[$cat];
|
||||
} else {
|
||||
$name = $cat . '.' . $name;
|
||||
$cat = $this->keys['default'];
|
||||
}
|
||||
if (is_null($name)) {
|
||||
if (! isset($_SESSION[$cat])) {
|
||||
$_SESSION[$cat] = null;
|
||||
}
|
||||
$session =& $_SESSION[$cat];
|
||||
} else {
|
||||
if (! isset($_SESSION[$cat]) || ! is_array($_SESSION[$cat])) {
|
||||
$_SESSION[$cat] = array();
|
||||
}
|
||||
if (! isset($_SESSION[$cat][$name])) {
|
||||
$_SESSION[$cat][$name] = null;
|
||||
}
|
||||
$session =& $_SESSION[$cat][$name];
|
||||
}
|
||||
}
|
||||
return $session;
|
||||
}
|
||||
|
||||
protected function encodeData($data)
|
||||
{
|
||||
if ($this->base64encode) {
|
||||
$data = base64_encode(serialize($data));
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
protected function decodeData($data)
|
||||
{
|
||||
if ($this->base64encode) {
|
||||
if (is_string($data)) {
|
||||
if (($data = base64_decode($data)) !== false) {
|
||||
$data = unserialize($data);
|
||||
} else {
|
||||
$data = null;
|
||||
}
|
||||
} else {
|
||||
$data = null;
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
protected function session_start_error($errno , $errstr) {}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* elFinder - file manager for web.
|
||||
* Session Wrapper Interface.
|
||||
*
|
||||
* @package elfinder
|
||||
* @author Naoki Sawada
|
||||
**/
|
||||
|
||||
interface elFinderSessionInterface
|
||||
{
|
||||
/**
|
||||
* Session start
|
||||
*
|
||||
* @return self
|
||||
**/
|
||||
public function start();
|
||||
|
||||
/**
|
||||
* Session write & close
|
||||
*
|
||||
* @return self
|
||||
**/
|
||||
public function close();
|
||||
|
||||
/**
|
||||
* Get session data
|
||||
*
|
||||
* This method must be equipped with an automatic start / close.
|
||||
*
|
||||
* @param string $key Target key
|
||||
* @param mixed $empty Return value of if session target key does not exist
|
||||
*
|
||||
* @return mixed
|
||||
**/
|
||||
public function get($key, $empty = '');
|
||||
|
||||
/**
|
||||
* Set session data
|
||||
*
|
||||
* This method must be equipped with an automatic start / close.
|
||||
*
|
||||
* @param string $key Target key
|
||||
* @param mixed $data Value
|
||||
*
|
||||
* @return self
|
||||
**/
|
||||
public function set($key, $data);
|
||||
|
||||
/**
|
||||
* Get session data
|
||||
*
|
||||
* @param string $key Target key
|
||||
*
|
||||
* @return self
|
||||
**/
|
||||
public function remove($key);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,283 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* elFinder driver for Volume Group.
|
||||
*
|
||||
* @author Naoki Sawada
|
||||
**/
|
||||
class elFinderVolumeGroup extends elFinderVolumeDriver {
|
||||
|
||||
/**
|
||||
* Driver id
|
||||
* Must be started from letter and contains [a-z0-9]
|
||||
* Used as part of volume id
|
||||
*
|
||||
* @var string
|
||||
**/
|
||||
protected $driverId = 'g';
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* Extend options with required fields
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->options['type'] = 'group';
|
||||
$this->options['path'] = '/';
|
||||
$this->options['dirUrlOwn'] = true;
|
||||
$this->options['syncMinMs'] = 0;
|
||||
$this->options['tmbPath'] = '';
|
||||
$this->options['disabled'] = array(
|
||||
'archive',
|
||||
'copy',
|
||||
'cut',
|
||||
'duplicate',
|
||||
'edit',
|
||||
'empty',
|
||||
'extract',
|
||||
'getfile',
|
||||
'mkdir',
|
||||
'mkfile',
|
||||
'paste',
|
||||
'resize',
|
||||
'rm',
|
||||
'upload'
|
||||
);
|
||||
}
|
||||
|
||||
/*********************************************************************/
|
||||
/* FS API */
|
||||
/*********************************************************************/
|
||||
|
||||
/*********************** paths/urls *************************/
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
**/
|
||||
protected function _dirname($path) {
|
||||
return '/';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
**/
|
||||
protected function _basename($path) {
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
**/
|
||||
protected function _joinPath($dir, $name) {
|
||||
return '/' . $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
**/
|
||||
protected function _normpath($path) {
|
||||
return '/';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
**/
|
||||
protected function _relpath($path) {
|
||||
return '/';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
**/
|
||||
protected function _abspath($path) {
|
||||
return '/';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
**/
|
||||
protected function _path($path) {
|
||||
return '/';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
**/
|
||||
protected function _inpath($path, $parent) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************** file stat ********************/
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
**/
|
||||
protected function _stat($path) {
|
||||
if ($path === '/') {
|
||||
return array(
|
||||
'size' => 0,
|
||||
'ts' => 0,
|
||||
'mime' => 'directory',
|
||||
'read' => true,
|
||||
'write' => false,
|
||||
'locked' => true,
|
||||
'hidden' => false,
|
||||
'dirs' => 0
|
||||
);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
**/
|
||||
protected function _subdirs($path) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
**/
|
||||
protected function _dimensions($path, $mime) {
|
||||
return false;
|
||||
}
|
||||
/******************** file/dir content *********************/
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
**/
|
||||
protected function readlink($path) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
**/
|
||||
protected function _scandir($path) {
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
**/
|
||||
protected function _fopen($path, $mode='rb') {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
**/
|
||||
protected function _fclose($fp, $path='') {
|
||||
return true;
|
||||
}
|
||||
|
||||
/******************** file/dir manipulations *************************/
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
**/
|
||||
protected function _mkdir($path, $name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
**/
|
||||
protected function _mkfile($path, $name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
**/
|
||||
protected function _symlink($source, $targetDir, $name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
**/
|
||||
protected function _copy($source, $targetDir, $name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
**/
|
||||
protected function _move($source, $targetDir, $name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
**/
|
||||
protected function _unlink($path) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
**/
|
||||
protected function _rmdir($path) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
**/
|
||||
protected function _save($fp, $dir, $name, $stat) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
**/
|
||||
protected function _getContents($path) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
**/
|
||||
protected function _filePutContents($path, $content) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
**/
|
||||
protected function _checkArchivers() {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
**/
|
||||
protected function _chmod($path, $mode) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
**/
|
||||
protected function _findSymlinks($path) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
**/
|
||||
protected function _extract($path, $arc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
**/
|
||||
protected function _archive($dir, $files, $name, $arc) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,938 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Simple elFinder driver for MySQL.
|
||||
*
|
||||
* @author Dmitry (dio) Levashov
|
||||
**/
|
||||
class elFinderVolumeMySQL extends elFinderVolumeDriver {
|
||||
|
||||
/**
|
||||
* Driver id
|
||||
* Must be started from letter and contains [a-z0-9]
|
||||
* Used as part of volume id
|
||||
*
|
||||
* @var string
|
||||
**/
|
||||
protected $driverId = 'm';
|
||||
|
||||
/**
|
||||
* Database object
|
||||
*
|
||||
* @var mysqli
|
||||
**/
|
||||
protected $db = null;
|
||||
|
||||
/**
|
||||
* Tables to store files
|
||||
*
|
||||
* @var string
|
||||
**/
|
||||
protected $tbf = '';
|
||||
|
||||
/**
|
||||
* Directory for tmp files
|
||||
* If not set driver will try to use tmbDir as tmpDir
|
||||
*
|
||||
* @var string
|
||||
**/
|
||||
protected $tmpPath = '';
|
||||
|
||||
/**
|
||||
* Numbers of sql requests (for debug)
|
||||
*
|
||||
* @var int
|
||||
**/
|
||||
protected $sqlCnt = 0;
|
||||
|
||||
/**
|
||||
* Last db error message
|
||||
*
|
||||
* @var string
|
||||
**/
|
||||
protected $dbError = '';
|
||||
|
||||
/**
|
||||
* This root has parent id
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $rootHasParent = false;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* Extend options with required fields
|
||||
*
|
||||
* @author Dmitry (dio) Levashov
|
||||
*/
|
||||
public function __construct() {
|
||||
$opts = array(
|
||||
'host' => 'localhost',
|
||||
'user' => '',
|
||||
'pass' => '',
|
||||
'db' => '',
|
||||
'port' => null,
|
||||
'socket' => null,
|
||||
'files_table' => 'elfinder_file',
|
||||
'tmbPath' => '',
|
||||
'tmpPath' => '',
|
||||
'rootCssClass' => 'elfinder-navbar-root-sql',
|
||||
'noSessionCache' => array('hasdirs')
|
||||
);
|
||||
$this->options = array_merge($this->options, $opts);
|
||||
$this->options['mimeDetect'] = 'internal';
|
||||
}
|
||||
|
||||
/*********************************************************************/
|
||||
/* INIT AND CONFIGURE */
|
||||
/*********************************************************************/
|
||||
|
||||
/**
|
||||
* Prepare driver before mount volume.
|
||||
* Connect to db, check required tables and fetch root path
|
||||
*
|
||||
* @return bool
|
||||
* @author Dmitry (dio) Levashov
|
||||
**/
|
||||
protected function init() {
|
||||
|
||||
if (!($this->options['host'] || $this->options['socket'])
|
||||
|| !$this->options['user']
|
||||
|| !$this->options['pass']
|
||||
|| !$this->options['db']
|
||||
|| !$this->options['path']
|
||||
|| !$this->options['files_table']) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
$this->db = new mysqli($this->options['host'], $this->options['user'], $this->options['pass'], $this->options['db'], $this->options['port'], $this->options['socket']);
|
||||
if ($this->db->connect_error || mysqli_connect_error()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->db->set_charset('utf8');
|
||||
|
||||
if ($res = $this->db->query('SHOW TABLES')) {
|
||||
while ($row = $res->fetch_array()) {
|
||||
if ($row[0] == $this->options['files_table']) {
|
||||
$this->tbf = $this->options['files_table'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$this->tbf) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->updateCache($this->options['path'], $this->_stat($this->options['path']));
|
||||
|
||||
// enable command archive
|
||||
$this->options['useRemoteArchive'] = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set tmp path
|
||||
*
|
||||
* @return void
|
||||
* @author Dmitry (dio) Levashov
|
||||
**/
|
||||
protected function configure() {
|
||||
parent::configure();
|
||||
|
||||
if (($tmp = $this->options['tmpPath'])) {
|
||||
if (!file_exists($tmp)) {
|
||||
if (mkdir($tmp)) {
|
||||
chmod($tmp, $this->options['tmbPathMode']);
|
||||
}
|
||||
}
|
||||
|
||||
$this->tmpPath = is_dir($tmp) && is_writable($tmp) ? $tmp : false;
|
||||
}
|
||||
if (!$this->tmpPath && ($tmp = elFinder::getStaticVar('commonTempPath'))) {
|
||||
$this->tmpPath = $tmp;
|
||||
}
|
||||
|
||||
// fallback of $this->tmp
|
||||
if (!$this->tmpPath && $this->tmbPathWritable) {
|
||||
$this->tmpPath = $this->tmbPath;
|
||||
}
|
||||
|
||||
$this->mimeDetect = 'internal';
|
||||
}
|
||||
|
||||
/**
|
||||
* Close connection
|
||||
*
|
||||
* @return void
|
||||
* @author Dmitry (dio) Levashov
|
||||
**/
|
||||
public function umount() {
|
||||
$this->db->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return debug info for client
|
||||
*
|
||||
* @return array
|
||||
* @author Dmitry (dio) Levashov
|
||||
**/
|
||||
public function debug() {
|
||||
$debug = parent::debug();
|
||||
$debug['sqlCount'] = $this->sqlCnt;
|
||||
if ($this->dbError) {
|
||||
$debug['dbError'] = $this->dbError;
|
||||
}
|
||||
return $debug;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform sql query and return result.
|
||||
* Increase sqlCnt and save error if occured
|
||||
*
|
||||
* @param string $sql query
|
||||
* @return misc
|
||||
* @author Dmitry (dio) Levashov
|
||||
**/
|
||||
protected function query($sql) {
|
||||
$this->sqlCnt++;
|
||||
$res = $this->db->query($sql);
|
||||
if (!$res) {
|
||||
$this->dbError = $this->db->error;
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create empty object with required mimetype
|
||||
*
|
||||
* @param string $path parent dir path
|
||||
* @param string $name object name
|
||||
* @param string $mime mime type
|
||||
* @return bool
|
||||
* @author Dmitry (dio) Levashov
|
||||
**/
|
||||
protected function make($path, $name, $mime) {
|
||||
$sql = 'INSERT INTO %s (`parent_id`, `name`, `size`, `mtime`, `mime`, `content`, `read`, `write`, `locked`, `hidden`, `width`, `height`) VALUES (\'%s\', \'%s\', 0, %d, \'%s\', \'\', \'%d\', \'%d\', \'%d\', \'%d\', 0, 0)';
|
||||
$sql = sprintf($sql, $this->tbf, $path, $this->db->real_escape_string($name), time(), $mime, $this->defaults['read'], $this->defaults['write'], $this->defaults['locked'], $this->defaults['hidden']);
|
||||
// echo $sql;
|
||||
return $this->query($sql) && $this->db->affected_rows > 0;
|
||||
}
|
||||
|
||||
/*********************************************************************/
|
||||
/* FS API */
|
||||
/*********************************************************************/
|
||||
|
||||
/**
|
||||
* Cache dir contents
|
||||
*
|
||||
* @param string $path dir path
|
||||
* @return string
|
||||
* @author Dmitry Levashov
|
||||
**/
|
||||
protected function cacheDir($path) {
|
||||
$this->dirsCache[$path] = array();
|
||||
|
||||
$sql = 'SELECT f.id, f.parent_id, f.name, f.size, f.mtime AS ts, f.mime, f.read, f.write, f.locked, f.hidden, f.width, f.height, IF(ch.id, 1, 0) AS dirs
|
||||
FROM '.$this->tbf.' AS f
|
||||
LEFT JOIN '.$this->tbf.' AS ch ON ch.parent_id=f.id AND ch.mime=\'directory\'
|
||||
WHERE f.parent_id=\''.$path.'\'
|
||||
GROUP BY f.id, ch.id';
|
||||
|
||||
$res = $this->query($sql);
|
||||
if ($res) {
|
||||
while ($row = $res->fetch_assoc()) {
|
||||
$id = $row['id'];
|
||||
if ($row['parent_id'] && $id != $this->root) {
|
||||
$row['phash'] = $this->encode($row['parent_id']);
|
||||
}
|
||||
|
||||
if ($row['mime'] == 'directory') {
|
||||
unset($row['width']);
|
||||
unset($row['height']);
|
||||
$row['size'] = 0;
|
||||
} else {
|
||||
unset($row['dirs']);
|
||||
}
|
||||
|
||||
unset($row['id']);
|
||||
unset($row['parent_id']);
|
||||
|
||||
|
||||
|
||||
if (($stat = $this->updateCache($id, $row)) && empty($stat['hidden'])) {
|
||||
$this->dirsCache[$path][] = $id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->dirsCache[$path];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return array of parents paths (ids)
|
||||
*
|
||||
* @param int $path file path (id)
|
||||
* @return array
|
||||
* @author Dmitry (dio) Levashov
|
||||
**/
|
||||
protected function getParents($path) {
|
||||
$parents = array();
|
||||
|
||||
while ($path) {
|
||||
if ($file = $this->stat($path)) {
|
||||
array_unshift($parents, $path);
|
||||
$path = isset($file['phash']) ? $this->decode($file['phash']) : false;
|
||||
}
|
||||
}
|
||||
|
||||
if (count($parents)) {
|
||||
array_pop($parents);
|
||||
}
|
||||
return $parents;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return correct file path for LOAD_FILE method
|
||||
*
|
||||
* @param string $path file path (id)
|
||||
* @return string
|
||||
* @author Troex Nevelin
|
||||
**/
|
||||
protected function loadFilePath($path) {
|
||||
$realPath = realpath($path);
|
||||
if (DIRECTORY_SEPARATOR == '\\') { // windows
|
||||
$realPath = str_replace('\\', '\\\\', $realPath);
|
||||
}
|
||||
return $this->db->real_escape_string($realPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursive files search
|
||||
*
|
||||
* @param string $path dir path
|
||||
* @param string $q search string
|
||||
* @param array $mimes
|
||||
* @return array
|
||||
* @author Dmitry (dio) Levashov
|
||||
**/
|
||||
protected function doSearch($path, $q, $mimes) {
|
||||
if (!empty($this->doSearchCurrentQuery['matchMethod'])) {
|
||||
// has custom match method use elFinderVolumeDriver::doSearch()
|
||||
return parent::doSearch($path, $q, $mimes);
|
||||
}
|
||||
|
||||
$dirs = array();
|
||||
$timeout = $this->options['searchTimeout']? $this->searchStart + $this->options['searchTimeout'] : 0;
|
||||
|
||||
if ($path != $this->root || $this->rootHasParent) {
|
||||
$dirs = $inpath = array(intval($path));
|
||||
while($inpath) {
|
||||
$in = '('.join(',', $inpath).')';
|
||||
$inpath = array();
|
||||
$sql = 'SELECT f.id FROM %s AS f WHERE f.parent_id IN '.$in.' AND `mime` = \'directory\'';
|
||||
$sql = sprintf($sql, $this->tbf);
|
||||
if ($res = $this->query($sql)) {
|
||||
$_dir = array();
|
||||
while ($dat = $res->fetch_assoc()) {
|
||||
$inpath[] = $dat['id'];
|
||||
}
|
||||
$dirs = array_merge($dirs, $inpath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$result = array();
|
||||
|
||||
if ($mimes) {
|
||||
$whrs = array();
|
||||
foreach($mimes as $mime) {
|
||||
if (strpos($mime, '/') === false) {
|
||||
$whrs[] = sprintf('f.mime LIKE \'%s/%%\'', $this->db->real_escape_string($mime));
|
||||
} else {
|
||||
$whrs[] = sprintf('f.mime = \'%s\'', $this->db->real_escape_string($mime));
|
||||
}
|
||||
}
|
||||
$whr = join(' OR ', $whrs);
|
||||
} else {
|
||||
$whr = sprintf('f.name LIKE \'%%%s%%\'', $this->db->real_escape_string($q));
|
||||
}
|
||||
if ($dirs) {
|
||||
$whr = '(' . $whr . ') AND (`parent_id` IN (' . join(',', $dirs) . '))';
|
||||
}
|
||||
|
||||
$sql = 'SELECT f.id, f.parent_id, f.name, f.size, f.mtime AS ts, f.mime, f.read, f.write, f.locked, f.hidden, f.width, f.height, 0 AS dirs
|
||||
FROM %s AS f
|
||||
WHERE %s';
|
||||
|
||||
$sql = sprintf($sql, $this->tbf, $whr);
|
||||
|
||||
if (($res = $this->query($sql))) {
|
||||
while ($row = $res->fetch_assoc()) {
|
||||
if ($timeout && $timeout < time()) {
|
||||
$this->setError(elFinder::ERROR_SEARCH_TIMEOUT, $this->path($this->encode($path)));
|
||||
break;
|
||||
}
|
||||
|
||||
if (!$this->mimeAccepted($row['mime'], $mimes)) {
|
||||
continue;
|
||||
}
|
||||
$id = $row['id'];
|
||||
if ($id == $this->root) {
|
||||
continue;
|
||||
}
|
||||
if ($row['parent_id'] && $id != $this->root) {
|
||||
$row['phash'] = $this->encode($row['parent_id']);
|
||||
}
|
||||
$row['path'] = $this->_path($id);
|
||||
|
||||
if ($row['mime'] == 'directory') {
|
||||
unset($row['width']);
|
||||
unset($row['height']);
|
||||
} else {
|
||||
unset($row['dirs']);
|
||||
}
|
||||
|
||||
unset($row['id']);
|
||||
unset($row['parent_id']);
|
||||
|
||||
if (($stat = $this->updateCache($id, $row)) && empty($stat['hidden'])) {
|
||||
$result[] = $stat;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
/*********************** paths/urls *************************/
|
||||
|
||||
/**
|
||||
* Return parent directory path
|
||||
*
|
||||
* @param string $path file path
|
||||
* @return string
|
||||
* @author Dmitry (dio) Levashov
|
||||
**/
|
||||
protected function _dirname($path) {
|
||||
return ($stat = $this->stat($path)) ? (!empty($stat['phash']) ? $this->decode($stat['phash']) : $this->root) : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return file name
|
||||
*
|
||||
* @param string $path file path
|
||||
* @return string
|
||||
* @author Dmitry (dio) Levashov
|
||||
**/
|
||||
protected function _basename($path) {
|
||||
return ($stat = $this->stat($path)) ? $stat['name'] : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Join dir name and file name and return full path
|
||||
*
|
||||
* @param string $dir
|
||||
* @param string $name
|
||||
* @return string
|
||||
* @author Dmitry (dio) Levashov
|
||||
**/
|
||||
protected function _joinPath($dir, $name) {
|
||||
$sql = 'SELECT id FROM '.$this->tbf.' WHERE parent_id=\''.$dir.'\' AND name=\''.$this->db->real_escape_string($name).'\'';
|
||||
|
||||
if (($res = $this->query($sql)) && ($r = $res->fetch_assoc())) {
|
||||
$this->updateCache($r['id'], $this->_stat($r['id']));
|
||||
return $r['id'];
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return normalized path, this works the same as os.path.normpath() in Python
|
||||
*
|
||||
* @param string $path path
|
||||
* @return string
|
||||
* @author Troex Nevelin
|
||||
**/
|
||||
protected function _normpath($path) {
|
||||
return $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return file path related to root dir
|
||||
*
|
||||
* @param string $path file path
|
||||
* @return string
|
||||
* @author Dmitry (dio) Levashov
|
||||
**/
|
||||
protected function _relpath($path) {
|
||||
return $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert path related to root dir into real path
|
||||
*
|
||||
* @param string $path file path
|
||||
* @return string
|
||||
* @author Dmitry (dio) Levashov
|
||||
**/
|
||||
protected function _abspath($path) {
|
||||
return $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return fake path started from root dir
|
||||
*
|
||||
* @param string $path file path
|
||||
* @return string
|
||||
* @author Dmitry (dio) Levashov
|
||||
**/
|
||||
protected function _path($path) {
|
||||
if (($file = $this->stat($path)) == false) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$parentsIds = $this->getParents($path);
|
||||
$path = '';
|
||||
foreach ($parentsIds as $id) {
|
||||
$dir = $this->stat($id);
|
||||
$path .= $dir['name'].$this->separator;
|
||||
}
|
||||
return $path.$file['name'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if $path is children of $parent
|
||||
*
|
||||
* @param string $path path to check
|
||||
* @param string $parent parent path
|
||||
* @return bool
|
||||
* @author Dmitry (dio) Levashov
|
||||
**/
|
||||
protected function _inpath($path, $parent) {
|
||||
return $path == $parent
|
||||
? true
|
||||
: in_array($parent, $this->getParents($path));
|
||||
}
|
||||
|
||||
/***************** file stat ********************/
|
||||
/**
|
||||
* Return stat for given path.
|
||||
* Stat contains following fields:
|
||||
* - (int) size file size in b. required
|
||||
* - (int) ts file modification time in unix time. required
|
||||
* - (string) mime mimetype. required for folders, others - optionally
|
||||
* - (bool) read read permissions. required
|
||||
* - (bool) write write permissions. required
|
||||
* - (bool) locked is object locked. optionally
|
||||
* - (bool) hidden is object hidden. optionally
|
||||
* - (string) alias for symlinks - link target path relative to root path. optionally
|
||||
* - (string) target for symlinks - link target path. optionally
|
||||
*
|
||||
* If file does not exists - returns empty array or false.
|
||||
*
|
||||
* @param string $path file path
|
||||
* @return array|false
|
||||
* @author Dmitry (dio) Levashov
|
||||
**/
|
||||
protected function _stat($path) {
|
||||
$sql = 'SELECT f.id, f.parent_id, f.name, f.size, f.mtime AS ts, f.mime, f.read, f.write, f.locked, f.hidden, f.width, f.height, IF(ch.id, 1, 0) AS dirs
|
||||
FROM '.$this->tbf.' AS f
|
||||
LEFT JOIN '.$this->tbf.' AS ch ON ch.parent_id=f.id AND ch.mime=\'directory\'
|
||||
WHERE f.id=\''.$path.'\'
|
||||
GROUP BY f.id, ch.id';
|
||||
|
||||
$res = $this->query($sql);
|
||||
|
||||
if ($res) {
|
||||
$stat = $res->fetch_assoc();
|
||||
if ($stat['id'] == $this->root) {
|
||||
$this->rootHasParent = true;
|
||||
$stat['parent_id'] = '';
|
||||
}
|
||||
if ($stat['parent_id']) {
|
||||
$stat['phash'] = $this->encode($stat['parent_id']);
|
||||
}
|
||||
if ($stat['mime'] == 'directory') {
|
||||
unset($stat['width']);
|
||||
unset($stat['height']);
|
||||
$stat['size'] = 0;
|
||||
} else {
|
||||
if (!$stat['mime']) {
|
||||
unset($stat['mime']);
|
||||
}
|
||||
unset($stat['dirs']);
|
||||
}
|
||||
unset($stat['id']);
|
||||
unset($stat['parent_id']);
|
||||
return $stat;
|
||||
|
||||
}
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if path is dir and has at least one childs directory
|
||||
*
|
||||
* @param string $path dir path
|
||||
* @return bool
|
||||
* @author Dmitry (dio) Levashov
|
||||
**/
|
||||
protected function _subdirs($path) {
|
||||
return ($stat = $this->stat($path)) && isset($stat['dirs']) ? $stat['dirs'] : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return object width and height
|
||||
* Usualy used for images, but can be realize for video etc...
|
||||
*
|
||||
* @param string $path file path
|
||||
* @param string $mime file mime type
|
||||
* @return string
|
||||
* @author Dmitry (dio) Levashov
|
||||
**/
|
||||
protected function _dimensions($path, $mime) {
|
||||
return ($stat = $this->stat($path)) && isset($stat['width']) && isset($stat['height']) ? $stat['width'].'x'.$stat['height'] : '';
|
||||
}
|
||||
|
||||
/******************** file/dir content *********************/
|
||||
|
||||
/**
|
||||
* Return files list in directory.
|
||||
*
|
||||
* @param string $path dir path
|
||||
* @return array
|
||||
* @author Dmitry (dio) Levashov
|
||||
**/
|
||||
protected function _scandir($path) {
|
||||
return isset($this->dirsCache[$path])
|
||||
? $this->dirsCache[$path]
|
||||
: $this->cacheDir($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open file and return file pointer
|
||||
*
|
||||
* @param string $path file path
|
||||
* @param string $mode open file mode (ignored in this driver)
|
||||
* @return resource|false
|
||||
* @author Dmitry (dio) Levashov
|
||||
**/
|
||||
protected function _fopen($path, $mode='rb') {
|
||||
$fp = $this->tmbPath
|
||||
? fopen($this->getTempFile($path), 'w+')
|
||||
: $this->tmpfile();
|
||||
|
||||
|
||||
if ($fp) {
|
||||
if (($res = $this->query('SELECT content FROM '.$this->tbf.' WHERE id=\''.$path.'\''))
|
||||
&& ($r = $res->fetch_assoc())) {
|
||||
fwrite($fp, $r['content']);
|
||||
rewind($fp);
|
||||
return $fp;
|
||||
} else {
|
||||
$this->_fclose($fp, $path);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close opened file
|
||||
*
|
||||
* @param resource $fp file pointer
|
||||
* @param string $path
|
||||
* @return bool
|
||||
* @author Dmitry (dio) Levashov
|
||||
*/
|
||||
protected function _fclose($fp, $path='') {
|
||||
is_resource($fp) && fclose($fp);
|
||||
if ($path) {
|
||||
$file = $this->getTempFile($path);
|
||||
is_file($file) && unlink($file);
|
||||
}
|
||||
}
|
||||
|
||||
/******************** file/dir manipulations *************************/
|
||||
|
||||
/**
|
||||
* Create dir and return created dir path or false on failed
|
||||
*
|
||||
* @param string $path parent dir path
|
||||
* @param string $name new directory name
|
||||
* @return string|bool
|
||||
* @author Dmitry (dio) Levashov
|
||||
**/
|
||||
protected function _mkdir($path, $name) {
|
||||
return $this->make($path, $name, 'directory') ? $this->_joinPath($path, $name) : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create file and return it's path or false on failed
|
||||
*
|
||||
* @param string $path parent dir path
|
||||
* @param string $name new file name
|
||||
* @return string|bool
|
||||
* @author Dmitry (dio) Levashov
|
||||
**/
|
||||
protected function _mkfile($path, $name) {
|
||||
return $this->make($path, $name, '') ? $this->_joinPath($path, $name) : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create symlink. FTP driver does not support symlinks.
|
||||
*
|
||||
* @param string $target link target
|
||||
* @param string $path symlink path
|
||||
* @param string $name
|
||||
* @return bool
|
||||
* @author Dmitry (dio) Levashov
|
||||
*/
|
||||
protected function _symlink($target, $path, $name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy file into another file
|
||||
*
|
||||
* @param string $source source file path
|
||||
* @param string $targetDir target directory path
|
||||
* @param string $name new file name
|
||||
* @return bool
|
||||
* @author Dmitry (dio) Levashov
|
||||
**/
|
||||
protected function _copy($source, $targetDir, $name) {
|
||||
$this->clearcache();
|
||||
$id = $this->_joinPath($targetDir, $name);
|
||||
|
||||
$sql = $id > 0
|
||||
? sprintf('REPLACE INTO %s (id, parent_id, name, content, size, mtime, mime, width, height, `read`, `write`, `locked`, `hidden`) (SELECT %d, %d, name, content, size, mtime, mime, width, height, `read`, `write`, `locked`, `hidden` FROM %s WHERE id=%d)', $this->tbf, $id, $this->_dirname($id), $this->tbf, $source)
|
||||
: sprintf('INSERT INTO %s (parent_id, name, content, size, mtime, mime, width, height, `read`, `write`, `locked`, `hidden`) SELECT %d, \'%s\', content, size, %d, mime, width, height, `read`, `write`, `locked`, `hidden` FROM %s WHERE id=%d', $this->tbf, $targetDir, $this->db->real_escape_string($name), time(), $this->tbf, $source);
|
||||
|
||||
return $this->query($sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* Move file into another parent dir.
|
||||
* Return new file path or false.
|
||||
*
|
||||
* @param string $source source file path
|
||||
* @param $targetDir
|
||||
* @param string $name file name
|
||||
* @return bool|string
|
||||
* @internal param string $target target dir path
|
||||
* @author Dmitry (dio) Levashov
|
||||
*/
|
||||
protected function _move($source, $targetDir, $name) {
|
||||
$sql = 'UPDATE %s SET parent_id=%d, name=\'%s\' WHERE id=%d LIMIT 1';
|
||||
$sql = sprintf($sql, $this->tbf, $targetDir, $this->db->real_escape_string($name), $source);
|
||||
return $this->query($sql) && $this->db->affected_rows > 0 ? $source : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove file
|
||||
*
|
||||
* @param string $path file path
|
||||
* @return bool
|
||||
* @author Dmitry (dio) Levashov
|
||||
**/
|
||||
protected function _unlink($path) {
|
||||
return $this->query(sprintf('DELETE FROM %s WHERE id=%d AND mime!=\'directory\' LIMIT 1', $this->tbf, $path)) && $this->db->affected_rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove dir
|
||||
*
|
||||
* @param string $path dir path
|
||||
* @return bool
|
||||
* @author Dmitry (dio) Levashov
|
||||
**/
|
||||
protected function _rmdir($path) {
|
||||
return $this->query(sprintf('DELETE FROM %s WHERE id=%d AND mime=\'directory\' LIMIT 1', $this->tbf, $path)) && $this->db->affected_rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* undocumented function
|
||||
*
|
||||
* @param $path
|
||||
* @param $fp
|
||||
* @author Dmitry Levashov
|
||||
*/
|
||||
protected function _setContent($path, $fp) {
|
||||
elFinder::rewind($fp);
|
||||
$fstat = fstat($fp);
|
||||
$size = $fstat['size'];
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new file and write into it from file pointer.
|
||||
* Return new file path or false on error.
|
||||
*
|
||||
* @param resource $fp file pointer
|
||||
* @param string $dir target dir path
|
||||
* @param string $name file name
|
||||
* @param array $stat file stat (required by some virtual fs)
|
||||
* @return bool|string
|
||||
* @author Dmitry (dio) Levashov
|
||||
**/
|
||||
protected function _save($fp, $dir, $name, $stat) {
|
||||
$this->clearcache();
|
||||
|
||||
$mime = $stat['mime'];
|
||||
$w = !empty($stat['width']) ? $stat['width'] : 0;
|
||||
$h = !empty($stat['height']) ? $stat['height'] : 0;
|
||||
|
||||
$id = $this->_joinPath($dir, $name);
|
||||
elFinder::rewind($fp);
|
||||
$stat = fstat($fp);
|
||||
$size = $stat['size'];
|
||||
|
||||
if (($tmpfile = tempnam($this->tmpPath, $this->id))) {
|
||||
if (($trgfp = fopen($tmpfile, 'wb')) == false) {
|
||||
unlink($tmpfile);
|
||||
} else {
|
||||
while (!feof($fp)) {
|
||||
fwrite($trgfp, fread($fp, 8192));
|
||||
}
|
||||
fclose($trgfp);
|
||||
chmod($tmpfile, 0644);
|
||||
|
||||
$sql = $id > 0
|
||||
? 'REPLACE INTO %s (id, parent_id, name, content, size, mtime, mime, width, height) VALUES ('.$id.', %d, \'%s\', LOAD_FILE(\'%s\'), %d, %d, \'%s\', %d, %d)'
|
||||
: 'INSERT INTO %s (parent_id, name, content, size, mtime, mime, width, height) VALUES (%d, \'%s\', LOAD_FILE(\'%s\'), %d, %d, \'%s\', %d, %d)';
|
||||
$sql = sprintf($sql, $this->tbf, $dir, $this->db->real_escape_string($name), $this->loadFilePath($tmpfile), $size, time(), $mime, $w, $h);
|
||||
|
||||
$res = $this->query($sql);
|
||||
unlink($tmpfile);
|
||||
|
||||
if ($res) {
|
||||
return $id > 0 ? $id : $this->db->insert_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$content = '';
|
||||
elFinder::rewind($fp);
|
||||
while (!feof($fp)) {
|
||||
$content .= fread($fp, 8192);
|
||||
}
|
||||
|
||||
$sql = $id > 0
|
||||
? 'REPLACE INTO %s (id, parent_id, name, content, size, mtime, mime, width, height) VALUES ('.$id.', %d, \'%s\', \'%s\', %d, %d, \'%s\', %d, %d)'
|
||||
: 'INSERT INTO %s (parent_id, name, content, size, mtime, mime, width, height) VALUES (%d, \'%s\', \'%s\', %d, %d, \'%s\', %d, %d)';
|
||||
$sql = sprintf($sql, $this->tbf, $dir, $this->db->real_escape_string($name), $this->db->real_escape_string($content), $size, time(), $mime, $w, $h);
|
||||
|
||||
unset($content);
|
||||
|
||||
if ($this->query($sql)) {
|
||||
return $id > 0 ? $id : $this->db->insert_id;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get file contents
|
||||
*
|
||||
* @param string $path file path
|
||||
* @return string|false
|
||||
* @author Dmitry (dio) Levashov
|
||||
**/
|
||||
protected function _getContents($path) {
|
||||
return ($res = $this->query(sprintf('SELECT content FROM %s WHERE id=%d', $this->tbf, $path))) && ($r = $res->fetch_assoc()) ? $r['content'] : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a string to a file
|
||||
*
|
||||
* @param string $path file path
|
||||
* @param string $content new file content
|
||||
* @return bool
|
||||
* @author Dmitry (dio) Levashov
|
||||
**/
|
||||
protected function _filePutContents($path, $content) {
|
||||
return $this->query(sprintf('UPDATE %s SET content=\'%s\', size=%d, mtime=%d WHERE id=%d LIMIT 1', $this->tbf, $this->db->real_escape_string($content), strlen($content), time(), $path));
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect available archivers
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
protected function _checkArchivers() {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* chmod implementation
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $mode
|
||||
* @return bool
|
||||
*/
|
||||
protected function _chmod($path, $mode) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unpack archive
|
||||
*
|
||||
* @param string $path archive path
|
||||
* @param array $arc archiver command and arguments (same as in $this->archivers)
|
||||
* @return void
|
||||
* @author Dmitry (dio) Levashov
|
||||
* @author Alexey Sukhotin
|
||||
**/
|
||||
protected function _unpack($path, $arc) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursive symlinks search
|
||||
*
|
||||
* @param string $path file/dir path
|
||||
* @return bool
|
||||
* @author Dmitry (dio) Levashov
|
||||
**/
|
||||
protected function _findSymlinks($path) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract files from archive
|
||||
*
|
||||
* @param string $path archive path
|
||||
* @param array $arc archiver command and arguments (same as in $this->archivers)
|
||||
* @return true
|
||||
* @author Dmitry (dio) Levashov,
|
||||
* @author Alexey Sukhotin
|
||||
**/
|
||||
protected function _extract($path, $arc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create archive and return its path
|
||||
*
|
||||
* @param string $dir target dir
|
||||
* @param array $files files names list
|
||||
* @param string $name archive name
|
||||
* @param array $arc archiver options
|
||||
* @return string|bool
|
||||
* @author Dmitry (dio) Levashov,
|
||||
* @author Alexey Sukhotin
|
||||
**/
|
||||
protected function _archive($dir, $files, $name, $arc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
} // END class
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
/**
|
||||
* elFinder driver for trash bin at local filesystem.
|
||||
*
|
||||
* @author NaokiSawada
|
||||
**/
|
||||
class elFinderVolumeTrash extends elFinderVolumeLocalFileSystem
|
||||
{
|
||||
/**
|
||||
* Driver id
|
||||
* Must be started from letter and contains [a-z0-9]
|
||||
* Used as part of volume id.
|
||||
*
|
||||
* @var string
|
||||
**/
|
||||
protected $driverId = 't';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
// original option of the Trash
|
||||
$this->options['lockEverything'] = false; // Lock all items in the trash to disable delete, move, rename.
|
||||
|
||||
// common options as the volume driver
|
||||
$this->options['alias'] = 'Trash';
|
||||
$this->options['quarantine'] = '';
|
||||
$this->options['rootCssClass'] = 'elfinder-navbar-root-trash';
|
||||
$this->options['copyOverwrite'] = false;
|
||||
$this->options['uiCmdMap'] = array('paste' => 'hidden', 'mkdir' => 'hidden', 'copy' => 'restore');
|
||||
$this->options['disabled'] = array('archive', 'duplicate', 'edit', 'extract', 'mkfile', 'places', 'put', 'rename', 'resize', 'upload');
|
||||
}
|
||||
|
||||
public function mount(array $opts)
|
||||
{
|
||||
if ($this->options['lockEverything']) {
|
||||
if (!is_array($opts['attributes'])) {
|
||||
$opts['attributes'] = array();
|
||||
}
|
||||
$attr = array(
|
||||
'pattern' => '/./',
|
||||
'locked' => true,
|
||||
);
|
||||
array_unshift($opts['attributes'], $attr);
|
||||
}
|
||||
// force set `copyJoin` to true
|
||||
$opts['copyJoin'] = true;
|
||||
|
||||
return parent::mount($opts);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
/**
|
||||
* elFinder driver for trash bin at MySQL Database
|
||||
*
|
||||
* @author NaokiSawada
|
||||
**/
|
||||
class elFinderVolumeTrashMySQL extends elFinderVolumeMySQL
|
||||
{
|
||||
/**
|
||||
* Driver id
|
||||
* Must be started from letter and contains [a-z0-9]
|
||||
* Used as part of volume id.
|
||||
*
|
||||
* @var string
|
||||
**/
|
||||
protected $driverId = 'tm';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
// original option of the Trash
|
||||
$this->options['lockEverything'] = false; // Lock all items in the trash to disable delete, move, rename.
|
||||
|
||||
// common options as the volume driver
|
||||
$this->options['alias'] = 'Trash';
|
||||
$this->options['quarantine'] = '';
|
||||
$this->options['rootCssClass'] = 'elfinder-navbar-root-trash';
|
||||
$this->options['copyOverwrite'] = false;
|
||||
$this->options['uiCmdMap'] = array('paste' => 'hidden', 'mkdir' => 'hidden', 'copy' => 'restore');
|
||||
$this->options['disabled'] = array('archive', 'duplicate', 'edit', 'extract', 'mkfile', 'places', 'put', 'rename', 'resize', 'upload');
|
||||
}
|
||||
|
||||
public function mount(array $opts)
|
||||
{
|
||||
if ($this->options['lockEverything']) {
|
||||
if (!is_array($opts['attributes'])) {
|
||||
$opts['attributes'] = array();
|
||||
}
|
||||
$attr = array(
|
||||
'pattern' => '/./',
|
||||
'locked' => true,
|
||||
);
|
||||
array_unshift($opts['attributes'], $attr);
|
||||
}
|
||||
// force set `copyJoin` to true
|
||||
$opts['copyJoin'] = true;
|
||||
|
||||
return parent::mount($opts);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,447 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) 2011, oov. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* - Neither the name of the oov nor the names of its contributors may be used to
|
||||
* endorse or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* bmp ファイルを GD で使えるように
|
||||
*
|
||||
* 使用例:
|
||||
* //ファイルから読み込む場合はGDでPNGなどを読み込むのと同じような方法で可
|
||||
* $image = imagecreatefrombmp("test.bmp");
|
||||
* imagedestroy($image);
|
||||
*
|
||||
* //文字列から読み込む場合は以下の方法で可
|
||||
* $image = GdBmp::loadFromString(file_get_contents("test.bmp"));
|
||||
* //自動判定されるので破損ファイルでなければこれでも上手くいく
|
||||
* //$image = imagecreatefrombmp(file_get_contents("test.bmp"));
|
||||
* imagedestroy($image);
|
||||
*
|
||||
* //その他任意のストリームからの読み込みも可能
|
||||
* $stream = fopen("http://127.0.0.1/test.bmp");
|
||||
* $image = GdBmp::loadFromStream($stream);
|
||||
* //自動判定されるのでこれでもいい
|
||||
* //$image = imagecreatefrombmp($stream);
|
||||
* fclose($stream);
|
||||
* imagedestroy($image);
|
||||
*
|
||||
* 対応フォーマット
|
||||
* 1bit
|
||||
* 4bit
|
||||
* 4bitRLE
|
||||
* 8bit
|
||||
* 8bitRLE
|
||||
* 16bit(任意のビットフィールド)
|
||||
* 24bit
|
||||
* 32bit(任意のビットフィールド)
|
||||
* BITMAPINFOHEADER の biCompression が BI_PNG / BI_JPEG の画像
|
||||
* すべての形式でトップダウン/ボトムアップの両方をサポート
|
||||
* 特殊なビットフィールドでもビットフィールドデータが正常なら読み込み可能
|
||||
*
|
||||
* 以下のものは非対応
|
||||
* BITMAPV4HEADER と BITMAPV5HEADER に含まれる色空間に関する様々な機能
|
||||
* @param $filename_or_stream_or_binary
|
||||
* @return bool|resource
|
||||
*/
|
||||
|
||||
if (! function_exists('imagecreatefrombmp')) {
|
||||
function imagecreatefrombmp($filename_or_stream_or_binary){
|
||||
return elFinderLibGdBmp::load($filename_or_stream_or_binary);
|
||||
}
|
||||
}
|
||||
|
||||
class elFinderLibGdBmp{
|
||||
public static function load($filename_or_stream_or_binary){
|
||||
if (is_resource($filename_or_stream_or_binary)){
|
||||
return self::loadFromStream($filename_or_stream_or_binary);
|
||||
} else if (is_string($filename_or_stream_or_binary) && strlen($filename_or_stream_or_binary) >= 26){
|
||||
$bfh = unpack("vtype/Vsize", $filename_or_stream_or_binary);
|
||||
if ($bfh["type"] == 0x4d42 && ($bfh["size"] == 0 || $bfh["size"] == strlen($filename_or_stream_or_binary))){
|
||||
return self::loadFromString($filename_or_stream_or_binary);
|
||||
}
|
||||
}
|
||||
return self::loadFromFile($filename_or_stream_or_binary);
|
||||
}
|
||||
public static function loadFromFile($filename){
|
||||
$fp = fopen($filename, "rb");
|
||||
if ($fp === false){
|
||||
return false;
|
||||
}
|
||||
|
||||
$bmp = self::loadFromStream($fp);
|
||||
|
||||
fclose($fp);
|
||||
return $bmp;
|
||||
}
|
||||
|
||||
public static function loadFromString($str){
|
||||
//data scheme より古いバージョンから対応しているようなので php://memory を使う
|
||||
$fp = fopen("php://memory", "r+b");
|
||||
if ($fp === false){
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fwrite($fp, $str) != strlen($str)){
|
||||
fclose($fp);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fseek($fp, 0) === -1){
|
||||
fclose($fp);
|
||||
return false;
|
||||
}
|
||||
|
||||
$bmp = self::loadFromStream($fp);
|
||||
|
||||
fclose($fp);
|
||||
return $bmp;
|
||||
}
|
||||
|
||||
public static function loadFromStream($stream){
|
||||
$buf = fread($stream, 14); //2+4+2+2+4
|
||||
if ($buf === false){
|
||||
return false;
|
||||
}
|
||||
|
||||
//シグネチャチェック
|
||||
if ($buf[0] != 'B' || $buf[1] != 'M'){
|
||||
return false;
|
||||
}
|
||||
|
||||
$bitmap_file_header = unpack(
|
||||
//BITMAPFILEHEADER構造体
|
||||
"vtype/".
|
||||
"Vsize/".
|
||||
"vreserved1/".
|
||||
"vreserved2/".
|
||||
"Voffbits", $buf
|
||||
);
|
||||
|
||||
return self::loadFromStreamAndFileHeader($stream, $bitmap_file_header);
|
||||
}
|
||||
|
||||
public static function loadFromStreamAndFileHeader($stream, array $bitmap_file_header){
|
||||
if ($bitmap_file_header["type"] != 0x4d42){
|
||||
return false;
|
||||
}
|
||||
|
||||
//情報ヘッダサイズを元に形式を区別して読み込み
|
||||
$buf = fread($stream, 4);
|
||||
if ($buf === false){
|
||||
return false;
|
||||
}
|
||||
list(,$header_size) = unpack("V", $buf);
|
||||
|
||||
|
||||
if ($header_size == 12){
|
||||
$buf = fread($stream, $header_size - 4);
|
||||
if ($buf === false){
|
||||
return false;
|
||||
}
|
||||
|
||||
extract(unpack(
|
||||
//BITMAPCOREHEADER構造体 - OS/2 Bitmap
|
||||
"vwidth/".
|
||||
"vheight/".
|
||||
"vplanes/".
|
||||
"vbit_count", $buf
|
||||
));
|
||||
//飛んでこない分は 0 で初期化しておく
|
||||
$clr_used = $clr_important = $alpha_mask = $compression = 0;
|
||||
|
||||
//マスク類は初期化されないのでここで割り当てておく
|
||||
$red_mask = 0x00ff0000;
|
||||
$green_mask = 0x0000ff00;
|
||||
$blue_mask = 0x000000ff;
|
||||
} else if (124 < $header_size || $header_size < 40) {
|
||||
//未知の形式
|
||||
return false;
|
||||
} else {
|
||||
//この時点で36バイト読めることまではわかっている
|
||||
$buf = fread($stream, 36); //既に読んだ部分は除外しつつBITMAPINFOHEADERのサイズだけ読む
|
||||
if ($buf === false){
|
||||
return false;
|
||||
}
|
||||
|
||||
//BITMAPINFOHEADER構造体 - Windows Bitmap
|
||||
extract(unpack(
|
||||
"Vwidth/".
|
||||
"Vheight/".
|
||||
"vplanes/".
|
||||
"vbit_count/".
|
||||
"Vcompression/".
|
||||
"Vsize_image/".
|
||||
"Vx_pels_per_meter/".
|
||||
"Vy_pels_per_meter/".
|
||||
"Vclr_used/".
|
||||
"Vclr_important", $buf
|
||||
));
|
||||
//負の整数を受け取る可能性があるものは自前で変換する
|
||||
if ($width & 0x80000000){ $width = -(~$width & 0xffffffff) - 1; }
|
||||
if ($height & 0x80000000){ $height = -(~$height & 0xffffffff) - 1; }
|
||||
if ($x_pels_per_meter & 0x80000000){ $x_pels_per_meter = -(~$x_pels_per_meter & 0xffffffff) - 1; }
|
||||
if ($y_pels_per_meter & 0x80000000){ $y_pels_per_meter = -(~$y_pels_per_meter & 0xffffffff) - 1; }
|
||||
|
||||
//ファイルによっては BITMAPINFOHEADER のサイズがおかしい(書き込み間違い?)ケースがある
|
||||
//自分でファイルサイズを元に逆算することで回避できることもあるので再計算できそうなら正当性を調べる
|
||||
//シークできないストリームの場合全体のファイルサイズは取得できないので、$bitmap_file_headerにサイズ申告がなければやらない
|
||||
if ($bitmap_file_header["size"] != 0){
|
||||
$colorsize = $bit_count == 1 || $bit_count == 4 || $bit_count == 8 ? ($clr_used ? $clr_used : pow(2, $bit_count))<<2 : 0;
|
||||
$bodysize = $size_image ? $size_image : ((($width * $bit_count + 31) >> 3) & ~3) * abs($height);
|
||||
$calcsize = $bitmap_file_header["size"] - $bodysize - $colorsize - 14;
|
||||
|
||||
//本来であれば一致するはずなのに合わない時は、値がおかしくなさそうなら(BITMAPV5HEADERの範囲内なら)計算して求めた値を採用する
|
||||
if ($header_size < $calcsize && 40 <= $header_size && $header_size <= 124){
|
||||
$header_size = $calcsize;
|
||||
}
|
||||
}
|
||||
|
||||
//BITMAPV4HEADER や BITMAPV5HEADER の場合まだ読むべきデータが残っている可能性がある
|
||||
if ($header_size - 40 > 0){
|
||||
$buf = fread($stream, $header_size - 40);
|
||||
if ($buf === false){
|
||||
return false;
|
||||
}
|
||||
|
||||
extract(unpack(
|
||||
//BITMAPV4HEADER構造体(Windows95以降)
|
||||
//BITMAPV5HEADER構造体(Windows98/2000以降)
|
||||
"Vred_mask/".
|
||||
"Vgreen_mask/".
|
||||
"Vblue_mask/".
|
||||
"Valpha_mask", $buf . str_repeat("\x00", 120)
|
||||
));
|
||||
} else {
|
||||
$alpha_mask = $red_mask = $green_mask = $blue_mask = 0;
|
||||
}
|
||||
|
||||
//パレットがないがカラーマスクもない時
|
||||
if (
|
||||
($bit_count == 16 || $bit_count == 24 || $bit_count == 32)&&
|
||||
$compression == 0 &&
|
||||
$red_mask == 0 && $green_mask == 0 && $blue_mask == 0
|
||||
){
|
||||
//もしカラーマスクを所持していない場合は
|
||||
//規定のカラーマスクを適用する
|
||||
switch($bit_count){
|
||||
case 16:
|
||||
$red_mask = 0x7c00;
|
||||
$green_mask = 0x03e0;
|
||||
$blue_mask = 0x001f;
|
||||
break;
|
||||
case 24:
|
||||
case 32:
|
||||
$red_mask = 0x00ff0000;
|
||||
$green_mask = 0x0000ff00;
|
||||
$blue_mask = 0x000000ff;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
($width == 0)||
|
||||
($height == 0)||
|
||||
($planes != 1)||
|
||||
(($alpha_mask & $red_mask ) != 0)||
|
||||
(($alpha_mask & $green_mask) != 0)||
|
||||
(($alpha_mask & $blue_mask ) != 0)||
|
||||
(($red_mask & $green_mask) != 0)||
|
||||
(($red_mask & $blue_mask ) != 0)||
|
||||
(($green_mask & $blue_mask ) != 0)
|
||||
){
|
||||
//不正な画像
|
||||
return false;
|
||||
}
|
||||
|
||||
//BI_JPEG と BI_PNG の場合は jpeg/png がそのまま入ってるだけなのでそのまま取り出してデコードする
|
||||
if ($compression == 4 || $compression == 5){
|
||||
$buf = stream_get_contents($stream, $size_image);
|
||||
if ($buf === false){
|
||||
return false;
|
||||
}
|
||||
return imagecreatefromstring($buf);
|
||||
}
|
||||
|
||||
//画像本体の読み出し
|
||||
//1行のバイト数
|
||||
$line_bytes = (($width * $bit_count + 31) >> 3) & ~3;
|
||||
//全体の行数
|
||||
$lines = abs($height);
|
||||
//y軸進行量(ボトムアップかトップダウンか)
|
||||
$y = $height > 0 ? $lines-1 : 0;
|
||||
$line_step = $height > 0 ? -1 : 1;
|
||||
|
||||
//256色以下の画像か?
|
||||
if ($bit_count == 1 || $bit_count == 4 || $bit_count == 8){
|
||||
$img = imagecreate($width, $lines);
|
||||
|
||||
//画像データの前にパレットデータがあるのでパレットを作成する
|
||||
$palette_size = $header_size == 12 ? 3 : 4; //OS/2形式の場合は x に相当する箇所のデータは最初から確保されていない
|
||||
$colors = $clr_used ? $clr_used : pow(2, $bit_count); //色数
|
||||
$palette = array();
|
||||
for($i = 0; $i < $colors; ++$i){
|
||||
$buf = fread($stream, $palette_size);
|
||||
if ($buf === false){
|
||||
imagedestroy($img);
|
||||
return false;
|
||||
}
|
||||
extract(unpack("Cb/Cg/Cr/Cx", $buf . "\x00"));
|
||||
$palette[] = imagecolorallocate($img, $r, $g, $b);
|
||||
}
|
||||
|
||||
$shift_base = 8 - $bit_count;
|
||||
$mask = ((1 << $bit_count) - 1) << $shift_base;
|
||||
|
||||
//圧縮されている場合とされていない場合でデコード処理が大きく変わる
|
||||
if ($compression == 1 || $compression == 2){
|
||||
$x = 0;
|
||||
$qrt_mod2 = $bit_count >> 2 & 1;
|
||||
for(;;){
|
||||
//もし描写先が範囲外になっている場合デコード処理がおかしくなっているので抜ける
|
||||
//変なデータが渡されたとしても最悪なケースで255回程度の無駄なので目を瞑る
|
||||
if ($x < -1 || $x > $width || $y < -1 || $y > $height){
|
||||
imagedestroy($img);
|
||||
return false;
|
||||
}
|
||||
$buf = fread($stream, 1);
|
||||
if ($buf === false){
|
||||
imagedestroy($img);
|
||||
return false;
|
||||
}
|
||||
switch($buf){
|
||||
case "\x00":
|
||||
$buf = fread($stream, 1);
|
||||
if ($buf === false){
|
||||
imagedestroy($img);
|
||||
return false;
|
||||
}
|
||||
switch($buf){
|
||||
case "\x00": //EOL
|
||||
$y += $line_step;
|
||||
$x = 0;
|
||||
break;
|
||||
case "\x01": //EOB
|
||||
$y = 0;
|
||||
$x = 0;
|
||||
break 3;
|
||||
case "\x02": //MOV
|
||||
$buf = fread($stream, 2);
|
||||
if ($buf === false){
|
||||
imagedestroy($img);
|
||||
return false;
|
||||
}
|
||||
list(,$xx, $yy) = unpack("C2", $buf);
|
||||
$x += $xx;
|
||||
$y += $yy * $line_step;
|
||||
break;
|
||||
default: //ABS
|
||||
list(,$pixels) = unpack("C", $buf);
|
||||
$bytes = ($pixels >> $qrt_mod2) + ($pixels & $qrt_mod2);
|
||||
$buf = fread($stream, ($bytes + 1) & ~1);
|
||||
if ($buf === false){
|
||||
imagedestroy($img);
|
||||
return false;
|
||||
}
|
||||
for ($i = 0, $pos = 0; $i < $pixels; ++$i, ++$x, $pos += $bit_count){
|
||||
list(,$c) = unpack("C", $buf[$pos >> 3]);
|
||||
$b = $pos & 0x07;
|
||||
imagesetpixel($img, $x, $y, $palette[($c & ($mask >> $b)) >> ($shift_base - $b)]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
$buf2 = fread($stream, 1);
|
||||
if ($buf2 === false){
|
||||
imagedestroy($img);
|
||||
return false;
|
||||
}
|
||||
list(,$size, $c) = unpack("C2", $buf . $buf2);
|
||||
for($i = 0, $pos = 0; $i < $size; ++$i, ++$x, $pos += $bit_count){
|
||||
$b = $pos & 0x07;
|
||||
imagesetpixel($img, $x, $y, $palette[($c & ($mask >> $b)) >> ($shift_base - $b)]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for ($line = 0; $line < $lines; ++$line, $y += $line_step){
|
||||
$buf = fread($stream, $line_bytes);
|
||||
if ($buf === false){
|
||||
imagedestroy($img);
|
||||
return false;
|
||||
}
|
||||
|
||||
$pos = 0;
|
||||
for ($x = 0; $x < $width; ++$x, $pos += $bit_count){
|
||||
list(,$c) = unpack("C", $buf[$pos >> 3]);
|
||||
$b = $pos & 0x7;
|
||||
imagesetpixel($img, $x, $y, $palette[($c & ($mask >> $b)) >> ($shift_base - $b)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$img = imagecreatetruecolor($width, $lines);
|
||||
imagealphablending($img, false);
|
||||
if ($alpha_mask)
|
||||
{
|
||||
//αデータがあるので透過情報も保存できるように
|
||||
imagesavealpha($img, true);
|
||||
}
|
||||
|
||||
//x軸進行量
|
||||
$pixel_step = $bit_count >> 3;
|
||||
$alpha_max = $alpha_mask ? 0x7f : 0x00;
|
||||
$alpha_mask_r = $alpha_mask ? 1/$alpha_mask : 1;
|
||||
$red_mask_r = $red_mask ? 1/$red_mask : 1;
|
||||
$green_mask_r = $green_mask ? 1/$green_mask : 1;
|
||||
$blue_mask_r = $blue_mask ? 1/$blue_mask : 1;
|
||||
|
||||
for ($line = 0; $line < $lines; ++$line, $y += $line_step){
|
||||
$buf = fread($stream, $line_bytes);
|
||||
if ($buf === false){
|
||||
imagedestroy($img);
|
||||
return false;
|
||||
}
|
||||
|
||||
$pos = 0;
|
||||
for ($x = 0; $x < $width; ++$x, $pos += $pixel_step){
|
||||
list(,$c) = unpack("V", substr($buf, $pos, $pixel_step). "\x00\x00");
|
||||
$a_masked = $c & $alpha_mask;
|
||||
$r_masked = $c & $red_mask;
|
||||
$g_masked = $c & $green_mask;
|
||||
$b_masked = $c & $blue_mask;
|
||||
$a = $alpha_max - ((($a_masked<<7) - $a_masked) * $alpha_mask_r);
|
||||
$r = (($r_masked<<8) - $r_masked) * $red_mask_r;
|
||||
$g = (($g_masked<<8) - $g_masked) * $green_mask_r;
|
||||
$b = (($b_masked<<8) - $b_masked) * $blue_mask_r;
|
||||
imagesetpixel($img, $x, $y, ($a<<24)|($r<<16)|($g<<8)|$b);
|
||||
}
|
||||
}
|
||||
imagealphablending($img, true); //デフォルト値に戻しておく
|
||||
}
|
||||
return $img;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,781 @@
|
||||
# This file maps Internet media types to unique file extension(s).
|
||||
# Although created for httpd, this file is used by many software systems
|
||||
# and has been placed in the public domain for unlimited redisribution.
|
||||
#
|
||||
# The table below contains both registered and (common) unregistered types.
|
||||
# A type that has no unique extension can be ignored -- they are listed
|
||||
# here to guide configurations toward known types and to make it easier to
|
||||
# identify "new" types. File extensions are also commonly used to indicate
|
||||
# content languages and encodings, so choose them carefully.
|
||||
#
|
||||
# Internet media types should be registered as described in RFC 4288.
|
||||
# The registry is at <http://www.iana.org/assignments/media-types/>.
|
||||
#
|
||||
# MIME type (lowercased) Extensions
|
||||
application/andrew-inset ez
|
||||
application/applixware aw
|
||||
application/atom+xml atom
|
||||
application/atomcat+xml atomcat
|
||||
application/atomsvc+xml atomsvc
|
||||
application/ccxml+xml ccxml
|
||||
application/cdmi-capability cdmia
|
||||
application/cdmi-container cdmic
|
||||
application/cdmi-domain cdmid
|
||||
application/cdmi-object cdmio
|
||||
application/cdmi-queue cdmiq
|
||||
application/cu-seeme cu
|
||||
application/davmount+xml davmount
|
||||
application/docbook+xml dbk
|
||||
application/dssc+der dssc
|
||||
application/dssc+xml xdssc
|
||||
application/ecmascript ecma
|
||||
application/emma+xml emma
|
||||
application/epub+zip epub
|
||||
application/exi exi
|
||||
application/font-tdpfr pfr
|
||||
application/gml+xml gml
|
||||
application/gpx+xml gpx
|
||||
application/gxf gxf
|
||||
application/hyperstudio stk
|
||||
application/inkml+xml ink inkml
|
||||
application/ipfix ipfix
|
||||
application/java-archive jar
|
||||
application/java-serialized-object ser
|
||||
application/java-vm class
|
||||
application/javascript js
|
||||
application/json json
|
||||
application/jsonml+json jsonml
|
||||
application/lost+xml lostxml
|
||||
application/mac-binhex40 hqx
|
||||
application/mac-compactpro cpt
|
||||
application/mads+xml mads
|
||||
application/marc mrc
|
||||
application/marcxml+xml mrcx
|
||||
application/mathematica ma nb mb
|
||||
application/mathml+xml mathml
|
||||
application/mbox mbox
|
||||
application/mediaservercontrol+xml mscml
|
||||
application/metalink+xml metalink
|
||||
application/metalink4+xml meta4
|
||||
application/mets+xml mets
|
||||
application/mods+xml mods
|
||||
application/mp21 m21 mp21
|
||||
application/mp4 mp4s
|
||||
application/msword doc dot
|
||||
application/mxf mxf
|
||||
application/octet-stream bin dms lrf mar so dist distz pkg bpk dump elc deploy
|
||||
application/oda oda
|
||||
application/oebps-package+xml opf
|
||||
application/ogg ogx
|
||||
application/omdoc+xml omdoc
|
||||
application/onenote onetoc onetoc2 onetmp onepkg
|
||||
application/oxps oxps
|
||||
application/patch-ops-error+xml xer
|
||||
application/pdf pdf
|
||||
application/pgp-encrypted pgp
|
||||
application/pgp-signature asc sig
|
||||
application/pics-rules prf
|
||||
application/pkcs10 p10
|
||||
application/pkcs7-mime p7m p7c
|
||||
application/pkcs7-signature p7s
|
||||
application/pkcs8 p8
|
||||
application/pkix-attr-cert ac
|
||||
application/pkix-cert cer
|
||||
application/pkix-crl crl
|
||||
application/pkix-pkipath pkipath
|
||||
application/pkixcmp pki
|
||||
application/pls+xml pls
|
||||
application/postscript ai eps ps
|
||||
application/prs.cww cww
|
||||
application/pskc+xml pskcxml
|
||||
application/rdf+xml rdf
|
||||
application/reginfo+xml rif
|
||||
application/relax-ng-compact-syntax rnc
|
||||
application/resource-lists+xml rl
|
||||
application/resource-lists-diff+xml rld
|
||||
application/rls-services+xml rs
|
||||
application/rpki-ghostbusters gbr
|
||||
application/rpki-manifest mft
|
||||
application/rpki-roa roa
|
||||
application/rsd+xml rsd
|
||||
application/rss+xml rss
|
||||
application/rtf rtf
|
||||
application/sbml+xml sbml
|
||||
application/scvp-cv-request scq
|
||||
application/scvp-cv-response scs
|
||||
application/scvp-vp-request spq
|
||||
application/scvp-vp-response spp
|
||||
application/sdp sdp
|
||||
application/set-payment-initiation setpay
|
||||
application/set-registration-initiation setreg
|
||||
application/shf+xml shf
|
||||
application/smil+xml smi smil
|
||||
application/sparql-query rq
|
||||
application/sparql-results+xml srx
|
||||
application/srgs gram
|
||||
application/srgs+xml grxml
|
||||
application/sru+xml sru
|
||||
application/ssdl+xml ssdl
|
||||
application/ssml+xml ssml
|
||||
application/tei+xml tei teicorpus
|
||||
application/thraud+xml tfi
|
||||
application/timestamped-data tsd
|
||||
application/vnd.3gpp.pic-bw-large plb
|
||||
application/vnd.3gpp.pic-bw-small psb
|
||||
application/vnd.3gpp.pic-bw-var pvb
|
||||
application/vnd.3gpp2.tcap tcap
|
||||
application/vnd.3m.post-it-notes pwn
|
||||
application/vnd.accpac.simply.aso aso
|
||||
application/vnd.accpac.simply.imp imp
|
||||
application/vnd.acucobol acu
|
||||
application/vnd.acucorp atc acutc
|
||||
application/vnd.adobe.air-application-installer-package+zip air
|
||||
application/vnd.adobe.formscentral.fcdt fcdt
|
||||
application/vnd.adobe.fxp fxp fxpl
|
||||
application/vnd.adobe.xdp+xml xdp
|
||||
application/vnd.adobe.xfdf xfdf
|
||||
application/vnd.ahead.space ahead
|
||||
application/vnd.airzip.filesecure.azf azf
|
||||
application/vnd.airzip.filesecure.azs azs
|
||||
application/vnd.amazon.ebook azw
|
||||
application/vnd.americandynamics.acc acc
|
||||
application/vnd.amiga.ami ami
|
||||
application/vnd.android.package-archive apk
|
||||
application/vnd.anser-web-certificate-issue-initiation cii
|
||||
application/vnd.anser-web-funds-transfer-initiation fti
|
||||
application/vnd.antix.game-component atx
|
||||
application/vnd.apple.installer+xml mpkg
|
||||
application/vnd.apple.mpegurl m3u8
|
||||
application/vnd.aristanetworks.swi swi
|
||||
application/vnd.astraea-software.iota iota
|
||||
application/vnd.audiograph aep
|
||||
application/vnd.blueice.multipass mpm
|
||||
application/vnd.bmi bmi
|
||||
application/vnd.businessobjects rep
|
||||
application/vnd.chemdraw+xml cdxml
|
||||
application/vnd.chipnuts.karaoke-mmd mmd
|
||||
application/vnd.cinderella cdy
|
||||
application/vnd.claymore cla
|
||||
application/vnd.cloanto.rp9 rp9
|
||||
application/vnd.clonk.c4group c4g c4d c4f c4p c4u
|
||||
application/vnd.cluetrust.cartomobile-config c11amc
|
||||
application/vnd.cluetrust.cartomobile-config-pkg c11amz
|
||||
application/vnd.commonspace csp
|
||||
application/vnd.contact.cmsg cdbcmsg
|
||||
application/vnd.cosmocaller cmc
|
||||
application/vnd.crick.clicker clkx
|
||||
application/vnd.crick.clicker.keyboard clkk
|
||||
application/vnd.crick.clicker.palette clkp
|
||||
application/vnd.crick.clicker.template clkt
|
||||
application/vnd.crick.clicker.wordbank clkw
|
||||
application/vnd.criticaltools.wbs+xml wbs
|
||||
application/vnd.ctc-posml pml
|
||||
application/vnd.cups-ppd ppd
|
||||
application/vnd.curl.car car
|
||||
application/vnd.curl.pcurl pcurl
|
||||
application/vnd.dart dart
|
||||
application/vnd.data-vision.rdz rdz
|
||||
application/vnd.dece.data uvf uvvf uvd uvvd
|
||||
application/vnd.dece.ttml+xml uvt uvvt
|
||||
application/vnd.dece.unspecified uvx uvvx
|
||||
application/vnd.dece.zip uvz uvvz
|
||||
application/vnd.denovo.fcselayout-link fe_launch
|
||||
application/vnd.dna dna
|
||||
application/vnd.dolby.mlp mlp
|
||||
application/vnd.dpgraph dpg
|
||||
application/vnd.dreamfactory dfac
|
||||
application/vnd.ds-keypoint kpxx
|
||||
application/vnd.dvb.ait ait
|
||||
application/vnd.dvb.service svc
|
||||
application/vnd.dynageo geo
|
||||
application/vnd.ecowin.chart mag
|
||||
application/vnd.enliven nml
|
||||
application/vnd.epson.esf esf
|
||||
application/vnd.epson.msf msf
|
||||
application/vnd.epson.quickanime qam
|
||||
application/vnd.epson.salt slt
|
||||
application/vnd.epson.ssf ssf
|
||||
application/vnd.eszigno3+xml es3 et3
|
||||
application/vnd.ezpix-album ez2
|
||||
application/vnd.ezpix-package ez3
|
||||
application/vnd.fdf fdf
|
||||
application/vnd.fdsn.mseed mseed
|
||||
application/vnd.fdsn.seed seed dataless
|
||||
application/vnd.flographit gph
|
||||
application/vnd.fluxtime.clip ftc
|
||||
application/vnd.framemaker fm frame maker book
|
||||
application/vnd.frogans.fnc fnc
|
||||
application/vnd.frogans.ltf ltf
|
||||
application/vnd.fsc.weblaunch fsc
|
||||
application/vnd.fujitsu.oasys oas
|
||||
application/vnd.fujitsu.oasys2 oa2
|
||||
application/vnd.fujitsu.oasys3 oa3
|
||||
application/vnd.fujitsu.oasysgp fg5
|
||||
application/vnd.fujitsu.oasysprs bh2
|
||||
application/vnd.fujixerox.ddd ddd
|
||||
application/vnd.fujixerox.docuworks xdw
|
||||
application/vnd.fujixerox.docuworks.binder xbd
|
||||
application/vnd.fuzzysheet fzs
|
||||
application/vnd.genomatix.tuxedo txd
|
||||
application/vnd.geogebra.file ggb
|
||||
application/vnd.geogebra.tool ggt
|
||||
application/vnd.geometry-explorer gex gre
|
||||
application/vnd.geonext gxt
|
||||
application/vnd.geoplan g2w
|
||||
application/vnd.geospace g3w
|
||||
application/vnd.gmx gmx
|
||||
application/vnd.google-earth.kml+xml kml
|
||||
application/vnd.google-earth.kmz kmz
|
||||
application/vnd.grafeq gqf gqs
|
||||
application/vnd.groove-account gac
|
||||
application/vnd.groove-help ghf
|
||||
application/vnd.groove-identity-message gim
|
||||
application/vnd.groove-injector grv
|
||||
application/vnd.groove-tool-message gtm
|
||||
application/vnd.groove-tool-template tpl
|
||||
application/vnd.groove-vcard vcg
|
||||
application/vnd.hal+xml hal
|
||||
application/vnd.handheld-entertainment+xml zmm
|
||||
application/vnd.hbci hbci
|
||||
application/vnd.hhe.lesson-player les
|
||||
application/vnd.hp-hpgl hpgl
|
||||
application/vnd.hp-hpid hpid
|
||||
application/vnd.hp-hps hps
|
||||
application/vnd.hp-jlyt jlt
|
||||
application/vnd.hp-pcl pcl
|
||||
application/vnd.hp-pclxl pclxl
|
||||
application/vnd.hydrostatix.sof-data sfd-hdstx
|
||||
application/vnd.ibm.minipay mpy
|
||||
application/vnd.ibm.modcap afp listafp list3820
|
||||
application/vnd.ibm.rights-management irm
|
||||
application/vnd.ibm.secure-container sc
|
||||
application/vnd.iccprofile icc icm
|
||||
application/vnd.igloader igl
|
||||
application/vnd.immervision-ivp ivp
|
||||
application/vnd.immervision-ivu ivu
|
||||
application/vnd.insors.igm igm
|
||||
application/vnd.intercon.formnet xpw xpx
|
||||
application/vnd.intergeo i2g
|
||||
application/vnd.intu.qbo qbo
|
||||
application/vnd.intu.qfx qfx
|
||||
application/vnd.ipunplugged.rcprofile rcprofile
|
||||
application/vnd.irepository.package+xml irp
|
||||
application/vnd.is-xpr xpr
|
||||
application/vnd.isac.fcs fcs
|
||||
application/vnd.jam jam
|
||||
application/vnd.jcp.javame.midlet-rms rms
|
||||
application/vnd.jisp jisp
|
||||
application/vnd.joost.joda-archive joda
|
||||
application/vnd.kahootz ktz ktr
|
||||
application/vnd.kde.karbon karbon
|
||||
application/vnd.kde.kchart chrt
|
||||
application/vnd.kde.kformula kfo
|
||||
application/vnd.kde.kivio flw
|
||||
application/vnd.kde.kontour kon
|
||||
application/vnd.kde.kpresenter kpr kpt
|
||||
application/vnd.kde.kspread ksp
|
||||
application/vnd.kde.kword kwd kwt
|
||||
application/vnd.kenameaapp htke
|
||||
application/vnd.kidspiration kia
|
||||
application/vnd.kinar kne knp
|
||||
application/vnd.koan skp skd skt skm
|
||||
application/vnd.kodak-descriptor sse
|
||||
application/vnd.las.las+xml lasxml
|
||||
application/vnd.llamagraphics.life-balance.desktop lbd
|
||||
application/vnd.llamagraphics.life-balance.exchange+xml lbe
|
||||
application/vnd.lotus-1-2-3 123
|
||||
application/vnd.lotus-approach apr
|
||||
application/vnd.lotus-freelance pre
|
||||
application/vnd.lotus-notes nsf
|
||||
application/vnd.lotus-organizer org
|
||||
application/vnd.lotus-screencam scm
|
||||
application/vnd.lotus-wordpro lwp
|
||||
application/vnd.macports.portpkg portpkg
|
||||
application/vnd.mcd mcd
|
||||
application/vnd.medcalcdata mc1
|
||||
application/vnd.mediastation.cdkey cdkey
|
||||
application/vnd.mfer mwf
|
||||
application/vnd.mfmp mfm
|
||||
application/vnd.micrografx.flo flo
|
||||
application/vnd.micrografx.igx igx
|
||||
application/vnd.mif mif
|
||||
application/vnd.mobius.daf daf
|
||||
application/vnd.mobius.dis dis
|
||||
application/vnd.mobius.mbk mbk
|
||||
application/vnd.mobius.mqy mqy
|
||||
application/vnd.mobius.msl msl
|
||||
application/vnd.mobius.plc plc
|
||||
application/vnd.mobius.txf txf
|
||||
application/vnd.mophun.application mpn
|
||||
application/vnd.mophun.certificate mpc
|
||||
application/vnd.mozilla.xul+xml xul
|
||||
application/vnd.ms-artgalry cil
|
||||
application/vnd.ms-cab-compressed cab
|
||||
application/vnd.ms-excel xls xlm xla xlc xlt xlw
|
||||
application/vnd.ms-excel.addin.macroenabled.12 xlam
|
||||
application/vnd.ms-excel.sheet.binary.macroenabled.12 xlsb
|
||||
application/vnd.ms-excel.sheet.macroenabled.12 xlsm
|
||||
application/vnd.ms-excel.template.macroenabled.12 xltm
|
||||
application/vnd.ms-fontobject eot
|
||||
application/vnd.ms-htmlhelp chm
|
||||
application/vnd.ms-ims ims
|
||||
application/vnd.ms-lrm lrm
|
||||
application/vnd.ms-officetheme thmx
|
||||
application/vnd.ms-pki.seccat cat
|
||||
application/vnd.ms-pki.stl stl
|
||||
application/vnd.ms-powerpoint ppt pps pot
|
||||
application/vnd.ms-powerpoint.addin.macroenabled.12 ppam
|
||||
application/vnd.ms-powerpoint.presentation.macroenabled.12 pptm
|
||||
application/vnd.ms-powerpoint.slide.macroenabled.12 sldm
|
||||
application/vnd.ms-powerpoint.slideshow.macroenabled.12 ppsm
|
||||
application/vnd.ms-powerpoint.template.macroenabled.12 potm
|
||||
application/vnd.ms-project mpp mpt
|
||||
application/vnd.ms-word.document.macroenabled.12 docm
|
||||
application/vnd.ms-word.template.macroenabled.12 dotm
|
||||
application/vnd.ms-works wps wks wcm wdb
|
||||
application/vnd.ms-wpl wpl
|
||||
application/vnd.ms-xpsdocument xps
|
||||
application/vnd.mseq mseq
|
||||
application/vnd.musician mus
|
||||
application/vnd.muvee.style msty
|
||||
application/vnd.mynfc taglet
|
||||
application/vnd.neurolanguage.nlu nlu
|
||||
application/vnd.nitf ntf nitf
|
||||
application/vnd.noblenet-directory nnd
|
||||
application/vnd.noblenet-sealer nns
|
||||
application/vnd.noblenet-web nnw
|
||||
application/vnd.nokia.n-gage.data ngdat
|
||||
application/vnd.nokia.n-gage.symbian.install n-gage
|
||||
application/vnd.nokia.radio-preset rpst
|
||||
application/vnd.nokia.radio-presets rpss
|
||||
application/vnd.novadigm.edm edm
|
||||
application/vnd.novadigm.edx edx
|
||||
application/vnd.novadigm.ext ext
|
||||
application/vnd.oasis.opendocument.chart odc
|
||||
application/vnd.oasis.opendocument.chart-template otc
|
||||
application/vnd.oasis.opendocument.database odb
|
||||
application/vnd.oasis.opendocument.formula odf
|
||||
application/vnd.oasis.opendocument.formula-template odft
|
||||
application/vnd.oasis.opendocument.graphics odg
|
||||
application/vnd.oasis.opendocument.graphics-template otg
|
||||
application/vnd.oasis.opendocument.image odi
|
||||
application/vnd.oasis.opendocument.image-template oti
|
||||
application/vnd.oasis.opendocument.presentation odp
|
||||
application/vnd.oasis.opendocument.presentation-template otp
|
||||
application/vnd.oasis.opendocument.spreadsheet ods
|
||||
application/vnd.oasis.opendocument.spreadsheet-template ots
|
||||
application/vnd.oasis.opendocument.text odt
|
||||
application/vnd.oasis.opendocument.text-master odm
|
||||
application/vnd.oasis.opendocument.text-template ott
|
||||
application/vnd.oasis.opendocument.text-web oth
|
||||
application/vnd.olpc-sugar xo
|
||||
application/vnd.oma.dd2+xml dd2
|
||||
application/vnd.openofficeorg.extension oxt
|
||||
application/vnd.openxmlformats-officedocument.presentationml.presentation pptx
|
||||
application/vnd.openxmlformats-officedocument.presentationml.slide sldx
|
||||
application/vnd.openxmlformats-officedocument.presentationml.slideshow ppsx
|
||||
application/vnd.openxmlformats-officedocument.presentationml.template potx
|
||||
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx
|
||||
application/vnd.openxmlformats-officedocument.spreadsheetml.template xltx
|
||||
application/vnd.openxmlformats-officedocument.wordprocessingml.document docx
|
||||
application/vnd.openxmlformats-officedocument.wordprocessingml.template dotx
|
||||
application/vnd.osgeo.mapguide.package mgp
|
||||
application/vnd.osgi.dp dp
|
||||
application/vnd.osgi.subsystem esa
|
||||
application/vnd.palm pdb pqa oprc
|
||||
application/vnd.pawaafile paw
|
||||
application/vnd.pg.format str
|
||||
application/vnd.pg.osasli ei6
|
||||
application/vnd.picsel efif
|
||||
application/vnd.pmi.widget wg
|
||||
application/vnd.pocketlearn plf
|
||||
application/vnd.powerbuilder6 pbd
|
||||
application/vnd.previewsystems.box box
|
||||
application/vnd.proteus.magazine mgz
|
||||
application/vnd.publishare-delta-tree qps
|
||||
application/vnd.pvi.ptid1 ptid
|
||||
application/vnd.quark.quarkxpress qxd qxt qwd qwt qxl qxb
|
||||
application/vnd.realvnc.bed bed
|
||||
application/vnd.recordare.musicxml mxl
|
||||
application/vnd.recordare.musicxml+xml musicxml
|
||||
application/vnd.rig.cryptonote cryptonote
|
||||
application/vnd.rim.cod cod
|
||||
application/vnd.rn-realmedia rm
|
||||
application/vnd.rn-realmedia-vbr rmvb
|
||||
application/vnd.route66.link66+xml link66
|
||||
application/vnd.sailingtracker.track st
|
||||
application/vnd.seemail see
|
||||
application/vnd.sema sema
|
||||
application/vnd.semd semd
|
||||
application/vnd.semf semf
|
||||
application/vnd.shana.informed.formdata ifm
|
||||
application/vnd.shana.informed.formtemplate itp
|
||||
application/vnd.shana.informed.interchange iif
|
||||
application/vnd.shana.informed.package ipk
|
||||
application/vnd.simtech-mindmapper twd twds
|
||||
application/vnd.smaf mmf
|
||||
application/vnd.smart.teacher teacher
|
||||
application/vnd.solent.sdkm+xml sdkm sdkd
|
||||
application/vnd.spotfire.dxp dxp
|
||||
application/vnd.spotfire.sfs sfs
|
||||
application/vnd.stardivision.calc sdc
|
||||
application/vnd.stardivision.draw sda
|
||||
application/vnd.stardivision.impress sdd
|
||||
application/vnd.stardivision.math smf
|
||||
application/vnd.stardivision.writer sdw vor
|
||||
application/vnd.stardivision.writer-global sgl
|
||||
application/vnd.stepmania.package smzip
|
||||
application/vnd.stepmania.stepchart sm
|
||||
application/vnd.sun.xml.calc sxc
|
||||
application/vnd.sun.xml.calc.template stc
|
||||
application/vnd.sun.xml.draw sxd
|
||||
application/vnd.sun.xml.draw.template std
|
||||
application/vnd.sun.xml.impress sxi
|
||||
application/vnd.sun.xml.impress.template sti
|
||||
application/vnd.sun.xml.math sxm
|
||||
application/vnd.sun.xml.writer sxw
|
||||
application/vnd.sun.xml.writer.global sxg
|
||||
application/vnd.sun.xml.writer.template stw
|
||||
application/vnd.sus-calendar sus susp
|
||||
application/vnd.svd svd
|
||||
application/vnd.symbian.install sis sisx
|
||||
application/vnd.syncml+xml xsm
|
||||
application/vnd.syncml.dm+wbxml bdm
|
||||
application/vnd.syncml.dm+xml xdm
|
||||
application/vnd.tao.intent-module-archive tao
|
||||
application/vnd.tcpdump.pcap pcap cap dmp
|
||||
application/vnd.tmobile-livetv tmo
|
||||
application/vnd.trid.tpt tpt
|
||||
application/vnd.triscape.mxs mxs
|
||||
application/vnd.trueapp tra
|
||||
application/vnd.ufdl ufd ufdl
|
||||
application/vnd.uiq.theme utz
|
||||
application/vnd.umajin umj
|
||||
application/vnd.unity unityweb
|
||||
application/vnd.uoml+xml uoml
|
||||
application/vnd.vcx vcx
|
||||
application/vnd.visio vsd vst vss vsw
|
||||
application/vnd.visionary vis
|
||||
application/vnd.vsf vsf
|
||||
application/vnd.wap.wbxml wbxml
|
||||
application/vnd.wap.wmlc wmlc
|
||||
application/vnd.wap.wmlscriptc wmlsc
|
||||
application/vnd.webturbo wtb
|
||||
application/vnd.wolfram.player nbp
|
||||
application/vnd.wordperfect wpd
|
||||
application/vnd.wqd wqd
|
||||
application/vnd.wt.stf stf
|
||||
application/vnd.xara xar
|
||||
application/vnd.xfdl xfdl
|
||||
application/vnd.yamaha.hv-dic hvd
|
||||
application/vnd.yamaha.hv-script hvs
|
||||
application/vnd.yamaha.hv-voice hvp
|
||||
application/vnd.yamaha.openscoreformat osf
|
||||
application/vnd.yamaha.openscoreformat.osfpvg+xml osfpvg
|
||||
application/vnd.yamaha.smaf-audio saf
|
||||
application/vnd.yamaha.smaf-phrase spf
|
||||
application/vnd.yellowriver-custom-menu cmp
|
||||
application/vnd.zul zir zirz
|
||||
application/vnd.zzazz.deck+xml zaz
|
||||
application/voicexml+xml vxml
|
||||
application/widget wgt
|
||||
application/winhlp hlp
|
||||
application/wsdl+xml wsdl
|
||||
application/wspolicy+xml wspolicy
|
||||
application/x-7z-compressed 7z
|
||||
application/x-abiword abw
|
||||
application/x-ace-compressed ace
|
||||
application/x-apple-diskimage dmg
|
||||
application/x-authorware-bin aab x32 u32 vox
|
||||
application/x-authorware-map aam
|
||||
application/x-authorware-seg aas
|
||||
application/x-bcpio bcpio
|
||||
application/x-bittorrent torrent
|
||||
application/x-blorb blb blorb
|
||||
application/x-bzip bz
|
||||
application/x-bzip2 bz2 boz
|
||||
application/x-cbr cbr cba cbt cbz cb7
|
||||
application/x-cdlink vcd
|
||||
application/x-cfs-compressed cfs
|
||||
application/x-chat chat
|
||||
application/x-chess-pgn pgn
|
||||
application/x-conference nsc
|
||||
application/x-cpio cpio
|
||||
application/x-csh csh
|
||||
application/x-debian-package deb udeb
|
||||
application/x-dgc-compressed dgc
|
||||
application/x-director dir dcr dxr cst cct cxt w3d fgd swa
|
||||
application/x-doom wad
|
||||
application/x-dtbncx+xml ncx
|
||||
application/x-dtbook+xml dtb
|
||||
application/x-dtbresource+xml res
|
||||
application/x-dvi dvi
|
||||
application/x-envoy evy
|
||||
application/x-eva eva
|
||||
application/x-font-bdf bdf
|
||||
application/x-font-ghostscript gsf
|
||||
application/x-font-linux-psf psf
|
||||
application/x-font-pcf pcf
|
||||
application/x-font-snf snf
|
||||
application/x-font-type1 pfa pfb pfm afm
|
||||
application/x-freearc arc
|
||||
application/x-futuresplash spl
|
||||
application/x-gca-compressed gca
|
||||
application/x-glulx ulx
|
||||
application/x-gnumeric gnumeric
|
||||
application/x-gramps-xml gramps
|
||||
application/x-gtar gtar
|
||||
application/x-hdf hdf
|
||||
application/x-install-instructions install
|
||||
application/x-iso9660-image iso
|
||||
application/x-java-jnlp-file jnlp
|
||||
application/x-latex latex
|
||||
application/x-lzh-compressed lzh lha
|
||||
application/x-mie mie
|
||||
application/x-mobipocket-ebook prc mobi
|
||||
application/x-ms-application application
|
||||
application/x-ms-shortcut lnk
|
||||
application/x-ms-wmd wmd
|
||||
application/x-ms-wmz wmz
|
||||
application/x-ms-xbap xbap
|
||||
application/x-msaccess mdb
|
||||
application/x-msbinder obd
|
||||
application/x-mscardfile crd
|
||||
application/x-msclip clp
|
||||
application/x-msdownload exe dll com bat msi
|
||||
application/x-msmediaview mvb m13 m14
|
||||
application/x-msmetafile wmf wmz emf emz
|
||||
application/x-msmoney mny
|
||||
application/x-mspublisher pub
|
||||
application/x-msschedule scd
|
||||
application/x-msterminal trm
|
||||
application/x-mswrite wri
|
||||
application/x-netcdf nc cdf
|
||||
application/x-nzb nzb
|
||||
application/x-pkcs12 p12 pfx
|
||||
application/x-pkcs7-certificates p7b spc
|
||||
application/x-pkcs7-certreqresp p7r
|
||||
application/x-rar-compressed rar
|
||||
application/x-research-info-systems ris
|
||||
application/x-sh sh
|
||||
application/x-shar shar
|
||||
application/x-shockwave-flash swf
|
||||
application/x-silverlight-app xap
|
||||
application/x-sql sql
|
||||
application/x-stuffit sit
|
||||
application/x-stuffitx sitx
|
||||
application/x-subrip srt
|
||||
application/x-sv4cpio sv4cpio
|
||||
application/x-sv4crc sv4crc
|
||||
application/x-t3vm-image t3
|
||||
application/x-tads gam
|
||||
application/x-tar tar
|
||||
application/x-tcl tcl
|
||||
application/x-tex tex
|
||||
application/x-tex-tfm tfm
|
||||
application/x-texinfo texinfo texi
|
||||
application/x-tgif obj
|
||||
application/x-ustar ustar
|
||||
application/x-wais-source src
|
||||
application/x-x509-ca-cert der crt
|
||||
application/x-xfig fig
|
||||
application/x-xliff+xml xlf
|
||||
application/x-xpinstall xpi
|
||||
application/x-xz xz
|
||||
application/x-zmachine z1 z2 z3 z4 z5 z6 z7 z8
|
||||
application/xaml+xml xaml
|
||||
application/xcap-diff+xml xdf
|
||||
application/xenc+xml xenc
|
||||
application/xhtml+xml xhtml xht
|
||||
application/xml xml xsl
|
||||
application/xml-dtd dtd
|
||||
application/xop+xml xop
|
||||
application/xproc+xml xpl
|
||||
application/xslt+xml xslt
|
||||
application/xspf+xml xspf
|
||||
application/xv+xml mxml xhvml xvml xvm
|
||||
application/yang yang
|
||||
application/yin+xml yin
|
||||
application/zip zip
|
||||
audio/adpcm adp
|
||||
audio/basic au snd
|
||||
audio/midi mid midi kar rmi
|
||||
audio/mp4 m4a mp4a
|
||||
audio/mpeg mpga mp2 mp2a mp3 m2a m3a
|
||||
audio/ogg oga ogg spx
|
||||
audio/s3m s3m
|
||||
audio/silk sil
|
||||
audio/vnd.dece.audio uva uvva
|
||||
audio/vnd.digital-winds eol
|
||||
audio/vnd.dra dra
|
||||
audio/vnd.dts dts
|
||||
audio/vnd.dts.hd dtshd
|
||||
audio/vnd.lucent.voice lvp
|
||||
audio/vnd.ms-playready.media.pya pya
|
||||
audio/vnd.nuera.ecelp4800 ecelp4800
|
||||
audio/vnd.nuera.ecelp7470 ecelp7470
|
||||
audio/vnd.nuera.ecelp9600 ecelp9600
|
||||
audio/vnd.rip rip
|
||||
audio/webm weba
|
||||
audio/x-aac aac
|
||||
audio/x-aiff aif aiff aifc
|
||||
audio/x-caf caf
|
||||
audio/x-flac flac
|
||||
audio/x-matroska mka
|
||||
audio/x-mpegurl m3u
|
||||
audio/x-ms-wax wax
|
||||
audio/x-ms-wma wma
|
||||
audio/x-pn-realaudio ram ra
|
||||
audio/x-pn-realaudio-plugin rmp
|
||||
audio/x-wav wav
|
||||
audio/xm xm
|
||||
chemical/x-cdx cdx
|
||||
chemical/x-cif cif
|
||||
chemical/x-cmdf cmdf
|
||||
chemical/x-cml cml
|
||||
chemical/x-csml csml
|
||||
chemical/x-xyz xyz
|
||||
font/collection ttc
|
||||
font/otf otf
|
||||
font/ttf ttf
|
||||
font/woff woff
|
||||
font/woff2 woff2
|
||||
image/bmp bmp
|
||||
image/cgm cgm
|
||||
image/g3fax g3
|
||||
image/gif gif
|
||||
image/ief ief
|
||||
image/jpeg jpeg jpg jpe
|
||||
image/ktx ktx
|
||||
image/png png
|
||||
image/prs.btif btif
|
||||
image/sgi sgi
|
||||
image/svg+xml svg svgz
|
||||
image/tiff tiff tif
|
||||
image/vnd.adobe.photoshop psd
|
||||
image/vnd.dece.graphic uvi uvvi uvg uvvg
|
||||
image/vnd.djvu djvu djv
|
||||
image/vnd.dvb.subtitle sub
|
||||
image/vnd.dwg dwg
|
||||
image/vnd.dxf dxf
|
||||
image/vnd.fastbidsheet fbs
|
||||
image/vnd.fpx fpx
|
||||
image/vnd.fst fst
|
||||
image/vnd.fujixerox.edmics-mmr mmr
|
||||
image/vnd.fujixerox.edmics-rlc rlc
|
||||
image/vnd.ms-modi mdi
|
||||
image/vnd.ms-photo wdp
|
||||
image/vnd.net-fpx npx
|
||||
image/vnd.wap.wbmp wbmp
|
||||
image/vnd.xiff xif
|
||||
image/webp webp
|
||||
image/x-3ds 3ds
|
||||
image/x-cmu-raster ras
|
||||
image/x-cmx cmx
|
||||
image/x-freehand fh fhc fh4 fh5 fh7
|
||||
image/x-icon ico
|
||||
image/x-mrsid-image sid
|
||||
image/x-pcx pcx
|
||||
image/x-pict pic pct
|
||||
image/x-portable-anymap pnm
|
||||
image/x-portable-bitmap pbm
|
||||
image/x-portable-graymap pgm
|
||||
image/x-portable-pixmap ppm
|
||||
image/x-rgb rgb
|
||||
image/x-tga tga
|
||||
image/x-xbitmap xbm
|
||||
image/x-xpixmap xpm
|
||||
image/x-xwindowdump xwd
|
||||
message/rfc822 eml mime
|
||||
model/iges igs iges
|
||||
model/mesh msh mesh silo
|
||||
model/vnd.collada+xml dae
|
||||
model/vnd.dwf dwf
|
||||
model/vnd.gdl gdl
|
||||
model/vnd.gtw gtw
|
||||
model/vnd.mts mts
|
||||
model/vnd.vtu vtu
|
||||
model/vrml wrl vrml
|
||||
model/x3d+binary x3db x3dbz
|
||||
model/x3d+vrml x3dv x3dvz
|
||||
model/x3d+xml x3d x3dz
|
||||
text/cache-manifest appcache
|
||||
text/calendar ics ifb
|
||||
text/css css
|
||||
text/csv csv
|
||||
text/html html htm
|
||||
text/n3 n3
|
||||
text/plain txt text conf def list log in
|
||||
text/prs.lines.tag dsc
|
||||
text/richtext rtx
|
||||
text/sgml sgml sgm
|
||||
text/tab-separated-values tsv
|
||||
text/troff t tr roff man me ms
|
||||
text/turtle ttl
|
||||
text/uri-list uri uris urls
|
||||
text/vcard vcard
|
||||
text/vnd.curl curl
|
||||
text/vnd.curl.dcurl dcurl
|
||||
text/vnd.curl.mcurl mcurl
|
||||
text/vnd.curl.scurl scurl
|
||||
text/vnd.dvb.subtitle sub
|
||||
text/vnd.fly fly
|
||||
text/vnd.fmi.flexstor flx
|
||||
text/vnd.graphviz gv
|
||||
text/vnd.in3d.3dml 3dml
|
||||
text/vnd.in3d.spot spot
|
||||
text/vnd.sun.j2me.app-descriptor jad
|
||||
text/vnd.wap.wml wml
|
||||
text/vnd.wap.wmlscript wmls
|
||||
text/x-asm s asm
|
||||
text/x-c c cc cxx cpp h hh dic
|
||||
text/x-fortran f for f77 f90
|
||||
text/x-java-source java
|
||||
text/x-nfo nfo
|
||||
text/x-opml opml
|
||||
text/x-pascal p pas
|
||||
text/x-setext etx
|
||||
text/x-sfv sfv
|
||||
text/x-uuencode uu
|
||||
text/x-vcalendar vcs
|
||||
text/x-vcard vcf
|
||||
video/3gpp 3gp
|
||||
video/3gpp2 3g2
|
||||
video/h261 h261
|
||||
video/h263 h263
|
||||
video/h264 h264
|
||||
video/jpeg jpgv
|
||||
video/jpm jpm jpgm
|
||||
video/mj2 mj2 mjp2
|
||||
video/mp4 mp4 mp4v mpg4
|
||||
video/mpeg mpeg mpg mpe m1v m2v
|
||||
video/ogg ogv
|
||||
video/quicktime qt mov
|
||||
video/vnd.dece.hd uvh uvvh
|
||||
video/vnd.dece.mobile uvm uvvm
|
||||
video/vnd.dece.pd uvp uvvp
|
||||
video/vnd.dece.sd uvs uvvs
|
||||
video/vnd.dece.video uvv uvvv
|
||||
video/vnd.dvb.file dvb
|
||||
video/vnd.fvt fvt
|
||||
video/vnd.mpegurl mxu m4u
|
||||
video/vnd.ms-playready.media.pyv pyv
|
||||
video/vnd.uvvu.mp4 uvu uvvu
|
||||
video/vnd.vivo viv
|
||||
video/webm webm
|
||||
video/x-f4v f4v
|
||||
video/x-fli fli
|
||||
video/x-flv flv
|
||||
video/x-m4v m4v
|
||||
video/x-matroska mkv mk3d mks
|
||||
video/x-mng mng
|
||||
video/x-ms-asf asf asx
|
||||
video/x-ms-vob vob
|
||||
video/x-ms-wm wm
|
||||
video/x-ms-wmv wmv
|
||||
video/x-ms-wmx wmx
|
||||
video/x-ms-wvx wvx
|
||||
video/x-msvideo avi
|
||||
video/x-sgi-movie movie
|
||||
video/x-smv smv
|
||||
x-conference/x-cooltalk ice
|
||||
@@ -0,0 +1,141 @@
|
||||
<?php
|
||||
/**
|
||||
* elFinder Plugin AutoResize
|
||||
*
|
||||
* Auto resize on file upload.
|
||||
*
|
||||
* ex. binding, configure on connector options
|
||||
* $opts = array(
|
||||
* 'bind' => array(
|
||||
* 'upload.presave' => array(
|
||||
* 'Plugin.AutoResize.onUpLoadPreSave'
|
||||
* )
|
||||
* ),
|
||||
* // global configure (optional)
|
||||
* 'plugin' => array(
|
||||
* 'AutoResize' => array(
|
||||
* 'enable' => true, // For control by volume driver
|
||||
* 'maxWidth' => 1024, // Path to Water mark image
|
||||
* 'maxHeight' => 1024, // Margin right pixel
|
||||
* 'quality' => 95, // JPEG image save quality
|
||||
* 'preserveExif' => false, // Preserve EXIF data (Imagick only)
|
||||
* 'forceEffect' => false, // For change quality or make progressive JPEG of small images
|
||||
* 'targetType' => IMG_GIF|IMG_JPG|IMG_PNG|IMG_WBMP, // Target image formats ( bit-field )
|
||||
* 'offDropWith' => null, // Enabled by default. To disable it if it is dropped with pressing the meta key
|
||||
* // Alt: 8, Ctrl: 4, Meta: 2, Shift: 1 - sum of each value
|
||||
* // In case of using any key, specify it as an array
|
||||
* 'onDropWith' => null // Disabled by default. To enable it if it is dropped with pressing the meta key
|
||||
* // Alt: 8, Ctrl: 4, Meta: 2, Shift: 1 - sum of each value
|
||||
* // In case of using any key, specify it as an array
|
||||
* )
|
||||
* ),
|
||||
* // each volume configure (optional)
|
||||
* 'roots' => array(
|
||||
* array(
|
||||
* 'driver' => 'LocalFileSystem',
|
||||
* 'path' => '/path/to/files/',
|
||||
* 'URL' => 'http://localhost/to/files/'
|
||||
* 'plugin' => array(
|
||||
* 'AutoResize' => array(
|
||||
* 'enable' => true, // For control by volume driver
|
||||
* 'maxWidth' => 1024, // Path to Water mark image
|
||||
* 'maxHeight' => 1024, // Margin right pixel
|
||||
* 'quality' => 95, // JPEG image save quality
|
||||
* 'preserveExif' => false, // Preserve EXIF data (Imagick only)
|
||||
* 'forceEffect' => false, // For change quality or make progressive JPEG of small images
|
||||
* 'targetType' => IMG_GIF|IMG_JPG|IMG_PNG|IMG_WBMP, // Target image formats ( bit-field )
|
||||
* 'offDropWith' => null, // Enabled by default. To disable it if it is dropped with pressing the meta key
|
||||
* // Alt: 8, Ctrl: 4, Meta: 2, Shift: 1 - sum of each value
|
||||
* // In case of using any key, specify it as an array
|
||||
* 'onDropWith' => null // Disabled by default. To enable it if it is dropped with pressing the meta key
|
||||
* // Alt: 8, Ctrl: 4, Meta: 2, Shift: 1 - sum of each value
|
||||
* // In case of using any key, specify it as an array
|
||||
* )
|
||||
* )
|
||||
* )
|
||||
* )
|
||||
* );
|
||||
*
|
||||
* @package elfinder
|
||||
* @author Naoki Sawada
|
||||
* @license New BSD
|
||||
*/
|
||||
class elFinderPluginAutoResize extends elFinderPlugin {
|
||||
|
||||
public function __construct($opts) {
|
||||
$defaults = array(
|
||||
'enable' => true, // For control by volume driver
|
||||
'maxWidth' => 1024, // Path to Water mark image
|
||||
'maxHeight' => 1024, // Margin right pixel
|
||||
'quality' => 95, // JPEG image save quality
|
||||
'preserveExif' => false, // Preserve EXIF data (Imagick only)
|
||||
'forceEffect' => false, // For change quality or make progressive JPEG of small images
|
||||
'targetType' => IMG_GIF|IMG_JPG|IMG_PNG|IMG_WBMP, // Target image formats ( bit-field )
|
||||
'offDropWith' => null, // To disable it if it is dropped with pressing the meta key
|
||||
// Alt: 8, Ctrl: 4, Meta: 2, Shift: 1 - sum of each value
|
||||
// In case of using any key, specify it as an array
|
||||
'disableWithContentSaveId' => true // Disable on URL upload with post data "contentSaveId"
|
||||
);
|
||||
|
||||
$this->opts = array_merge($defaults, $opts);
|
||||
|
||||
}
|
||||
|
||||
public function onUpLoadPreSave(&$thash, &$name, $src, $elfinder, $volume) {
|
||||
$opts = $this->getCurrentOpts($volume);
|
||||
|
||||
if (! $this->iaEnabled($opts, $elfinder)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$imageType = null;
|
||||
$srcImgInfo = null;
|
||||
if (extension_loaded('fileinfo') && function_exists('mime_content_type')) {
|
||||
$mime = mime_content_type($src);
|
||||
if (substr($mime, 0, 5) !== 'image') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (extension_loaded('exif') && function_exists('exif_imagetype')) {
|
||||
$imageType = exif_imagetype($src);
|
||||
} else {
|
||||
$srcImgInfo = getimagesize($src);
|
||||
if ($srcImgInfo === false) {
|
||||
return false;
|
||||
}
|
||||
$imageType = $srcImgInfo[2];
|
||||
}
|
||||
|
||||
// check target image type
|
||||
$imgTypes = array(
|
||||
IMAGETYPE_GIF => IMG_GIF,
|
||||
IMAGETYPE_JPEG => IMG_JPEG,
|
||||
IMAGETYPE_PNG => IMG_PNG,
|
||||
IMAGETYPE_BMP => IMG_WBMP,
|
||||
IMAGETYPE_WBMP => IMG_WBMP
|
||||
);
|
||||
if (! isset($imgTypes[$imageType]) || ! ($opts['targetType'] & $imgTypes[$imageType])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! $srcImgInfo) {
|
||||
$srcImgInfo = getimagesize($src);
|
||||
}
|
||||
|
||||
if ($opts['forceEffect'] || $srcImgInfo[0] > $opts['maxWidth'] || $srcImgInfo[1] > $opts['maxHeight']) {
|
||||
return $this->resize($volume, $src, $srcImgInfo, $opts['maxWidth'], $opts['maxHeight'], $opts['quality'], $opts['preserveExif']);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function resize($volume, $src, $srcImgInfo, $maxWidth, $maxHeight, $jpgQuality, $preserveExif) {
|
||||
$zoom = min(($maxWidth/$srcImgInfo[0]),($maxHeight/$srcImgInfo[1]));
|
||||
$width = round($srcImgInfo[0] * $zoom);
|
||||
$height = round($srcImgInfo[1] * $zoom);
|
||||
$unenlarge = true;
|
||||
$checkAnimated = true;
|
||||
|
||||
return $volume->imageUtil('resize', $src, compact('width', 'height', 'jpgQuality', 'preserveExif', 'unenlarge', 'checkAnimated'));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
/**
|
||||
* elFinder Plugin AutoRotate
|
||||
*
|
||||
* Auto rotation on file upload of JPEG file by EXIF Orientation.
|
||||
*
|
||||
* ex. binding, configure on connector options
|
||||
* $opts = array(
|
||||
* 'bind' => array(
|
||||
* 'upload.presave' => array(
|
||||
* 'Plugin.AutoRotate.onUpLoadPreSave'
|
||||
* )
|
||||
* ),
|
||||
* // global configure (optional)
|
||||
* 'plugin' => array(
|
||||
* 'AutoRotate' => array(
|
||||
* 'enable' => true, // For control by volume driver
|
||||
* 'quality' => 95, // JPEG image save quality
|
||||
* 'offDropWith' => null, // Enabled by default. To disable it if it is dropped with pressing the meta key
|
||||
* // Alt: 8, Ctrl: 4, Meta: 2, Shift: 1 - sum of each value
|
||||
* // In case of using any key, specify it as an array
|
||||
* 'onDropWith' => null // Disabled by default. To enable it if it is dropped with pressing the meta key
|
||||
* // Alt: 8, Ctrl: 4, Meta: 2, Shift: 1 - sum of each value
|
||||
* // In case of using any key, specify it as an array
|
||||
* )
|
||||
* ),
|
||||
* // each volume configure (optional)
|
||||
* 'roots' => array(
|
||||
* array(
|
||||
* 'driver' => 'LocalFileSystem',
|
||||
* 'path' => '/path/to/files/',
|
||||
* 'URL' => 'http://localhost/to/files/'
|
||||
* 'plugin' => array(
|
||||
* 'AutoRotate' => array(
|
||||
* 'enable' => true, // For control by volume driver
|
||||
* 'quality' => 95, // JPEG image save quality
|
||||
* 'offDropWith' => null, // Enabled by default. To disable it if it is dropped with pressing the meta key
|
||||
* // Alt: 8, Ctrl: 4, Meta: 2, Shift: 1 - sum of each value
|
||||
* // In case of using any key, specify it as an array
|
||||
* 'onDropWith' => null // Disabled by default. To enable it if it is dropped with pressing the meta key
|
||||
* // Alt: 8, Ctrl: 4, Meta: 2, Shift: 1 - sum of each value
|
||||
* // In case of using any key, specify it as an array
|
||||
* )
|
||||
* )
|
||||
* )
|
||||
* )
|
||||
* );
|
||||
*
|
||||
* @package elfinder
|
||||
* @author Naoki Sawada
|
||||
* @license New BSD
|
||||
*/
|
||||
class elFinderPluginAutoRotate extends elFinderPlugin {
|
||||
|
||||
public function __construct($opts) {
|
||||
$defaults = array(
|
||||
'enable' => true, // For control by volume driver
|
||||
'quality' => 95, // JPEG image save quality
|
||||
'offDropWith' => null, // To disable it if it is dropped with pressing the meta key
|
||||
// Alt: 8, Ctrl: 4, Meta: 2, Shift: 1 - sum of each value
|
||||
// In case of using any key, specify it as an array
|
||||
'disableWithContentSaveId' => true // Disable on URL upload with post data "contentSaveId"
|
||||
);
|
||||
|
||||
$this->opts = array_merge($defaults, $opts);
|
||||
|
||||
}
|
||||
|
||||
public function onUpLoadPreSave(&$thash, &$name, $src, $elfinder, $volume) {
|
||||
$opts = $this->getCurrentOpts($volume);
|
||||
|
||||
if (! $this->iaEnabled($opts, $elfinder)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$imageType = null;
|
||||
$srcImgInfo = null;
|
||||
if (extension_loaded('fileinfo') && function_exists('mime_content_type')) {
|
||||
$mime = mime_content_type($src);
|
||||
if (substr($mime, 0, 5) !== 'image') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (extension_loaded('exif') && function_exists('exif_imagetype')) {
|
||||
$imageType = exif_imagetype($src);
|
||||
} else {
|
||||
$srcImgInfo = getimagesize($src);
|
||||
if ($srcImgInfo === false) {
|
||||
return false;
|
||||
}
|
||||
$imageType = $srcImgInfo[2];
|
||||
}
|
||||
|
||||
// check target image type
|
||||
if ($imageType !== IMAGETYPE_JPEG) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! $srcImgInfo) {
|
||||
$srcImgInfo = getimagesize($src);
|
||||
}
|
||||
|
||||
return $this->rotate($volume, $src, $srcImgInfo, $opts['quality']);
|
||||
}
|
||||
|
||||
private function rotate($volume, $src, $srcImgInfo, $quality) {
|
||||
if (! function_exists('exif_read_data')) {
|
||||
return false;
|
||||
}
|
||||
$degree = 0;
|
||||
$exif = exif_read_data($src);
|
||||
if($exif && !empty($exif['Orientation'])) {
|
||||
switch($exif['Orientation']) {
|
||||
case 8:
|
||||
$degree = 270;
|
||||
break;
|
||||
case 3:
|
||||
$degree = 180;
|
||||
break;
|
||||
case 6:
|
||||
$degree = 90;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$opts = array(
|
||||
'degree' => $degree,
|
||||
'jpgQuality' => $quality,
|
||||
'checkAnimated' => true
|
||||
);
|
||||
return $volume->imageUtil('rotate', $src, $opts);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
<?php
|
||||
/**
|
||||
* elFinder Plugin Normalizer
|
||||
*
|
||||
* UTF-8 Normalizer of file-name and file-path etc.
|
||||
* nfc(NFC): Canonical Decomposition followed by Canonical Composition
|
||||
* nfkc(NFKC): Compatibility Decomposition followed by Canonical
|
||||
*
|
||||
* This plugin require Class "Normalizer" (PHP 5 >= 5.3.0, PECL intl >= 1.0.0)
|
||||
* or PEAR package "I18N_UnicodeNormalizer"
|
||||
*
|
||||
* ex. binding, configure on connector options
|
||||
* $opts = array(
|
||||
* 'bind' => array(
|
||||
* 'upload.pre mkdir.pre mkfile.pre rename.pre archive.pre ls.pre' => array(
|
||||
* 'Plugin.Normalizer.cmdPreprocess'
|
||||
* ),
|
||||
* 'upload.presave' => array(
|
||||
* 'Plugin.Normalizer.onUpLoadPreSave'
|
||||
* )
|
||||
* ),
|
||||
* // global configure (optional)
|
||||
* 'plugin' => array(
|
||||
* 'Normalizer' => array(
|
||||
* 'enable' => true,
|
||||
* 'nfc' => true,
|
||||
* 'nfkc' => true,
|
||||
* 'umlauts' => false,
|
||||
* 'lowercase' => false,
|
||||
* 'convmap' => array()
|
||||
* )
|
||||
* ),
|
||||
* // each volume configure (optional)
|
||||
* 'roots' => array(
|
||||
* array(
|
||||
* 'driver' => 'LocalFileSystem',
|
||||
* 'path' => '/path/to/files/',
|
||||
* 'URL' => 'http://localhost/to/files/'
|
||||
* 'plugin' => array(
|
||||
* 'Normalizer' => array(
|
||||
* 'enable' => true,
|
||||
* 'nfc' => true,
|
||||
* 'nfkc' => true,
|
||||
* 'umlauts' => false,
|
||||
* 'lowercase' => false,
|
||||
* 'convmap' => array()
|
||||
* )
|
||||
* )
|
||||
* )
|
||||
* )
|
||||
* );
|
||||
*
|
||||
* @package elfinder
|
||||
* @author Naoki Sawada
|
||||
* @license New BSD
|
||||
*/
|
||||
class elFinderPluginNormalizer extends elFinderPlugin
|
||||
{
|
||||
private $replaced = array();
|
||||
private $keyMap = array(
|
||||
'ls' => 'intersect',
|
||||
'upload' => 'renames',
|
||||
'mkdir' => array('name', 'dirs')
|
||||
);
|
||||
|
||||
public function __construct($opts) {
|
||||
$defaults = array(
|
||||
'enable' => true, // For control by volume driver
|
||||
'nfc' => true, // Canonical Decomposition followed by Canonical Composition
|
||||
'nfkc' => true, // Compatibility Decomposition followed by Canonical
|
||||
'umlauts' => false, // Convert umlauts with their closest 7 bit ascii equivalent
|
||||
'lowercase' => false, // Make chars lowercase
|
||||
'convmap' => array()// Convert map ('FROM' => 'TO') array
|
||||
);
|
||||
|
||||
$this->opts = array_merge($defaults, $opts);
|
||||
}
|
||||
|
||||
public function cmdPreprocess($cmd, &$args, $elfinder, $volume) {
|
||||
$opts = $this->getCurrentOpts($volume);
|
||||
if (! $opts['enable']) {
|
||||
return false;
|
||||
}
|
||||
$this->replaced[$cmd] = array();
|
||||
$key = (isset($this->keyMap[$cmd]))? $this->keyMap[$cmd] : 'name';
|
||||
|
||||
if (is_array($key)) {
|
||||
$keys = $key;
|
||||
} else {
|
||||
$keys = array($key);
|
||||
}
|
||||
foreach($keys as $key) {
|
||||
if (isset($args[$key])) {
|
||||
if (is_array($args[$key])) {
|
||||
foreach($args[$key] as $i => $name) {
|
||||
if ($cmd === 'mkdir' && $key === 'dirs') {
|
||||
// $name need '/' as prefix see #2607
|
||||
$name = '/' . ltrim($name, '/');
|
||||
$_names = explode('/', $name);
|
||||
$_res = array();
|
||||
foreach($_names as $_name) {
|
||||
$_res[] = $this->normalize($_name, $opts);
|
||||
}
|
||||
$this->replaced[$cmd][$name] = $args[$key][$i] = join('/', $_res);
|
||||
} else {
|
||||
$this->replaced[$cmd][$name] = $args[$key][$i] = $this->normalize($name, $opts);
|
||||
}
|
||||
}
|
||||
} else if ($args[$key] !== '') {
|
||||
$name = $args[$key];
|
||||
$this->replaced[$cmd][$name] = $args[$key] = $this->normalize($name, $opts);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($cmd === 'ls' || $cmd === 'mkdir') {
|
||||
if (! empty($this->replaced[$cmd])) {
|
||||
// un-regist for legacy settings
|
||||
$elfinder->unbind($cmd, array($this, 'cmdPostprocess'));
|
||||
$elfinder->bind($cmd, array($this, 'cmdPostprocess'));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function cmdPostprocess($cmd, &$result, $args, $elfinder, $volume) {
|
||||
if ($cmd === 'ls') {
|
||||
if (! empty($result['list']) && ! empty($this->replaced['ls'])) {
|
||||
foreach($result['list'] as $hash => $name) {
|
||||
if ($keys = array_keys($this->replaced['ls'], $name)) {
|
||||
if (count($keys) === 1) {
|
||||
$result['list'][$hash] = $keys[0];
|
||||
} else {
|
||||
$result['list'][$hash] = $keys;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if ($cmd === 'mkdir') {
|
||||
if (! empty($result['hashes']) && ! empty($this->replaced['mkdir'])) {
|
||||
foreach($result['hashes'] as $name => $hash) {
|
||||
if ($keys = array_keys($this->replaced['mkdir'], $name)) {
|
||||
$result['hashes'][$keys[0]] = $hash;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: $thash is directory hash so it unneed to process at here
|
||||
public function onUpLoadPreSave(&$thash, &$name, $src, $elfinder, $volume) {
|
||||
$opts = $this->getCurrentOpts($volume);
|
||||
if (! $opts['enable']) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$name = $this->normalize($name, $opts);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function normalize($str, $opts) {
|
||||
if ($opts['nfc'] || $opts['nfkc']) {
|
||||
if (class_exists('Normalizer', false)) {
|
||||
if ($opts['nfc'] && ! Normalizer::isNormalized($str, Normalizer::FORM_C))
|
||||
$str = Normalizer::normalize($str, Normalizer::FORM_C);
|
||||
if ($opts['nfkc'] && ! Normalizer::isNormalized($str, Normalizer::FORM_KC))
|
||||
$str = Normalizer::normalize($str, Normalizer::FORM_KC);
|
||||
} else {
|
||||
if (! class_exists('I18N_UnicodeNormalizer', false)) {
|
||||
include_once 'I18N/UnicodeNormalizer.php';
|
||||
}
|
||||
if (class_exists('I18N_UnicodeNormalizer', false)) {
|
||||
$normalizer = new I18N_UnicodeNormalizer();
|
||||
if ($opts['nfc'])
|
||||
$str = $normalizer->normalize($str, 'NFC');
|
||||
if ($opts['nfkc'])
|
||||
$str = $normalizer->normalize($str, 'NFKC');
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($opts['umlauts']) {
|
||||
if (strpos($str = htmlentities($str, ENT_QUOTES, 'UTF-8'), '&') !== false) {
|
||||
$str = html_entity_decode(preg_replace('~&([a-z]{1,2})(?:acute|cedil|circ|grave|lig|orn|ring|slash|tilde|uml);~i', '$1', $str), ENT_QUOTES, 'utf-8');
|
||||
}
|
||||
}
|
||||
if ($opts['convmap'] && is_array($opts['convmap'])) {
|
||||
$str = strtr($str, $opts['convmap']);
|
||||
}
|
||||
if ($opts['lowercase']) {
|
||||
if (function_exists('mb_strtolower')) {
|
||||
$str = mb_strtolower($str, 'UTF-8');
|
||||
} else {
|
||||
$str = strtolower($str);
|
||||
}
|
||||
}
|
||||
return $str;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
<?php
|
||||
/**
|
||||
* elFinder Plugin Sanitizer
|
||||
*
|
||||
* Sanitizer of file-name and file-path etc.
|
||||
*
|
||||
* ex. binding, configure on connector options
|
||||
* $opts = array(
|
||||
* 'bind' => array(
|
||||
* 'upload.pre mkdir.pre mkfile.pre rename.pre archive.pre ls.pre' => array(
|
||||
* 'Plugin.Sanitizer.cmdPreprocess'
|
||||
* ),
|
||||
* 'upload.presave' => array(
|
||||
* 'Plugin.Sanitizer.onUpLoadPreSave'
|
||||
* )
|
||||
* ),
|
||||
* // global configure (optional)
|
||||
* 'plugin' => array(
|
||||
* 'Sanitizer' => array(
|
||||
* 'enable' => true,
|
||||
* 'targets' => array('\\','/',':','*','?','"','<','>','|'), // target chars
|
||||
* 'replace' => '_', // replace to this
|
||||
* 'callBack' => null // Or @callable sanitize function
|
||||
* )
|
||||
* ),
|
||||
* // each volume configure (optional)
|
||||
* 'roots' => array(
|
||||
* array(
|
||||
* 'driver' => 'LocalFileSystem',
|
||||
* 'path' => '/path/to/files/',
|
||||
* 'URL' => 'http://localhost/to/files/'
|
||||
* 'plugin' => array(
|
||||
* 'Sanitizer' => array(
|
||||
* 'enable' => true,
|
||||
* 'targets' => array('\\','/',':','*','?','"','<','>','|'), // target chars
|
||||
* 'replace' => '_', // replace to this
|
||||
* 'callBack' => null // Or @callable sanitize function
|
||||
* )
|
||||
* )
|
||||
* )
|
||||
* )
|
||||
* );
|
||||
*
|
||||
* @package elfinder
|
||||
* @author Naoki Sawada
|
||||
* @license New BSD
|
||||
*/
|
||||
class elFinderPluginSanitizer extends elFinderPlugin
|
||||
{
|
||||
private $replaced = array();
|
||||
private $keyMap = array(
|
||||
'ls' => 'intersect',
|
||||
'upload' => 'renames',
|
||||
'mkdir' => array('name', 'dirs')
|
||||
);
|
||||
|
||||
public function __construct($opts) {
|
||||
$defaults = array(
|
||||
'enable' => true, // For control by volume driver
|
||||
'targets' => array('\\','/',':','*','?','"','<','>','|'), // target chars
|
||||
'replace' => '_', // replace to this
|
||||
'callBack' => null // Or callable sanitize function
|
||||
);
|
||||
$this->opts = array_merge($defaults, $opts);
|
||||
}
|
||||
|
||||
public function cmdPreprocess($cmd, &$args, $elfinder, $volume) {
|
||||
$opts = $this->getCurrentOpts($volume);
|
||||
if (! $opts['enable']) {
|
||||
return false;
|
||||
}
|
||||
$this->replaced[$cmd] = array();
|
||||
$key = (isset($this->keyMap[$cmd]))? $this->keyMap[$cmd] : 'name';
|
||||
|
||||
if (is_array($key)) {
|
||||
$keys = $key;
|
||||
} else {
|
||||
$keys = array($key);
|
||||
}
|
||||
foreach($keys as $key) {
|
||||
if (isset($args[$key])) {
|
||||
if (is_array($args[$key])) {
|
||||
foreach($args[$key] as $i => $name) {
|
||||
if ($cmd === 'mkdir' && $key === 'dirs') {
|
||||
// $name need '/' as prefix see #2607
|
||||
$name = '/' . ltrim($name, '/');
|
||||
$_names = explode('/', $name);
|
||||
$_res = array();
|
||||
foreach($_names as $_name) {
|
||||
$_res[] = $this->sanitizeFileName($_name, $opts);
|
||||
}
|
||||
$this->replaced[$cmd][$name] = $args[$key][$i] = join('/', $_res);
|
||||
} else {
|
||||
$this->replaced[$cmd][$name] = $args[$key][$i] = $this->sanitizeFileName($name, $opts);
|
||||
}
|
||||
}
|
||||
} else if ($args[$key] !== '') {
|
||||
$name = $args[$key];
|
||||
$this->replaced[$cmd][$name] = $args[$key] = $this->sanitizeFileName($name, $opts);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($cmd === 'ls' || $cmd === 'mkdir') {
|
||||
if (! empty($this->replaced[$cmd])) {
|
||||
// un-regist for legacy settings
|
||||
$elfinder->unbind($cmd, array($this, 'cmdPostprocess'));
|
||||
$elfinder->bind($cmd, array($this, 'cmdPostprocess'));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function cmdPostprocess($cmd, &$result, $args, $elfinder, $volume) {
|
||||
if ($cmd === 'ls') {
|
||||
if (! empty($result['list']) && ! empty($this->replaced['ls'])) {
|
||||
foreach($result['list'] as $hash => $name) {
|
||||
if ($keys = array_keys($this->replaced['ls'], $name)) {
|
||||
if (count($keys) === 1) {
|
||||
$result['list'][$hash] = $keys[0];
|
||||
} else {
|
||||
$result['list'][$hash] = $keys;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if ($cmd === 'mkdir') {
|
||||
if (! empty($result['hashes']) && ! empty($this->replaced['mkdir'])) {
|
||||
foreach($result['hashes'] as $name => $hash) {
|
||||
if ($keys = array_keys($this->replaced['mkdir'], $name)) {
|
||||
$result['hashes'][$keys[0]] = $hash;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: $thash is directory hash so it unneed to process at here
|
||||
public function onUpLoadPreSave(&$thash, &$name, $src, $elfinder, $volume) {
|
||||
$opts = $this->getCurrentOpts($volume);
|
||||
if (! $opts['enable']) {
|
||||
return false;
|
||||
}
|
||||
$name = $this->sanitizeFileName($name, $opts);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function sanitizeFileName($filename, $opts) {
|
||||
if(!empty($opts['callBack']) && is_callable($opts['callBack'])) {
|
||||
return call_user_func_array($opts['callBack'], array($filename, $opts));
|
||||
}
|
||||
return str_replace($opts['targets'], $opts['replace'], $filename);
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 8.7 KiB |
@@ -0,0 +1,420 @@
|
||||
<?php
|
||||
/**
|
||||
* elFinder Plugin Watermark
|
||||
*
|
||||
* Print watermark on file upload.
|
||||
*
|
||||
* ex. binding, configure on connector options
|
||||
* $opts = array(
|
||||
* 'bind' => array(
|
||||
* 'upload.presave' => array(
|
||||
* 'Plugin.Watermark.onUpLoadPreSave'
|
||||
* )
|
||||
* ),
|
||||
* // global configure (optional)
|
||||
* 'plugin' => array(
|
||||
* 'Watermark' => array(
|
||||
* 'enable' => true, // For control by volume driver
|
||||
* 'source' => 'logo.png', // Path to Water mark image
|
||||
* 'ratio' => 0.2, // Ratio to original image (ratio > 0 and ratio <= 1)
|
||||
* 'position' => 'RB', // Position L(eft)/C(enter)/R(ight) and T(op)/M(edium)/B(ottom)
|
||||
* 'marginX' => 5, // Margin horizontal pixel
|
||||
* 'marginY' => 5, // Margin vertical pixel
|
||||
* 'quality' => 95, // JPEG image save quality
|
||||
* 'transparency' => 70, // Water mark image transparency ( other than PNG )
|
||||
* 'targetType' => IMG_GIF|IMG_JPG|IMG_PNG|IMG_WBMP, // Target image formats ( bit-field )
|
||||
* 'targetMinPixel' => 200, // Target image minimum pixel size
|
||||
* 'interlace' => IMG_GIF|IMG_JPG, // Set interlacebit image formats ( bit-field )
|
||||
* 'offDropWith' => null, // Enabled by default. To disable it if it is dropped with pressing the meta key
|
||||
* // Alt: 8, Ctrl: 4, Meta: 2, Shift: 1 - sum of each value
|
||||
* // In case of using any key, specify it as an array
|
||||
* 'onDropWith' => null // Disabled by default. To enable it if it is dropped with pressing the meta key
|
||||
* // Alt: 8, Ctrl: 4, Meta: 2, Shift: 1 - sum of each value
|
||||
* // In case of using any key, specify it as an array
|
||||
* )
|
||||
* ),
|
||||
* // each volume configure (optional)
|
||||
* 'roots' => array(
|
||||
* array(
|
||||
* 'driver' => 'LocalFileSystem',
|
||||
* 'path' => '/path/to/files/',
|
||||
* 'URL' => 'http://localhost/to/files/'
|
||||
* 'plugin' => array(
|
||||
* 'Watermark' => array(
|
||||
* 'enable' => true, // For control by volume driver
|
||||
* 'source' => 'logo.png', // Path to Water mark image
|
||||
* 'ratio' => 0.2, // Ratio to original image (ratio > 0 and ratio <= 1)
|
||||
* 'position' => 'RB', // Position L(eft)/C(enter)/R(ight) and T(op)/M(edium)/B(ottom)
|
||||
* 'marginX' => 5, // Margin horizontal pixel
|
||||
* 'marginY' => 5, // Margin vertical pixel
|
||||
* 'quality' => 95, // JPEG image save quality
|
||||
* 'transparency' => 70, // Water mark image transparency ( other than PNG )
|
||||
* 'targetType' => IMG_GIF|IMG_JPG|IMG_PNG|IMG_WBMP, // Target image formats ( bit-field )
|
||||
* 'targetMinPixel' => 200, // Target image minimum pixel size
|
||||
* 'interlace' => IMG_GIF|IMG_JPG, // Set interlacebit image formats ( bit-field )
|
||||
* 'offDropWith' => null, // Enabled by default. To disable it if it is dropped with pressing the meta key
|
||||
* // Alt: 8, Ctrl: 4, Meta: 2, Shift: 1 - sum of each value
|
||||
* // In case of using any key, specify it as an array
|
||||
* 'onDropWith' => null // Disabled by default. To enable it if it is dropped with pressing the meta key
|
||||
* // Alt: 8, Ctrl: 4, Meta: 2, Shift: 1 - sum of each value
|
||||
* // In case of using any key, specify it as an array
|
||||
* )
|
||||
* )
|
||||
* )
|
||||
* )
|
||||
* );
|
||||
*
|
||||
* @package elfinder
|
||||
* @author Naoki Sawada
|
||||
* @license New BSD
|
||||
*/
|
||||
class elFinderPluginWatermark extends elFinderPlugin {
|
||||
|
||||
private $watermarkImgInfo = null;
|
||||
|
||||
public function __construct($opts) {
|
||||
$defaults = array(
|
||||
'enable' => true, // For control by volume driver
|
||||
'source' => 'logo.png', // Path to Water mark image
|
||||
'ratio' => 0.2, // Ratio to original image (ratio > 0 and ratio <= 1)
|
||||
'position' => 'RB', // Position L(eft)/C(enter)/R(ight) and T(op)/M(edium)/B(ottom)
|
||||
'marginX' => 5, // Margin horizontal pixel
|
||||
'marginY' => 5, // Margin vertical pixel
|
||||
'quality' => 95, // JPEG image save quality
|
||||
'transparency' => 70, // Water mark image transparency ( other than PNG )
|
||||
'targetType' => IMG_GIF|IMG_JPG|IMG_PNG|IMG_WBMP, // Target image formats ( bit-field )
|
||||
'targetMinPixel' => 200, // Target image minimum pixel size
|
||||
'interlace' => IMG_GIF|IMG_JPG, // Set interlacebit image formats ( bit-field )
|
||||
'offDropWith' => null, // To disable it if it is dropped with pressing the meta key
|
||||
// Alt: 8, Ctrl: 4, Meta: 2, Shift: 1 - sum of each value
|
||||
// In case of using any key, specify it as an array
|
||||
'marginRight' => 0, // Deprecated - marginX should be used
|
||||
'marginBottom' => 0, // Deprecated - marginY should be used
|
||||
'disableWithContentSaveId' => true // Disable on URL upload with post data "contentSaveId"
|
||||
);
|
||||
|
||||
$this->opts = array_merge($defaults, $opts);
|
||||
|
||||
}
|
||||
|
||||
public function onUpLoadPreSave(&$thash, &$name, $src, $elfinder, $volume) {
|
||||
$opts = $this->getCurrentOpts($volume);
|
||||
|
||||
if (! $this->iaEnabled($opts, $elfinder)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$imageType = null;
|
||||
$srcImgInfo = null;
|
||||
if (extension_loaded('fileinfo') && function_exists('mime_content_type')) {
|
||||
$mime = mime_content_type($src);
|
||||
if (substr($mime, 0, 5) !== 'image') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (extension_loaded('exif') && function_exists('exif_imagetype')) {
|
||||
$imageType = exif_imagetype($src);
|
||||
} else {
|
||||
$srcImgInfo = getimagesize($src);
|
||||
if ($srcImgInfo === false) {
|
||||
return false;
|
||||
}
|
||||
$imageType = $srcImgInfo[2];
|
||||
}
|
||||
|
||||
// check target image type
|
||||
$imgTypes = array(
|
||||
IMAGETYPE_GIF => IMG_GIF,
|
||||
IMAGETYPE_JPEG => IMG_JPEG,
|
||||
IMAGETYPE_PNG => IMG_PNG,
|
||||
IMAGETYPE_BMP => IMG_WBMP,
|
||||
IMAGETYPE_WBMP => IMG_WBMP
|
||||
);
|
||||
if (! isset($imgTypes[$imageType]) || ! ($opts['targetType'] & $imgTypes[$imageType])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// check Animation Gif
|
||||
if ($imageType === IMAGETYPE_GIF && elFinder::isAnimationGif($src)) {
|
||||
return false;
|
||||
}
|
||||
// check Animation Png
|
||||
if ($imageType === IMAGETYPE_PNG && elFinder::isAnimationPng($src)) {
|
||||
return false;
|
||||
}
|
||||
// check water mark image
|
||||
if (! file_exists($opts['source'])) {
|
||||
$opts['source'] = dirname(__FILE__) . "/" . $opts['source'];
|
||||
}
|
||||
if (is_readable($opts['source'])) {
|
||||
$watermarkImgInfo = getimagesize($opts['source']);
|
||||
if (! $watermarkImgInfo) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! $srcImgInfo) {
|
||||
$srcImgInfo = getimagesize($src);
|
||||
}
|
||||
|
||||
$watermark = $opts['source'];
|
||||
$quality = $opts['quality'];
|
||||
$transparency = $opts['transparency'];
|
||||
|
||||
// check target image size
|
||||
if ($opts['targetMinPixel'] > 0 && $opts['targetMinPixel'] > min($srcImgInfo[0], $srcImgInfo[1])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$watermark_width = $watermarkImgInfo[0];
|
||||
$watermark_height = $watermarkImgInfo[1];
|
||||
|
||||
// Specified as a ratio to the image size
|
||||
if ($opts['ratio'] && $opts['ratio'] > 0 && $opts['ratio'] <= 1) {
|
||||
$maxW = $srcImgInfo[0] * $opts['ratio'] - ($opts['marginX'] * 2);
|
||||
$maxH = $srcImgInfo[1] * $opts['ratio'] - ($opts['marginY'] * 2);
|
||||
$dx = $dy = 0;
|
||||
if (($maxW >= $watermarkImgInfo[0] && $maxH >= $watermarkImgInfo[0]) || ($maxW <= $watermarkImgInfo[0] && $maxH <= $watermarkImgInfo[0])) {
|
||||
$dx = abs($srcImgInfo[0] - $watermarkImgInfo[0]);
|
||||
$dy = abs($srcImgInfo[1] - $watermarkImgInfo[1]);
|
||||
} else if ($maxW < $watermarkImgInfo[0]) {
|
||||
$dx = -1;
|
||||
} else {
|
||||
$dy = -1;
|
||||
}
|
||||
if ($dx < $dy) {
|
||||
$ww = $maxW;
|
||||
$wh = $watermarkImgInfo[1] * ($ww / $watermarkImgInfo[0]);
|
||||
} else {
|
||||
$wh = $maxH;
|
||||
$ww = $watermarkImgInfo[0] * ($wh / $watermarkImgInfo[1]);
|
||||
}
|
||||
$watermarkImgInfo[0] = $ww;
|
||||
$watermarkImgInfo[1] = $wh;
|
||||
} else {
|
||||
$opts['ratio'] = null;
|
||||
}
|
||||
|
||||
$opts['position'] = strtoupper($opts['position']);
|
||||
|
||||
// Set vertical position
|
||||
if (strpos($opts['position'], 'T') !== false) {
|
||||
// Top
|
||||
$dest_x = $opts['marginX'];
|
||||
} else if (strpos($opts['position'], 'M') !== false) {
|
||||
// Middle
|
||||
$dest_x = ($srcImgInfo[0] - $watermarkImgInfo[0]) / 2;
|
||||
} else {
|
||||
// Bottom
|
||||
$dest_x = $srcImgInfo[0] - $watermarkImgInfo[0] - max($opts['marginBottom'], $opts['marginX']);
|
||||
}
|
||||
|
||||
// Set horizontal position
|
||||
if (strpos($opts['position'], 'L') !== false) {
|
||||
// Left
|
||||
$dest_y = $opts['marginY'];
|
||||
} else if (strpos($opts['position'], 'C') !== false) {
|
||||
// Middle
|
||||
$dest_y = ($srcImgInfo[1] - $watermarkImgInfo[1]) / 2;
|
||||
} else {
|
||||
// Right
|
||||
$dest_y = $srcImgInfo[1] - $watermarkImgInfo[1] - max($opts['marginRight'], $opts['marginY']);
|
||||
}
|
||||
|
||||
|
||||
// check interlace
|
||||
$opts['interlace'] = ($opts['interlace'] & $imgTypes[$imageType]);
|
||||
|
||||
if (class_exists('Imagick', false)) {
|
||||
return $this->watermarkPrint_imagick($src, $watermark, $dest_x, $dest_y, $quality, $transparency, $watermarkImgInfo, $opts);
|
||||
} else {
|
||||
elFinder::expandMemoryForGD(array($watermarkImgInfo, $srcImgInfo));
|
||||
return $this->watermarkPrint_gd($src, $watermark, $dest_x, $dest_y, $quality, $transparency, $watermarkImgInfo, $srcImgInfo, $opts);
|
||||
}
|
||||
}
|
||||
|
||||
private function watermarkPrint_imagick($src, $watermark, $dest_x, $dest_y, $quality, $transparency, $watermarkImgInfo, $opts) {
|
||||
|
||||
try {
|
||||
|
||||
// Open the original image
|
||||
$img = new Imagick($src);
|
||||
|
||||
// Open the watermark
|
||||
$watermark = new Imagick($watermark);
|
||||
|
||||
// zoom
|
||||
if ($opts['ratio']) {
|
||||
$watermark->scaleImage($watermarkImgInfo[0], $watermarkImgInfo[1]);
|
||||
}
|
||||
|
||||
// Set transparency
|
||||
if (strtoupper($watermark->getImageFormat()) !== 'PNG') {
|
||||
$watermark->setImageOpacity($transparency/100);
|
||||
}
|
||||
|
||||
// Overlay the watermark on the original image
|
||||
$img->compositeImage($watermark, imagick::COMPOSITE_OVER, $dest_x, $dest_y);
|
||||
|
||||
// Set quality
|
||||
if (strtoupper($img->getImageFormat()) === 'JPEG') {
|
||||
$img->setImageCompression(imagick::COMPRESSION_JPEG);
|
||||
$img->setCompressionQuality($quality);
|
||||
}
|
||||
|
||||
// set interlace
|
||||
$opts['interlace'] && $img->setInterlaceScheme(Imagick::INTERLACE_PLANE);
|
||||
|
||||
$result = $img->writeImage($src);
|
||||
|
||||
$img->clear();
|
||||
$img->destroy();
|
||||
$watermark->clear();
|
||||
$watermark->destroy();
|
||||
|
||||
return $result ? true : false;
|
||||
} catch (Exception $e) {
|
||||
$ermsg = $e->getMessage();
|
||||
$ermsg && trigger_error($ermsg);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private function watermarkPrint_gd($src, $watermark, $dest_x, $dest_y, $quality, $transparency, $watermarkImgInfo, $srcImgInfo, $opts) {
|
||||
|
||||
$watermark_width = $watermarkImgInfo[0];
|
||||
$watermark_height = $watermarkImgInfo[1];
|
||||
|
||||
$ermsg = '';
|
||||
switch ($watermarkImgInfo['mime']) {
|
||||
case 'image/gif':
|
||||
if (imagetypes() & IMG_GIF) {
|
||||
$oWatermarkImg = imagecreatefromgif($watermark);
|
||||
} else {
|
||||
$ermsg = 'GIF images are not supported as watermark image';
|
||||
}
|
||||
break;
|
||||
case 'image/jpeg':
|
||||
if (imagetypes() & IMG_JPG) {
|
||||
$oWatermarkImg = imagecreatefromjpeg($watermark) ;
|
||||
} else {
|
||||
$ermsg = 'JPEG images are not supported as watermark image';
|
||||
}
|
||||
break;
|
||||
case 'image/png':
|
||||
if (imagetypes() & IMG_PNG) {
|
||||
$oWatermarkImg = imagecreatefrompng($watermark) ;
|
||||
} else {
|
||||
$ermsg = 'PNG images are not supported as watermark image';
|
||||
}
|
||||
break;
|
||||
case 'image/wbmp':
|
||||
if (imagetypes() & IMG_WBMP) {
|
||||
$oWatermarkImg = imagecreatefromwbmp($watermark);
|
||||
} else {
|
||||
$ermsg = 'WBMP images are not supported as watermark image';
|
||||
}
|
||||
break;
|
||||
default:
|
||||
$oWatermarkImg = false;
|
||||
$ermsg = $watermarkImgInfo['mime'].' images are not supported as watermark image';
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (! $ermsg) {
|
||||
// zoom
|
||||
if ($opts['ratio']) {
|
||||
$tmpImg = imagecreatetruecolor($watermarkImgInfo[0], $watermarkImgInfo[1]);
|
||||
imagealphablending($tmpImg, false);
|
||||
imagesavealpha($tmpImg, true);
|
||||
imagecopyresampled($tmpImg, $oWatermarkImg, 0, 0, 0, 0, $watermarkImgInfo[0], $watermarkImgInfo[1], imagesx($oWatermarkImg), imagesy($oWatermarkImg));
|
||||
imageDestroy($oWatermarkImg);
|
||||
$oWatermarkImg = $tmpImg;
|
||||
$tmpImg = null;
|
||||
}
|
||||
|
||||
switch ($srcImgInfo['mime']) {
|
||||
case 'image/gif':
|
||||
if (imagetypes() & IMG_GIF) {
|
||||
$oSrcImg = imagecreatefromgif($src);
|
||||
} else {
|
||||
$ermsg = 'GIF images are not supported as source image';
|
||||
}
|
||||
break;
|
||||
case 'image/jpeg':
|
||||
if (imagetypes() & IMG_JPG) {
|
||||
$oSrcImg = imagecreatefromjpeg($src) ;
|
||||
} else {
|
||||
$ermsg = 'JPEG images are not supported as source image';
|
||||
}
|
||||
break;
|
||||
case 'image/png':
|
||||
if (imagetypes() & IMG_PNG) {
|
||||
$oSrcImg = imagecreatefrompng($src) ;
|
||||
} else {
|
||||
$ermsg = 'PNG images are not supported as source image';
|
||||
}
|
||||
break;
|
||||
case 'image/wbmp':
|
||||
if (imagetypes() & IMG_WBMP) {
|
||||
$oSrcImg = imagecreatefromwbmp($src);
|
||||
} else {
|
||||
$ermsg = 'WBMP images are not supported as source image';
|
||||
}
|
||||
break;
|
||||
default:
|
||||
$oSrcImg = false;
|
||||
$ermsg = $srcImgInfo['mime'].' images are not supported as source image';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($ermsg || false === $oSrcImg || false === $oWatermarkImg) {
|
||||
$ermsg && trigger_error($ermsg);
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($srcImgInfo['mime'] === 'image/png') {
|
||||
if (function_exists('imagecolorallocatealpha')) {
|
||||
$bg = imagecolorallocatealpha($oSrcImg, 255, 255, 255, 127);
|
||||
imagefill($oSrcImg, 0, 0 , $bg);
|
||||
}
|
||||
}
|
||||
|
||||
if ($watermarkImgInfo['mime'] === 'image/png') {
|
||||
imagecopy($oSrcImg, $oWatermarkImg, $dest_x, $dest_y, 0, 0, $watermark_width, $watermark_height);
|
||||
} else {
|
||||
imagecopymerge($oSrcImg, $oWatermarkImg, $dest_x, $dest_y, 0, 0, $watermark_width, $watermark_height, $transparency);
|
||||
}
|
||||
|
||||
// set interlace
|
||||
$opts['interlace'] && imageinterlace($oSrcImg, true);
|
||||
|
||||
switch ($srcImgInfo['mime']) {
|
||||
case 'image/gif':
|
||||
imagegif($oSrcImg, $src);
|
||||
break;
|
||||
case 'image/jpeg':
|
||||
imagejpeg($oSrcImg, $src, $quality);
|
||||
break;
|
||||
case 'image/png':
|
||||
if (function_exists('imagesavealpha') && function_exists('imagealphablending')) {
|
||||
imagealphablending($oSrcImg, false);
|
||||
imagesavealpha($oSrcImg, true);
|
||||
}
|
||||
imagepng($oSrcImg, $src);
|
||||
break;
|
||||
case 'image/wbmp':
|
||||
imagewbmp($oSrcImg, $src);
|
||||
break;
|
||||
}
|
||||
|
||||
imageDestroy($oSrcImg);
|
||||
imageDestroy($oWatermarkImg);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 3.5 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.2 KiB |
Reference in New Issue
Block a user