<?php
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
* Version 0.1
* This is a gallery object, used to manage image gallery
* and permission access to directories.
* This can create thumbnails thanks to the GD library
*
*/
define('GALLERY_SORT_FILETYPE_ASC', 0x01);
define('GALLERY_SORT_FILETYPE_DESC', 0x02);
define('GALLERY_SORT_FILENAME_ASC', 0x04);
define('GALLERY_SORT_FILENAME_DESC', 0x08);
define('GALLERY_SORT_FILEMTIME_ASC', 0x10);
define('GALLERY_SORT_FILEMTIME_DESC', 0x20);
define('GALLERY_SORT_FILESIZE_ASC', 0x40);
define('GALLERY_SORT_FILESIZE_DESC', 0x80);
Class Gallery {
private $Conn; /* Must be a Connect object */
private $root_directory;
private $cache_directory;
private $use_cache;
private $parent_folder_name;
private $filter_filename_regexp;
private $downloadable_filename_regexp;
private $sort_type;
private $privileges_table;
private $current_user;
private $error_msg;
function __construct() {
$this->Gallery();
}
function Gallery() {
/* ---------------------------------------------------------------------------
* Constructor
* ------------------------------------------------------------------------ */
if ((defined('GALLERY_ROOT'))
&& (is_dir(GALLERY_ROOT)))
$this->root_directory = GALLERY_ROOT;
else
$this->root_directory = NULL;
if ((defined('GALLERY_CACHE_DIR'))
&& (is_dir(GALLERY_CACHE_DIR)))
$this->cache_directory = GALLERY_CACHE_DIR;
else
$this->cache_directory = NULL;
if (defined('GALLERY_USE_CACHE'))
$this->use_cache = GALLERY_USE_CACHE;
else
$this->use_cache = true;
if (defined('GALLERY_PARENT_FOLDER_NAME'))
$this->parent_folder_name = GALLERY_PARENT_FOLDER_NAME;
else
$this->parent_folder_name = NULL;
if (defined('GALLERY_FILTER_FILENAME'))
$this->filter_filename_regexp = GALLERY_FILTER_FILENAME;
else
$this->filter_filename_regexp = NULL;
if (defined('GALLERY_DOWNLOADABLE_FILENAME'))
$this->downloadable_filename_regexp = GALLERY_DOWNLOADABLE_FILENAME;
else
$this->downloadable_filename_regexp = NULL;
if (defined('GALLERY_PRIVILEGE_TABLE'))
$this->privileges_table = GALLERY_PRIVILEGE_TABLE;
else
$this->privileges_table = NULL;
$this->sort_type = NULL;
$this->Conn = NULL;
$this->error_msg = array();
}
function setConnect(&$Conn) {
if ((is_object($Conn))
&& (get_class($Conn) == "Connect")) {
$this->Conn = $Conn;
return true;
}
return false;
}
function setUser($user) {
$this->current_user = $user;
}
function setSortType($sort_type) {
$this->sort_type = $sort_type;
}
function isConnected() {
return (is_object($this->Conn))
&& (get_class($this->Conn) == "Connect");
}
function canGetPrivileges() {
/* ---------------------------------------------------------------------------
* PRIVATE
* Check if privileges can be fetched from SQL database
*
* @return boolean
* ------------------------------------------------------------------------ */
return ($this->isConnected() && !is_null($this->privileges_table));
}
function cleanPath($path) {
/* ---------------------------------------------------------------------------
* Convert any // to /
* Also, remove the / at the end, if exists
*
* @param string a path
* @return string
* ------------------------------------------------------------------------ */
$p = preg_replace("//{2,}/", "/", $path);
$len = strlen($p);
if ($len > 0) {
if ($p{$len-1} == "/")
$p = substr($p, 0, $len-1);
}
if ($p === "")
$p = "/";
return $p;
}
function safePath($path) {
/* ---------------------------------------------------------------------------
* Strip any ..
*
* @param string a path
* @return string
* ------------------------------------------------------------------------ */
return $this->cleanPath(str_replace("..", "", $path));
}
function safeMkdir($path, $mode = 0700) {
/* ---------------------------------------------------------------------------
* Safely create directories recursively
*
* @param string a path
* @param octal mode
* @return boolean
* ------------------------------------------------------------------------ */
if (is_dir($path))
return true;
$p = dirname($path);
if ($this->safeMkdir($p, $mode)) {
if (is_writeable($p))
return mkdir($path, $mode);
else
array_push($this->error_msg, "safeMkdir() : " . $p . " is not writeable");
}
return false;
}
function parentPath($path) {
/* ---------------------------------------------------------------------------
* PRIVATE
* Get the parent directory of a directory
*
* @param string a path
* @return string the parent path or the input path if no parent exists
* ------------------------------------------------------------------------ */
$len = strlen($path);
if ($len == 0)
return "/";
if ($path{$len-1} == "/")
$p = substr($path, 0, $len-1);
else
$p = $path;
$pos = strrpos($p, "/");
if ($pos !== false)
$p = substr($p, 0, $pos);
if ($p === "")
$p = "/";
return $p;
}
function isFiltered($filename) {
/* ---------------------------------------------------------------------------
* PRIVATE
* Determine if the following filename must filtered or not
*
* @param string a path
* @return boolean
* ------------------------------------------------------------------------ */
if (is_null($this->filter_filename_regexp)) {
// Secure by default
return false;
}
else if (!ereg($this->filter_filename_regexp, $filename)) {
return false;
}
return true;
}
function isDownloadable($filename) {
/* ---------------------------------------------------------------------------
* PRIVATE
* Determine if the following filename is downloadable or not
*
* @param string a path
* @return boolean
* ------------------------------------------------------------------------ */
if (is_null($this->downloadable_filename_regexp)) {
// Secure by default
return false;
}
else if (!ereg($this->downloadable_filename_regexp, $filename)) {
return false;
}
return true;
}
function isImageFile($full_path) {
/* ---------------------------------------------------------------------------
* PRIVATE
* Determine if the following file is an image
*
* @param string a full path
* @return boolean
* ------------------------------------------------------------------------ */
return (file_exists($full_path))
&& (is_file($full_path))
&& (@getimagesize($full_path) !== false);
}
function getLastErrorMessage() {
/* ---------------------------------------------------------------------------
* Return the last error message
*
* @return string
* ------------------------------------------------------------------------ */
$nb_error = count($this->error_msg);
if ($nb_error > 0)
return $this->error_msg[$nb_error-1];
return NULL;
}
function getStackErrorMessage() {
/* ---------------------------------------------------------------------------
* Return the stack errors
*
* @return array
* ------------------------------------------------------------------------ */
return $this->error_msg;
}
function getFolderAccess($relative_folderpath, $username = NULL, $inherit_only = false) {
/* ---------------------------------------------------------------------------
* PRIVATE
* Determine the permission access to the given folder
*
* @param string the sub folder relative to the root directory
* @param string permission by username (PRIVATE USE ONLY)
* @param boolean get only the folder inherit permission (PRIVATE USE ONLY)
* @return array or NULL
* ------------------------------------------------------------------------ */
if (!$this->canGetPrivileges()) {
array_push($this->error_msg, "getFolderAccess() : Privileges cannot be fetched. Default to deny.");
return NULL;
}
// Remove attempt to open parent directory (..)
$safe_folderpath = $this->safePath($relative_folderpath);
if (is_null($username)) {
// Anonymous user
$sql = "SELECT permit, visible, inherit " .
"FROM " . $this->privileges_table . " " .
"WHERE username IS NULL " .
"AND path = " . STRING_SQL($safe_folderpath) . " " .
"AND enable = 1 " .
($inherit_only ? "AND inherit = 1" : "");
}
else {
// Authenticated user
$sql = "SELECT permit, visible, inherit " .
"FROM " . $this->privileges_table . " " .
"WHERE username = " . STRING_SQL($username) . " " .
"AND path = " . STRING_SQL($safe_folderpath) . " " .
"AND enable = 1 " .
($inherit_only ? "AND inherit = 1" : "");
}
if ($result = $this->Conn->QueryDB($sql)) {
if ($cur = $this->Conn->CursorDB($result)) {
$this->Conn->FreeDB($result);
return $cur;
}
else {
$this->Conn->FreeDB($result);
$parent_folder = $this->parentPath($relative_folderpath);
if ($parent_folder !== $relative_folderpath) {
// Get folder access from parent folder
return $this->getFolderAccess($parent_folder, $username, true);
}
}
}
return NULL;
}
function getVisibleFolders($relative_paths, $username = NULL) {
/* ---------------------------------------------------------------------------
* PRIVATE
* Determine all the visible files and folders
*
* @param array sub folders relative to the root directory
* @param string permission by username (PRIVATE USE ONLY)
* @return array array of files that can be visible
* ------------------------------------------------------------------------ */
return $this->getVisibleOrHiddenFolders($relative_paths, 1, $username);
}
function getHiddenFolders($relative_paths, $username = NULL) {
/* ---------------------------------------------------------------------------
* PRIVATE
* Determine all the hidden files and folders
*
* @param array sub folders relative to the root directory
* @param string permission by username (PRIVATE USE ONLY)
* @return array array of files that must be hidden
* ------------------------------------------------------------------------ */
return $this->getVisibleOrHiddenFolders($relative_paths, 0, $username);
}
function getVisibleOrHiddenFolders($relative_paths, $visible, $username = NULL) {
/* ---------------------------------------------------------------------------
* PRIVATE
* Determine all the hidden/visible files and folders
*
* @param array sub folders relative to the root directory
* @param string permission by username (PRIVATE USE ONLY)
* @return array array of files
* ------------------------------------------------------------------------ */
if (!$this->canGetPrivileges()) {
array_push($this->error_msg, ($visible ? "getVisibleFolders()" : "getHiddenFolders()") . " : " .
"Privileges cannot be fetched. Default to deny.");
return NULL;
}
$sql_where_path = array();
foreach ($relative_paths as $path) {
array_push($sql_where_path, STRING_SQL($this->safePath($path)));
}
if (is_null($username)) {
// Anonymous user
$sql = "SELECT path " .
"FROM " . $this->privileges_table . " " .
"WHERE username IS NULL " .
"AND path IN (" . join(", ", $sql_where_path) . ") " .
"AND visible = " . $visible . " " .
"AND enable = 1";
}
else {
// Authenticated user
$sql = "SELECT path " .
"FROM " . $this->privileges_table . " " .
"WHERE username = " . STRING_SQL($username) . " " .
"AND path IN (" . join(", ", $sql_where_path) . ") " .
"AND visible = " . $visible . " " .
"AND enable = 1";
}
if ($result = $this->Conn->QueryDB($sql)) {
$arr_result = array();
while ($cur = $this->Conn->CursorDB($result)) {
array_push($arr_result, $cur['path']);
}
$this->Conn->FreeDB($result);
return $arr_result;
}
return NULL;
}
function getElements($relative_folderpath) {
/* ---------------------------------------------------------------------------
* Get an array of image fullpath
*
* @param string the sub folder relative to the root directory
* @param boolean include or not the .. parent folder
* @return array images path or NULL
* ------------------------------------------------------------------------ */
// Remove attempt to open parent directory (..)
$safe_folderpath = $this->safePath($relative_folderpath);
if (is_null($this->root_directory)) {
array_push($this->error_msg, "getElements() : Please, set the GALLERY_ROOT constant to a valid folder.");
return NULL;
}
if (!is_dir($this->root_directory)) {
array_push($this->error_msg, "getElements() : GALLERY_ROOT " . $this->root_directory . " is not a valid directory.");
return NULL;
}
if (!is_dir($this->root_directory . "/" . $safe_folderpath)) {
array_push($this->error_msg, "getElements() : " . $safe_folderpath . " is not a valid directory.");
return NULL;
}
if (!is_readable($this->root_directory . "/" . $safe_folderpath)) {
$this->error_msg = "getElements() : " . $safe_folderpath . " is not a readable directory.";
return NULL;
}
if (!is_null($this->current_user)) {
// Authenticated user
$permission = $this->getFolderAccess($relative_folderpath, $this->current_user);
if (is_null($permission)) {
// If no permision has been set for the user, get the permission for guest
$permission = $this->getFolderAccess($relative_folderpath);
}
}
else
$permission = $this->getFolderAccess($relative_folderpath);
if (is_null($permission)) {
// No permission has been set for the given folder
// Secure by default
array_push($this->error_msg, "getElements() : No permission has been set for " . $safe_folderpath . " . " .
"Default to deny.");
return NULL;
}
if (!$permission['permit']) {
// This folder has been explicitly denied to the current user
array_push($this->error_msg, "getElements() : Permission denied to access " . $safe_folderpath . " .");
return NULL;
}
$d = opendir($this->root_directory . "/" . $safe_folderpath);
if ($d === false) {
array_push($this->error_msg, "getElements() : Failed to open directory " . $safe_folderpath . " .");
return NULL;
}
$files = array();
$folder_paths = array();
while (($file = readdir($d)) !== false) {
array_push($files, $file);
if ($file != "..") {
// Ignore parent directory
array_push($folder_paths, $this->cleanPath($safe_folderpath . "/" . $file));
}
}
closedir($d);
// If the current permission is "visible" and "inherit",
// it means that the current directory content is all visible
if ((!$permission['visible'])
|| (!$permission['inherit'])) {
// For each folder, determine only the visible ones
if (!is_null($this->current_user)) {
// Authenticated user
$orig_folder_paths = $folder_paths;
$folder_paths = $this->getVisibleFolders($orig_folder_paths, $this->current_user);
if ((is_null($folder_paths))
|| (count($folder_paths) <= 0)) {
// If no visible folders has been set for the user, get the folders for guest
$folder_paths = $this->getVisibleFolders($orig_folder_paths);
}
}
else
$folder_paths = $this->getVisibleFolders($folder_paths);
if ((is_null($folder_paths))
|| (count($folder_paths) <= 0)) {
array_push($this->error_msg, "getElements() : No files, nor directories are visible in " . $safe_folderpath . " .");
return NULL;
}
}
else {
// However, some folder or file can be explicitly hidden
if (!is_null($this->current_user)) {
// Authenticated user
$hidden_paths = $this->getHiddenFolders($folder_paths, $this->current_user);
if ((is_null($hidden_paths))
|| (count($hidden_paths) <= 0)) {
// If no hidden folders has been set for the user, get the folders for guest
$hidden_paths = $this->getHiddenFolders($folder_paths);
}
}
else
$hidden_paths = $this->getHiddenFolders($folder_paths);
if ((count($folder_paths) > 0)
&& (count($hidden_paths) > 0)) {
// Remove the hidden ones
$folder_paths = array_diff($folder_paths, $hidden_paths);
}
}
$arr_result = array();
foreach ($files as $file) {
if (($file != ".") && (($file != "..") || $safe_folderpath != "/")) {
if ($file == "..") {
// Get the parent directory
$p = $this->parentPath($safe_folderpath);
if (is_null($this->parent_folder_name))
$entry = $file;
else
$entry = $this->parent_folder_name;
$ok = true;
}
else {
$p = $this->cleanPath($safe_folderpath . "/" . $file);
$entry = $file;
// If the given path is visible, ok = true
// else the file or folder is hidden
$ok = in_array($p, $folder_paths);
}
if ($ok) {
$info = @getimagesize($this->root_directory . "/" . $p);
$is_file = is_file($this->root_directory . "/" . $p);
$is_image = is_file($this->root_directory . "/" . $p)
&& ($info !== false);
$is_dir = is_dir($this->root_directory . "/" . $p);
if ($is_image) {
$width = $info[0];
$height = $info[1];
}
else {
$width = NULL;
$height = NULL;
}
$is_downloadable = true;
if (!$is_dir && !$is_image) {
// Check if the file (other than an image) is filtered or not
$ok = $this->isFiltered($entry);
$is_downloadable = $this->isDownloadable($entry);
}
if ($ok) {
array_push($arr_result,
array(
"fullpath" => $this->cleanPath($this->root_directory . "/" . $p),
"path" => $this->cleanPath($p),
"entry" => $entry,
"filename" => $file,
"is_file" => $is_file,
"is_image" => $is_image,
"width" => $width,
"height" => $height,
"is_dir" => $is_dir,
"is_downloadable" => $is_downloadable,
"filesize" => filesize($this->root_directory . "/" . $p),
"filemtime" => filemtime($this->root_directory . "/" . $p),
"filetype" => filetype($this->root_directory . "/" . $p)
)
);
}
}
}
}
if ((count($arr_result) > 0)
&& (!is_null($this->sort_type))) {
if (($this->sort_type & GALLERY_SORT_FILETYPE_ASC)
|| ($this->sort_type & GALLERY_SORT_FILETYPE_DESC)) {
$arr_sort = array();
foreach ($arr_result as $result) {
array_push($arr_sort, $result["filetype"]);
}
if ($this->sort_type & GALLERY_SORT_FILETYPE_ASC)
array_multisort($arr_sort, SORT_ASC, $arr_result);
else if ($this->sort_type & GALLERY_SORT_FILETYPE_DESC)
array_multisort($arr_sort, SORT_DESC, $arr_result);
}
if (($this->sort_type & GALLERY_SORT_FILENAME_ASC)
|| ($this->sort_type & GALLERY_SORT_FILENAME_DESC)) {
$arr_sort = array();
foreach ($arr_result as $result) {
array_push($arr_sort, $result["filename"]);
}
if ($this->sort_type & GALLERY_SORT_FILENAME_ASC)
array_multisort($arr_sort, SORT_ASC, $arr_result);
else if ($this->sort_type & GALLERY_SORT_FILENAME_DESC)
array_multisort($arr_sort, SORT_DESC, $arr_result);
}
if (($this->sort_type & GALLERY_SORT_FILEMTIME_ASC)
|| ($this->sort_type & GALLERY_SORT_FILEMTIME_DESC)) {
$arr_sort = array();
foreach ($arr_result as $result) {
array_push($arr_sort, $result["filemtime"]);
}
if ($this->sort_type & GALLERY_SORT_FILEMTIME_ASC)
array_multisort($arr_sort, SORT_ASC, $arr_result);
else if ($this->sort_type & GALLERY_SORT_FILEMTIME_DESC)
array_multisort($arr_sort, SORT_DESC, $arr_result);
}
if (($this->sort_type & GALLERY_SORT_FILESIZE_ASC)
|| ($this->sort_type & GALLERY_SORT_FILESIZE_DESC)) {
$arr_sort = array();
foreach ($arr_result as $result) {
array_push($arr_sort, $result["filesize"]);
}
if ($this->sort_type & GALLERY_SORT_FILESIZE_ASC)
array_multisort($arr_sort, SORT_ASC, $arr_result);
else if ($this->sort_type & GALLERY_SORT_FILESIZE_DESC)
array_multisort($arr_sort, SORT_DESC, $arr_result);
}
}
return $arr_result;
}
function getThumbnails($relative_folderpath, $width = 0, $height = 0) {
/* ---------------------------------------------------------------------------
* Get an array of thumbnail image fullpath
* if a thumbnail do not exists, it will be created
*
* @param string the sub folder relative to the root directory
* @param int the new width
* @param int the new height
* @return array images path or NULL
* ------------------------------------------------------------------------ */
if (is_null($this->cache_directory)) {
array_push($this->error_msg, "getThumbnails() : Please, set the GALLERY_CACHE_DIR constant to a valid folder.");
return NULL;
}
if (!is_dir($this->cache_directory)) {
array_push($this->error_msg, "getThumbnails() : GALLERY_CACHE_DIR " . $this->cache_directory . " is not a valid directory.");
return NULL;
}
if (($width <= 0) && ($height <= 0)) {
array_push($this->error_msg, "getThumbnails() : You must define thumbnails by width OR height");
return NULL;
}
if (($width > 0) && ($height > 0)) {
array_push($this->error_msg, "getThumbnails() : You must define thumbnails by width OR height, not both");
return NULL;
}
$elements = $this->getElements($relative_folderpath);
if (!is_null($elements)) {
foreach ($elements as $idx => $element) {
if ($element["is_image"]) {
// First, create directories inside the cache directory
if ($this->safeMkdir(
$this->cleanPath(
$this->cache_directory . "/" . dirname($element["path"])
)
)
) {
/*
$relative_th = dirname($element["path"]) . "/" .
"th_" .
($width > 0 ? $width : "W") ."x" . ($height > 0 ? $height : "H") . "_" .
basename($element["fullpath"]);
*/
$relative_th = $this->generateCacheFilename($element["path"], $width, $height);
$th = $this->cleanPath($this->cache_directory . "/" . $relative_th);
$elements[$idx]["th_path"] = $this->cleanPath($relative_th);
if ((!file_exists($th))
|| (!$this->use_cache)) {
// Generate a new thumbnail
if ($this->resizeImage($element["fullpath"], $th, $width, $height)) {
$elements[$idx]["th_fullpath"] = $th;
$elements[$idx]["th_filesize"] = filesize($th);
$info = getimagesize($th);
if ($info !== false) {
$elements[$idx]["th_width"] = $info[0];
$elements[$idx]["th_height"] = $info[1];
}
}
else {
array_push($this->error_msg, "getThumbnails() : " . $this->getLastErrorMessage());
return NULL;
}
}
else {
// Get the existing thumbnail
$elements[$idx]["th_fullpath"] = $th;
$elements[$idx]["th_filesize"] = filesize($th);
$info = @getimagesize($th);
if ($info !== false) {
$elements[$idx]["th_width"] = $info[0];
$elements[$idx]["th_height"] = $info[1];
}
}
}
}
}
reset($elements);
return $elements;
}
return NULL;
}
function getCacheFileInfo($relative_filepath) {
/* ---------------------------------------------------------------------------
* Get file information from the root directory
*
* @param string the file path relative to the root directory
* @return array or NULL
* ------------------------------------------------------------------------ */
if (is_null($this->cache_directory)) {
array_push($this->error_msg, "getCacheFileInfo() : Please, set the GALLERY_CACHE_DIR constant to a valid folder.");
return NULL;
}
if (!is_dir($this->cache_directory)) {
array_push($this->error_msg, "getCacheFileInfo() : GALLERY_CACHE_DIR " . $this->cache_directory . " is not a valid directory.");
return NULL;
}
$safe_filepath = $this->safePath($relative_filepath);
if (file_exists($this->cache_directory . "/" . $safe_filepath)) {
$is_file = is_file($this->cache_directory . "/" . $safe_filepath);
$is_image = false;
$width = NULL;
$height = NULL;
if ($is_file) {
$info = @getimagesize($this->cache_directory . "/" . $safe_filepath);
if ($info !== false) {
$is_image = true;
$width = $info[0];
$height = $info[1];
}
}
return array(
"fullpath" => $this->cleanPath($this->cache_directory . "/" . $safe_filepath),
"path" => $safe_filepath,
"filename" => basename($safe_filepath),
"is_file" => $is_file,
"is_image" => $is_image,
"width" => $width,
"height" => $height,
"filesize" => filesize($this->cache_directory . "/" . $safe_filepath),
"filemtime" => filemtime($this->cache_directory . "/" . $safe_filepath),
"filetype" => filetype($this->cache_directory . "/" . $safe_filepath)
);
}
return NULL;
}
function getFileInfo($relative_filepath) {
/* ---------------------------------------------------------------------------
* Get file information from the root directory
*
* @param string the file path relative to the root directory
* @return array or NULL
* ------------------------------------------------------------------------ */
if (is_null($this->root_directory)) {
array_push($this->error_msg, "getFileInfo() : Please, set the GALLERY_ROOT constant to a valid folder.");
return NULL;
}
if (!is_dir($this->root_directory)) {
array_push($this->error_msg, "getFileInfo() : GALLERY_ROOT " . $this->root_directory . " is not a valid directory.");
return NULL;
}
$safe_filepath = $this->safePath($relative_filepath);
if (file_exists($this->root_directory . "/" . $safe_filepath)) {
$is_file = is_file($this->root_directory . "/" . $safe_filepath);
$is_image = false;
$width = NULL;
$height = NULL;
if ($is_file) {
$info = @getimagesize($this->root_directory . "/" . $safe_filepath);
if ($info !== false) {
$is_image = true;
$width = $info[0];
$height = $info[1];
}
}
return array(
"fullpath" => $this->cleanPath($this->root_directory . "/" . $safe_filepath),
"path" => $safe_filepath,
"filename" => basename($safe_filepath),
"is_file" => $is_file,
"is_image" => $is_image,
"width" => $width,
"height" => $height,
"filesize" => filesize($this->root_directory . "/" . $safe_filepath),
"filemtime" => filemtime($this->root_directory . "/" . $safe_filepath),
"filetype" => filetype($this->root_directory . "/" . $safe_filepath)
);
}
return NULL;
}
function generateCacheFile($relative_filepath, $width = 0, $height = 0) {
/* ---------------------------------------------------------------------------
* Generate a cache file image from a file in the root directory
* and get information of the generated file
*
* @param string the file path relative to the root directory
* @param int the new width
* @param int the new height
* @return array or NULL
* ------------------------------------------------------------------------ */
if (is_null($this->root_directory)) {
array_push($this->error_msg, "generateCacheFile() : Please, set the GALLERY_ROOT constant to a valid folder.");
return NULL;
}
if (!is_dir($this->root_directory)) {
array_push($this->error_msg, "generateCacheFile() : GALLERY_ROOT " . $this->root_directory . " is not a valid directory.");
return NULL;
}
if (is_null($this->cache_directory)) {
array_push($this->error_msg, "generateCacheFile() : Please, set the GALLERY_CACHE_DIR constant to a valid folder.");
return NULL;
}
if (!is_dir($this->cache_directory)) {
array_push($this->error_msg, "generateCacheFile() : GALLERY_CACHE_DIR " . $this->cache_directory . " is not a valid directory.");
return NULL;
}
if (($width <= 0) && ($height <= 0)) {
array_push($this->error_msg, "generateCacheFile() : You must define thumbnails by width OR height");
return NULL;
}
if (($width > 0) && ($height > 0)) {
array_push($this->error_msg, "generateCacheFile() : You must define thumbnails by width OR height, not both");
return NULL;
}
$safe_filepath = $this->safePath($relative_filepath);
if ($this->isImageFile($this->root_directory . "/" . $safe_filepath)) {
// First, create directories inside the cache directory
if ($this->safeMkdir(
$this->cleanPath(
$this->cache_directory . "/" . dirname($safe_filepath)
)
)
) {
$relative_th = $this->generateCacheFilename($safe_filepath, $width, $height);
$th = $this->cleanPath($this->cache_directory . "/" . $relative_th);
if ((!file_exists($th))
|| (!$this->use_cache)) {
if ($this->resizeImage($this->root_directory . "/" . $safe_filepath, $th, $width, $height)) {
return $this->getCacheFileInfo($relative_th);
}
else {
array_push($this->error_msg, "generateCacheFile() : " . $this->getLastErrorMessage());
return NULL;
}
}
else {
return $this->getCacheFileInfo($relative_th);
}
}
}
return NULL;
}
function generateCacheFilename($relative_filepath, $width = 0, $height = 0) {
/* ---------------------------------------------------------------------------
* Simply generate a filename for the cache file
*
* @param string the file path relative to the root directory
* @param int the new width
* @param int the new height
* @return boolean
* ------------------------------------------------------------------------ */
$safe_filepath = $this->safePath($relative_filepath);
return dirname($safe_filepath) . "/" .
"th_" .
($width > 0 ? $width : "W") ."x" . ($height > 0 ? $height : "H") . "_" .
basename($safe_filepath);
}
function displayCacheFile($relative_filepath, $bufsize = 1024) {
/* ---------------------------------------------------------------------------
* Read and display a file from the cache directory
*
* @param string the file path relative to the cache directory
* @param int the size of the buffer, default : 1024
* @return boolean
* ------------------------------------------------------------------------ */
if (is_null($this->cache_directory)) {
array_push($this->error_msg, "displayCacheFile() : Please, set the GALLERY_CACHE_DIR constant to a valid folder.");
return false;
}
if (!is_dir($this->cache_directory)) {
array_push($this->error_msg, "displayCacheFile() : GALLERY_CACHE_DIR " . $this->cache_directory . " is not a valid directory.");
return false;
}
$safe_filepath = $this->safePath($relative_filepath);
// Get permission for the current folder
$relative_folderpath = $this->parentPath($safe_filepath);
if (!is_null($this->current_user)) {
// Authenticated user
$permission = $this->getFolderAccess($relative_folderpath, $this->current_user);
if (is_null($permission)) {
// If no permision has been set for the user, get the permission for guest
$permission = $this->getFolderAccess($relative_folderpath);
}
}
else
$permission = $this->getFolderAccess($relative_folderpath);
if (is_null($permission)) {
// No permission has been set for the given folder
// Secure by default
array_push($this->error_msg, "displayCacheFile() : No permission has been set for " . $relative_folderpath . " . " .
"Default to deny.");
return false;
}
if (!$permission['permit']) {
array_push($this->error_msg, "displayCacheFile() : Permission denied to access " . $safe_filepath . " .");
return false;
}
return $this->display($this->cleanPath(
$this->cache_directory . "/" . $safe_filepath
), $bufsize);
}
function displayFile($relative_filepath, $bufsize = 1024) {
/* ---------------------------------------------------------------------------
* Read and display a file
*
* @param string the file path relative to the root directory
* @param int the size of the buffer, default : 1024
* @return boolean
* ------------------------------------------------------------------------ */
if (is_null($this->root_directory)) {
array_push($this->error_msg, "displayFile() : Please, set the GALLERY_ROOT constant to a valid folder.");
return false;
}
if (!is_dir($this->root_directory)) {
array_push($this->error_msg, "displayFile() : GALLERY_ROOT " . $this->root_directory . " is not a valid directory.");
return false;
}
$safe_filepath = $this->safePath($relative_filepath);
// Get permission for the current folder
$relative_folderpath = $this->parentPath($safe_filepath);
if (!is_null($this->current_user)) {
// Authenticated user
$permission = $this->getFolderAccess($relative_folderpath, $this->current_user);
if (is_null($permission)) {
// If no permision has been set for the user, get the permission for guest
$permission = $this->getFolderAccess($relative_folderpath);
}
}
else
$permission = $this->getFolderAccess($relative_folderpath);
if (is_null($permission)) {
// No permission has been set for the given folder
// Secure by default
array_push($this->error_msg, "displayFile() : No permission has been set for " . $relative_folderpath . " . " .
"Default to deny.");
return false;
}
if (!$permission['permit']) {
array_push($this->error_msg, "displayFile() : Permission denied to access " . $safe_filepath . " .");
return false;
}
return $this->display($this->cleanPath(
$this->root_directory . "/" . $safe_filepath
), $bufsize);
}
function display($full_filepath, $bufsize = 1024) {
/* ---------------------------------------------------------------------------
* PRIVATE
* Read and display a file
*
* @param string the fullpath
* @param int the size of the buffer, default : 1024
* @return boolean
* ------------------------------------------------------------------------ */
if ((file_exists($full_filepath))
&& (is_file($full_filepath))) {
$fd = fopen($full_filepath, "rb");
if ($fd === false) {
array_push($this->error_msg, "display() : Failed to open file " . basename($full_filepath));
return false;
}
$info = @getimagesize($full_filepath);
if ($info === false) {
if (!$this->isDownloadable(basename($full_filepath))) {
array_push($this->error_msg, "display() : Permission denied to download " . basename($full_filepath));
return false;
}
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"" . basename($full_filepath) . "\"");
}
else {
switch($info[2]) {
case 1: // GIF
header("Content-Type: image/gif");
header("Content-Disposition: filename=\"" . basename($full_filepath) . "\"");
break;
case 2: // JPEG
header("Content-Type: image/jpeg");
header("Content-Disposition: filename=\"" . basename($full_filepath) . "\"");
break;
case 3: // PNG
header("Content-Type: image/png");
header("Content-Disposition: filename=\"" . basename($full_filepath) . "\"");
break;
default:
if (!$this->isDownloadable(basename($full_filepath))) {
array_push($this->error_msg, "display() : Permission denied to download " . basename($full_filepath));
return false;
}
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"" . basename($full_filepath) . "\"");
break;
}
}
header("Content-Length: " . filesize($full_filepath));
while(!feof($fd)) {
echo fread($fd, $bufsize);
}
fclose($fd);
return true;
}
return false;
}
function resizeImage($src_path, $dst_path, $width = 0, $height = 0) {
/* ---------------------------------------------------------------------------
* Resize an image by width OR height
*
* @param string the image source fullpath
* @param string the image destination fullpath
* @param int the new width
* @param int the new height
* @return boolean
* ------------------------------------------------------------------------ */
if (($width <= 0) && ($height <= 0)) {
array_push($this->error_msg, "resizeImage() : You must define thumbnails by width OR height");
return false;
}
if (($width > 0) && ($height > 0)) {
array_push($this->error_msg, "resizeImage() : You must resize by width OR height, not both");
return false;
}
$info = @getimagesize($src_path);
if ($info !== false) {
$w = $info[0];
$h = $info[1];
$type = $info[2];
switch($type) {
case 1: // GIF
$im_src = imagecreatefromgif($src_path);
break;
case 2: // JPEG
$im_src = imagecreatefromjpeg($src_path);
break;
case 3: // PNG
$im_src = imagecreatefrompng($src_path);
break;
default:
array_push($this->error_msg, "resizeImage() : Unknown image type : " . $type);
return false;
break;
}
if ((isset($im_src))
&& ($im_src !== false)) {
if ($width > 0) {
// Resize by width
if ($w == 0) {
array_push($this->error_msg, "resizeImage() : Image has a width of 0px");
return false;
}
$ratio = $width / $w;
$height = $h * $ratio;
}
else if ($height > 0) {
// Resize by height
if ($h == 0) {
array_push($this->error_msg, "resizeImage() : Image has a height of 0px");
return false;
}
$ratio = $height / $h;
$width = $w * $ratio;
}
$im_dst = imagecreatetruecolor($width, $height);
if ($im_dst === false) {
array_push($this->error_msg, "resizeImage() : Error in imagecreatetruecolor()");
return false;
}
if (imagecopyresampled($im_dst, $im_src, 0, 0, 0, 0, $width, $height, $w, $h)) {
switch($type) {
case 1:
imagegif($im_dst, $dst_path);
break;
case 2:
imagejpeg($im_dst, $dst_path);
break;
case 3:
imagepng($im_dst, $dst_path);
break;
}
return true;
}
else {
array_push($this->error_msg, "resizeImage() : Error in imagecopyresampled()");
}
}
}
else {
array_push($this->error_msg, "resizeImage() : Invalid image file");
}
return false;
}
}
?>