Page Menu
Home
In-Portal Phabricator
Search
Configure Global Search
Log In
Files
F849352
in-portal
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Sun, Apr 20, 4:51 PM
Size
74 KB
Mime Type
text/x-diff
Expires
Tue, Apr 22, 4:51 PM (16 h, 56 m)
Engine
blob
Format
Raw Data
Handle
603829
Attached To
rINP In-Portal
in-portal
View Options
Index: branches/5.2.x/core/kernel/constants.php
===================================================================
--- branches/5.2.x/core/kernel/constants.php (revision 14867)
+++ branches/5.2.x/core/kernel/constants.php (revision 14868)
@@ -1,186 +1,195 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
// item statuses
define('STATUS_DISABLED', 0);
define('STATUS_ACTIVE', 1);
define('STATUS_PENDING', 2);
define('STATUS_PENDING_EDITING', -2);
// sections
define('stTREE', 1);
define('stTAB', 2);
define('smHIDE', 0); // always hide section from tree
define('smNORMAL', 1); // show section even, if they were marked as smDEBUG or smSUPER_ADMIN before
define('smDEBUG', 2); // show section in debug mode only
define('smSUPER_ADMIN', 4); // show section in super admin & debug mode
// permission types
define('ptCATEGORY', 0);
define('ptSYSTEM', 1);
define('EDIT_MARK', '&|edit|&'); // replace this sequence inside filters to SID[_main_wid]
$application =& kApplication::Instance();
$spacer_url = $application->BaseURL().'core/admin_templates/img/spacer.gif';
define('SPACER_URL', $spacer_url);
if (!$application->isAdmin) {
// don't show debugger buttons on front (if not overridden in "debug.php")
kUtil::safeDefine('DBG_TOOLBAR_BUTTONS', 0);
}
// common usage regular expressions
define('REGEX_EMAIL_USER', '[-a-zA-Z0-9!\#$%&*+\/=?^_`{|}~.]+');
define('REGEX_EMAIL_DOMAIN', '[a-zA-Z0-9]{1}[-.a-zA-Z0-9_]*\.[a-zA-Z]{2,6}');
define('ALLOW_DEFAULT_SETTINGS', '_USE_DEFAULT_USER_DATA_'); //Allow persistent vars to take data from default user's persistent data
class ChangeLog {
const CREATE = 1;
const UPDATE = 2;
const DELETE = 3;
}
// Separator for ValueList fields
define('VALUE_LIST_SEPARATOR', '||');
// template editing modes
define('EDITING_MODE_BROWSE', 1); // no changes, front-end as users see it
define('EDITING_MODE_CONTENT', 2); // content blocks + phrase editing
define('EDITING_MODE_DESIGN', 3); // all other blocks
class Agent {
const AGENT_TYPE_USER = 1;
const AGENT_TYPE_SYSTEM = 2;
const LAST_RUN_SUCCEDED = 1;
const LAST_RUN_FAILED = 0;
const LAST_RUN_RUNNING = 2;
}
// place for product file uploads (sort of "/system/images" but for all other files)
define('ITEM_FILES_PATH', WRITEBALE_BASE . '/downloads/');
class MailingList {
const NOT_PROCESSED = 1;
const PARTIALLY_PROCESSED = 2;
const PROCESSED = 3;
const CANCELLED = 4;
}
// theme file statuses (related to structure creation process)
define('SMS_MODE_AUTO', 1);
define('SMS_MODE_FORCE', 2);
// Means, that actual category Template field value should inherited from parent category
define('CATEGORY_TEMPLATE_INHERIT', '#inherit#');
define('REWRITE_MODE_BUILD', 1);
define('REWRITE_MODE_PARSE', 2);
define('SESSION_LOG_ACTIVE', 0);
define('SESSION_LOG_LOGGED_OUT', 1);
define('SESSION_LOG_EXPIRED', 2);
class LoginResult {
const OK = 0;
const INVALID_LOGIN = 1;
const INVALID_PASSWORD = 2;
const BANNED = 3;
const NO_PERMISSION = 4;
}
define('DESTINATION_TYPE_COUNTRY', 1);
define('DESTINATION_TYPE_STATE', 2);
class SubmissionFormField {
const VISIBILITY_EVERYONE = 1;
const VISIBILITY_UNREGISTERED = 2;
const COMMUNICATION_ROLE_NAME = 1;
const COMMUNICATION_ROLE_EMAIL = 2;
const COMMUNICATION_ROLE_SUBJECT = 3;
const COMMUNICATION_ROLE_BODY = 4;
}
// form submission statuses
define('SUBMISSION_REPLIED', 1); // submission was replied by admin
define('SUBMISSION_NOT_REPLIED', 2); // submission has no client replies (no messages at all)
define('SUBMISSION_NEW_EMAIL', 3); // submission have new reply/email from client
define('SUBMISSION_BOUNCE', 4); // submission have bounce from client
// submission log statuses
define('SUBMISSION_LOG_SENT', 1);
define('SUBMISSION_LOG_BOUNCE', 2);
define('SUBMISSION_LOG_REPLIED', 1);
define('SUBMISSION_LOG_ATTACHMENT_PATH', WRITEBALE_BASE . '/user_files/submission_log/');
define('TIMENOW', adodb_mktime()); // for faster message processing
// site domains
define('SITE_DOMAIN_REDIRECT_CURRENT', 1);
define('SITE_DOMAIN_REDIRECT_EXTERNAL', 2);
class EmailEvent {
const EVENT_TYPE_FRONTEND = 0;
const EVENT_TYPE_ADMIN = 1;
const ADDRESS_TYPE_EMAIL = 1;
const ADDRESS_TYPE_USER = 2;
const ADDRESS_TYPE_GROUP = 3;
const RECIPIENT_TYPE_TO = 1;
const RECIPIENT_TYPE_CC = 2;
const RECIPIENT_TYPE_BCC = 3;
}
define('PAGE_TYPE_VIRTUAL', 1);
define('PAGE_TYPE_TEMPLATE', 2);
define('CONTENT_LASTAUTOSAVE_UPDATE_INTERVAL', 5 * 60); // 5 minutes
define('CONTENT_LASTAUTOSAVE_REFRESH_INTERVAL', 20); // 20 seconds
define('reBEFORE', 1);
define('reAFTER', 2);
define('hBEFORE', 1);
define('hAFTER', 2);
class UserType {
const USER = 0;
const ADMIN = 1;
}
// selectors
define('STYLE_BASE', 1);
define('STYLE_BLOCK', 2);
class Language {
const SYNCHRONIZE_TO_OTHERS = 1;
const SYNCHRONIZE_FROM_OTHERS = 2;
const SYNCHRONIZE_DEFAULT = '|1|2|';
const PHRASE_TYPE_FRONT = 0;
const PHRASE_TYPE_ADMIN = 1;
const PHRASE_TYPE_COMMON = 2;
}
class PromoBlockType {
const INTERNAL = 1;
const EXTERNAL = 2;
+ }
+
+ class StorageEngine {
+ const HASH = 1;
+ const TIMESTAMP = 2;
+
+ const PS_DATE_TIME = 'DATE-TIME';
+ const PS_PREFIX = 'PREFIX';
+ const PS_USER = 'USER';
}
\ No newline at end of file
Index: branches/5.2.x/core/kernel/utility/formatters/upload_formatter.php
===================================================================
--- branches/5.2.x/core/kernel/utility/formatters/upload_formatter.php (revision 14867)
+++ branches/5.2.x/core/kernel/utility/formatters/upload_formatter.php (revision 14868)
@@ -1,375 +1,453 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2011 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
class kUploadFormatter extends kFormatter
{
var $DestinationPath;
var $FullPath;
/**
* File helper reference
*
* @var FileHelper
*/
var $fileHelper = null;
public function __construct()
{
parent::__construct();
$this->fileHelper =& $this->Application->recallObject('FileHelper');
if ($this->DestinationPath) {
$this->FullPath = FULL_PATH.$this->DestinationPath;
}
}
/**
* Processes file uploads from form
*
* @param mixed $value
* @param string $field_name
* @param kDBItem $object
* @return mixed
* @access public
*/
public function Parse($value, $field_name, &$object)
{
$ret = !is_array($value) ? $value : '';
$options = $object->GetFieldOptions($field_name);
if (getArrayValue($options, 'upload_dir')) {
$this->DestinationPath = $options['upload_dir'];
$this->FullPath = FULL_PATH.$this->DestinationPath;
}
- $this->fileHelper->CheckFolder($this->FullPath);
-
// SWF Uploader
if (is_array($value) && isset($value['tmp_ids'])) {
if ($value['tmp_deleted']) {
$deleted = explode('|', $value['tmp_deleted']);
$upload = explode('|', $value['upload']);
$n_upload = array();
// $n_ids = array();
foreach ($upload as $name) {
if (in_array($name, $deleted)) continue;
$n_upload[] = $name;
// $n_ids[] = $name;
}
$value['upload'] = implode('|', $n_upload);
// $value['tmp_ids'] = implode('|', $n_ids);
}
if (!$value['tmp_ids']) {
// no pending files -> return already uploded files
return getArrayValue($value, 'upload');
}
$swf_uploaded_ids = explode('|', $value['tmp_ids']);
$swf_uploaded_names = explode('|', $value['tmp_names']);
$existing = $value['upload'] ? explode('|', $value['upload']) : array();
if (isset($options['multiple'])) {
$max_files = $options['multiple'] == false ? 1 : $options['multiple'];
}
else {
$max_files = 1;
}
$fret = array();
// don't delete uploaded file, when it's name matches delete file name
$var_name = $object->getPrefixSpecial().'_file_pending_actions'.$this->Application->GetVar('m_wid');
$schedule = $this->Application->RecallVar($var_name);
$schedule = $schedule ? unserialize($schedule) : Array();
$files2delete = Array();
foreach ($schedule as $data) {
if ($data['action'] == 'delete') {
$files2delete[] = $data['file'];
}
}
- for ($i=0; $i<min($max_files, count($swf_uploaded_ids)); $i++) {
- $real_name = $swf_uploaded_names[$i];
+ for ($i = 0; $i < min($max_files, count($swf_uploaded_ids)); $i++) {
+ $real_name = $this->getStorageEngineFile($swf_uploaded_names[$i], $options, $object->Prefix);
+ $real_name = $this->getStorageEngineFolder($real_name, $options) . $real_name;
+
$real_name = $this->fileHelper->ensureUniqueFilename($this->FullPath, $real_name, $files2delete);
- $file_name = $this->FullPath.$real_name;
+ $file_name = $this->FullPath . $real_name;
- $tmp_file = WRITEABLE . '/tmp/' . $swf_uploaded_ids[$i].'_'.$swf_uploaded_names[$i];
+ $tmp_file = WRITEABLE . '/tmp/' . $swf_uploaded_ids[$i] . '_' . $swf_uploaded_names[$i];
rename($tmp_file, $file_name);
@chmod($file_name, 0666);
- $fret[] = getArrayValue($options, 'upload_dir') ? $real_name : $this->DestinationPath.$real_name;
+ $fret[] = getArrayValue($options, 'upload_dir') ? $real_name : $this->DestinationPath . $real_name;
}
- $fret = array_merge($existing, $fret);
- return implode('|', $fret);
+
+ return implode('|', array_merge($existing, $fret));
}
// SWF Uploader END
if (getArrayValue($value, 'upload') && getArrayValue($value, 'error') == UPLOAD_ERR_NO_FILE) {
// file was not uploaded this time, but was uploaded before, then use previously uploaded file (from db)
return getArrayValue($value, 'upload');
}
if (is_array($value) && count($value) > 1 && $value['size']) {
if (is_array($value) && $value['error'] === UPLOAD_ERR_OK) {
$max_filesize = isset($options['max_size']) ? $options['max_size'] : MAX_UPLOAD_SIZE;
// we can get mime type based on file content and no use one, provided by the client
// $value['type'] = kUtil::mimeContentType($value['tmp_name']);
if ( getArrayValue($options, 'file_types') && !$this->extensionMatch($value['name'], $options['file_types']) ) {
// match by file extensions
$error_params = Array (
'file_name' => $value['name'],
'file_types' => $options['file_types'],
);
$object->SetError($field_name, 'bad_file_format', 'la_error_InvalidFileFormat', $error_params);
}
elseif ( getArrayValue($options, 'allowed_types') && !in_array($value['type'], $options['allowed_types']) ) {
// match by mime type provided by web-browser
$error_params = Array (
'file_type' => $value['type'],
'allowed_types' => $options['allowed_types'],
);
$object->SetError($field_name, 'bad_file_format', 'la_error_InvalidFileFormat', $error_params);
}
elseif ( $value['size'] > $max_filesize ) {
$object->SetError($field_name, 'bad_file_size', 'la_error_FileTooLarge');
}
elseif ( !is_writable($this->FullPath) ) {
$object->SetError($field_name, 'cant_save_file', 'la_error_cant_save_file');
}
else {
- $real_name = $this->fileHelper->ensureUniqueFilename($this->FullPath, $value['name']);
+ $real_name = $this->getStorageEngineFile($value['name'], $options, $object->Prefix);
+ $real_name = $this->getStorageEngineFolder($real_name, $options) . $real_name;
+ $real_name = $this->fileHelper->ensureUniqueFilename($this->FullPath, $real_name);
$file_name = $this->FullPath . $real_name;
+
if ( !move_uploaded_file($value['tmp_name'], $file_name) ) {
$object->SetError($field_name, 'cant_save_file', 'la_error_cant_save_file');
}
else {
@chmod($file_name, 0666);
if ( getArrayValue($options, 'size_field') ) {
$object->SetDBField($options['size_field'], $value['size']);
}
if ( getArrayValue($options, 'orig_name_field') ) {
$object->SetDBField($options['orig_name_field'], $value['name']);
}
if ( getArrayValue($options, 'content_type_field') ) {
$object->SetDBField($options['content_type_field'], $value['type']);
}
$ret = getArrayValue($options, 'upload_dir') ? $real_name : $this->DestinationPath . $real_name;
// delete previous file, when new file is uploaded under same field
/*$previous_file = isset($value['upload']) ? $value['upload'] : false;
if ($previous_file && file_exists($this->FullPath.$previous_file)) {
unlink($this->FullPath.$previous_file);
}*/
}
}
}
else {
$object->SetError($field_name, 'cant_save_file', 'la_error_cant_save_file');
}
}
if ( (count($value) > 1) && $value['error'] && ($value['error'] != UPLOAD_ERR_NO_FILE) ) {
$object->SetError($field_name, 'cant_save_file', 'la_error_cant_save_file', $value);
}
return $ret;
}
/**
* Checks, that given file name has on of provided file extensions
*
* @param string $filename
* @param string $file_types
* @return bool
* @access protected
*/
protected function extensionMatch($filename, $file_types)
{
if ( preg_match_all('/\*\.(.*?)(;|$)/', $file_types, $regs) ) {
$file_extension = mb_strtolower( pathinfo($filename, PATHINFO_EXTENSION) );
$file_extensions = array_map('mb_strtolower', $regs[1]);
return in_array($file_extension, $file_extensions);
}
return true;
}
function getSingleFormat($format)
{
$single_mapping = Array (
'file_urls' => 'full_url',
'file_paths' => 'full_path',
'file_sizes' => 'file_size',
'files_resized' => 'resize',
'img_sizes' => 'img_size',
'wms' => 'wm',
);
return $single_mapping[$format];
}
/**
* Return formatted file url,path or size (or same for multiple files)
*
* @param string $value
* @param string $field_name
* @param kDBItem|kDBList $object
* @param string $format
* @return string
*/
function Format($value, $field_name, &$object, $format = null)
{
if (is_null($value)) {
return '';
}
$options = $object->GetFieldOptions($field_name);
if (!isset($format)) {
$format = isset($options['format']) ? $options['format'] : false;
}
if ($format && preg_match('/(file_urls|file_paths|file_names|file_sizes|img_sizes|files_resized|wms)(.*)/', $format, $regs)) {
if (!$value || $format == 'file_names') {
// storage format matches display format OR no value
return $value;
}
$ret = Array ();
$files = explode('|', $value);
$format = $this->getSingleFormat($regs[1]).$regs[2];
foreach ($files as $a_file) {
$ret[] = $this->GetFormatted($a_file, $field_name, $object, $format);
}
return implode('|', $ret);
}
$tc_value = $this->TypeCast($value, $options);
if( ($tc_value === false) || ($tc_value != $value) ) return $value; // for leaving badly formatted date on the form
// force direct links for case, when non-swf uploader is used
return $this->GetFormatted($tc_value, $field_name, $object, $format, true);
}
/**
* Return formatted file url,path or size
*
* @param string $value
* @param string $field_name
* @param kDBItem $object
* @param string $format
* @param bool $force_direct_links
* @return string
*/
function GetFormatted($value, $field_name, &$object, $format = null, $force_direct_links = null)
{
if (!$format) {
return $value;
}
$options = $object->GetFieldOptions($field_name);
$upload_dir = isset($options['upload_dir']) ? $options['upload_dir'] : $this->DestinationPath;
if (preg_match('/resize:([\d]*)x([\d]*)/', $format, $regs)) {
$image_helper =& $this->Application->recallObject('ImageHelper');
/* @var $image_helper ImageHelper */
if (array_key_exists('include_path', $options) && $options['include_path']) {
// relative path is already included in field
$upload_dir = '';
}
return $image_helper->ResizeImage($value ? FULL_PATH . str_replace('/', DIRECTORY_SEPARATOR, $upload_dir) . $value : '', $format);
}
switch ($format) {
case 'full_url':
if ( isset($force_direct_links) ) {
$direct_links = $force_direct_links;
}
else {
$direct_links = isset($options['direct_links']) ? $options['direct_links'] : false;
}
if ( $direct_links ) {
return $this->fileHelper->pathToUrl(FULL_PATH . $upload_dir . $value);
}
else {
$url_params = Array (
'no_amp' => 1, 'pass' => 'm,'.$object->Prefix,
$object->Prefix . '_event' => 'OnViewFile',
'file' => rawurlencode($value), 'field' => $field_name
);
return $this->Application->HREF('', '', $url_params);
}
break;
case 'full_path':
return FULL_PATH . str_replace('/', DIRECTORY_SEPARATOR, $upload_dir) . $value;
break;
case 'file_size':
return filesize(FULL_PATH . str_replace('/', DIRECTORY_SEPARATOR, $upload_dir) . $value);
break;
case 'img_size':
$image_helper =& $this->Application->recallObject('ImageHelper');
/* @var $image_helper ImageHelper */
$image_info = $image_helper->getImageInfo(FULL_PATH . str_replace('/', DIRECTORY_SEPARATOR, $upload_dir) . $value);
return $image_info ? $image_info[3] : '';
break;
}
return sprintf($format, $value);
}
+
+ /**
+ * Creates & returns folder, based on storage engine specified in field options
+ *
+ * @param string $file_name
+ * @param array $options
+ * @return string
+ * @access protected
+ */
+ protected function getStorageEngineFolder($file_name, $options)
+ {
+ $storage_engine = (string)getArrayValue($options, 'storage_engine');
+
+ if ( !$storage_engine ) {
+ return '';
+ }
+
+ switch ($storage_engine) {
+ case StorageEngine::HASH:
+ $folder_path = kUtil::getHashPathForLevel($file_name);
+ break;
+
+ case StorageEngine::TIMESTAMP:
+ $folder_path = adodb_date('Y-m/d/');
+ break;
+
+ default:
+ throw new Exception('Unknown storage engine "<strong>' . $storage_engine . '</strong>".');
+ break;
+ }
+
+ return $folder_path;
+ }
+
+ /**
+ * Applies prefix & suffix to uploaded filename, based on storage engine in field options
+ *
+ * @param string $name
+ * @param array $options
+ * @param string $unit_prefix
+ * @return string
+ * @access protected
+ */
+ protected function getStorageEngineFile($name, $options, $unit_prefix)
+ {
+ $prefix = $this->getStorageEngineFilePart(getArrayValue($options, 'filename_prefix'), $unit_prefix);
+ $suffix = $this->getStorageEngineFilePart(getArrayValue($options, 'filename_suffix'), $unit_prefix);
+
+ $parts = pathinfo($name);
+
+ return ($prefix ? $prefix . '_' : '') . $parts['filename'] . ($suffix ? '_' . $suffix : '') . '.' . $parts['extension'];
+ }
+
+ /**
+ * Creates prefix/suffix to join with uploaded file
+ *
+ * Added "u" before user_id to keep this value after FileHelper::ensureUniqueFilename method call
+ *
+ * @param string $option
+ * @param string $unit_prefix
+ * @return string
+ * @access protected
+ */
+ protected function getStorageEngineFilePart($option, $unit_prefix)
+ {
+ $replace_from = Array (
+ StorageEngine::PS_DATE_TIME, StorageEngine::PS_PREFIX, StorageEngine::PS_USER
+ );
+
+ $replace_to = Array (
+ adodb_date('Ymd-His'), $unit_prefix, 'u' . $this->Application->RecallVar('user_id')
+ );
+
+ return str_replace($replace_from, $replace_to, $option);
+ }
}
class kPictureFormatter extends kUploadFormatter
{
public function __construct()
{
$this->NakeLookupPath = IMAGES_PATH; // used ?
$this->DestinationPath = kUtil::constOn('ADMIN') ? IMAGES_PENDING_PATH : IMAGES_PATH;
parent::__construct();
}
function GetFormatted($value, $field_name, &$object, $format = null, $force_direct_links = null)
{
if ($format == 'img_size') {
$upload_dir = isset($options['upload_dir']) ? $options['upload_dir'] : $this->DestinationPath;
$img_path = FULL_PATH.'/'.$upload_dir.$value;
$image_info = @getimagesize($img_path);
return ' width="'.$image_info[0].'" height="'.$image_info[1].'"';
}
return parent::GetFormatted($value, $field_name, $object, $format, $force_direct_links);
}
}
\ No newline at end of file
Index: branches/5.2.x/core/kernel/globals.php
===================================================================
--- branches/5.2.x/core/kernel/globals.php (revision 14867)
+++ branches/5.2.x/core/kernel/globals.php (revision 14868)
@@ -1,808 +1,832 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
class kUtil {
// const KG_TO_POUND = 2.20462262;
const POUND_TO_KG = 0.45359237;
/**
* Similar to array_merge_recursive but keyed-valued are always overwritten.
* Priority goes to the 2nd array.
*
* @param $paArray1 array
* @param $paArray2 array
* @return array
* @access public
*/
public static function array_merge_recursive($paArray1, $paArray2)
{
if (!is_array($paArray1) or !is_array($paArray2)) {
return $paArray2;
}
foreach ($paArray2 AS $sKey2 => $sValue2) {
$paArray1[$sKey2] = isset($paArray1[$sKey2]) ? self::array_merge_recursive($paArray1[$sKey2], $sValue2) : $sValue2;
}
return $paArray1;
}
/**
* Prepend a reference to an element to the beginning of an array.
* Renumbers numeric keys, so $value is always inserted to $array[0]
*
* @param $array array
* @param $value mixed
* @return int
* @access public
*/
public static function array_unshift_ref(&$array, &$value)
{
$return = array_unshift($array,'');
$array[0] =& $value;
return $return;
}
/**
* Rename key in associative array, maintaining keys order
*
* @param Array $array Associative Array
* @param mixed $old Old key name
* @param mixed $new New key name
* @access public
*/
public static function array_rename_key(&$array, $old, $new)
{
$new_array = Array ();
foreach ($array as $key => $val) {
$new_array[ $key == $old ? $new : $key] = $val;
}
$array = $new_array;
}
/**
* Same as print_r, but outputs result on screen or in debugger report (when in debug mode)
*
* @param Array $data
* @param string $label
* @param bool $on_screen
* @access public
*/
public static function print_r($data, $label = '', $on_screen = false)
{
$is_debug = false;
if ( class_exists('kApplication') && !$on_screen ) {
$application =& kApplication::Instance();
$is_debug = $application->isDebugMode();
}
if ( $is_debug && isset($application) ) {
if ( $label ) {
$application->Debugger->appendHTML('<strong>' . $label . '</strong>');
}
$application->Debugger->dumpVars($data);
}
else {
if ( $label ) {
echo '<strong>' . $label . '</strong><br/>';
}
echo '<pre>', print_r($data, true), '</pre>';
}
}
/**
* Define constant if it was not already defined before
*
* @param string $const_name
* @param string $const_value
* @access public
*/
public static function safeDefine($const_name, $const_value)
{
if ( !defined($const_name) ) {
define($const_name, $const_value);
}
}
/**
* Parses "/system/config.php" file and returns the result
*
* @param bool $parse_section
* @return Array
* @access public
*/
public static function parseConfig($parse_section = false)
{
$file = FULL_PATH . DIRECTORY_SEPARATOR . 'system' . DIRECTORY_SEPARATOR . 'config.php';
if (!file_exists($file)) {
return Array ();
}
if (file_exists($file) && !is_readable($file)) {
die('Could Not Open Ini File');
}
$contents = file($file);
if ($contents && $contents[0] == '<' . '?' . 'php die() ?' . ">\n") {
// format of "config.php" file before 5.1.0 version
array_shift($contents);
return parse_ini_string(implode('', $contents), $parse_section);
}
$_CONFIG = Array ();
require($file);
if ($parse_section) {
if ( isset($_CONFIG['Database']['LoadBalancing']) && $_CONFIG['Database']['LoadBalancing'] ) {
require FULL_PATH . DIRECTORY_SEPARATOR . 'system' . DIRECTORY_SEPARATOR . 'db_servers.php';
}
return $_CONFIG;
}
$ret = Array ();
foreach ($_CONFIG as $section => $section_variables) {
$ret = array_merge($ret, $section_variables);
}
return $ret;
}
/**
* Returns parsed variables from "config.php" file
*
* @return Array
* @access public
*/
public static function getConfigVars()
{
static $vars = null;
if ( !isset($vars) ) {
$vars = self::parseConfig();
}
return $vars;
}
/**
* Same as "include_once", but also profiles file includes in debug mode and DBG_PROFILE_INCLUDES constant is set
*
* @param string $file
* @access public
*/
public static function includeOnce($file)
{
global $debugger;
if ( defined('DEBUG_MODE') && DEBUG_MODE && isset($debugger) && defined('DBG_PROFILE_INCLUDES') && DBG_PROFILE_INCLUDES ) {
if ( in_array($file, get_included_files()) ) {
return ;
}
global $debugger;
/*$debugger->IncludeLevel++;
$before_mem = memory_get_usage();*/
$debugger->ProfileStart('inc_'.crc32($file), $file);
include_once($file);
$debugger->ProfileFinish('inc_'.crc32($file));
$debugger->profilerAddTotal('includes', 'inc_'.crc32($file));
/*$used_mem = memory_get_usage() - $before_mem;
$debugger->IncludeLevel--;
$debugger->IncludesData['file'][] = str_replace(FULL_PATH, '', $file);
$debugger->IncludesData['mem'][] = $used_mem;
$debugger->IncludesData['time'][] = $used_time;
$debugger->IncludesData['level'][] = $debugger->IncludeLevel;*/
}
else {
include_once($file);
}
}
/**
* Checks if given string is a serialized array
*
* @param string $string
* @return bool
* @access public
*/
public static function IsSerialized($string)
{
if ( is_array($string) ) {
return false;
}
return preg_match('/a:([\d]+):{/', $string);
}
/**
* Generates password of given length
*
* @param int $length
* @return string
* @access public
*/
public static function generatePassword($length = 10)
{
$pass_length = $length;
$p1 = Array ('b','c','d','f','g','h','j','k','l','m','n','p','q','r','s','t','v','w','x','y','z');
$p2 = Array ('a','e','i','o','u');
$p3 = Array ('1','2','3','4','5','6','7','8','9');
$p4 = Array ('(','&',')',';','%'); // if you need real strong stuff
// how much elements in the array
// can be done with a array count but counting once here is faster
$s1 = 21;// this is the count of $p1
$s2 = 5; // this is the count of $p2
$s3 = 9; // this is the count of $p3
$s4 = 5; // this is the count of $p4
// possible readable combinations
$c1 = '121'; // will be like 'bab'
$c2 = '212'; // will be like 'aba'
$c3 = '12'; // will be like 'ab'
$c4 = '3'; // will be just a number '1 to 9' if you dont like number delete the 3
//$c5 = '4'; // uncomment to active the strong stuff
$comb = '4'; // the amount of combinations you made above (and did not comment out)
for ($p = 0; $p < $pass_length;) {
mt_srand((double)microtime() * 1000000);
$strpart = mt_rand(1, $comb);
// checking if the stringpart is not the same as the previous one
if ($strpart != $previous) {
$pass_structure .= ${'c' . $strpart};
// shortcutting the loop a bit
$p = $p + mb_strlen(${'c' . $strpart});
}
$previous = $strpart;
}
// generating the password from the structure defined in $pass_structure
for ($g = 0; $g < mb_strlen($pass_structure); $g++) {
mt_srand((double)microtime() * 1000000);
$sel = mb_substr($pass_structure, $g, 1);
$pass .= ${'p' . $sel}[ mt_rand(0,-1+${'s'.$sel}) ];
}
return $pass;
}
/**
* Reverts effects of "htmlspecialchars" function
*
* @param string $string
* @return string
* @access public
*/
public static function unhtmlentities($string)
{
$trans_tbl = get_html_translation_table(HTML_ENTITIES); // from PHP 5.3.4: , ENT_COMPAT, 'utf-8');
$trans_tbl = array_flip ($trans_tbl);
return strtr($string, $trans_tbl);
}
/**
* submits $url with $post as POST
*
* @param string $url
* @param mixed $data
* @param Array $headers
* @param string $request_type
* @param Array $curl_options
* @return string
* @access public
* @deprecated
*/
public static function curl_post($url, $data, $headers = null, $request_type = 'POST', $curl_options = null)
{
$application =& kApplication::Instance();
$curl_helper =& $application->recallObject('CurlHelper');
/* @var $curl_helper kCurlHelper */
if ($request_type == 'POST') {
$curl_helper->SetRequestMethod(kCurlHelper::REQUEST_METHOD_POST);
}
$curl_helper->SetRequestData($data);
if (!is_null($headers)) {
// not an associative array, so don't use kCurlHelper::SetHeaders method
$curl_helper->setOptions( Array (CURLOPT_HTTPHEADER => $headers) );
}
if (is_array($curl_options)) {
$curl_helper->setOptions($curl_options);
}
$curl_helper->followLocation = false;
$ret = $curl_helper->Send($url);
$GLOBALS['curl_errorno'] = $curl_helper->lastErrorCode;
$GLOBALS['curl_error'] = $curl_helper->lastErrorMsg;
return $ret;
}
/**
* Checks if constant is defined and has positive value
*
* @param string $const_name
* @return bool
* @access public
*/
public static function constOn($const_name)
{
return defined($const_name) && constant($const_name);
}
/**
* Converts KG to Pounds
*
* @param float $kg
* @param bool $pounds_only
* @return float
* @access public
*/
public static function Kg2Pounds($kg, $pounds_only = false)
{
$major = floor( round($kg / self::POUND_TO_KG, 3) );
$minor = abs(round(($kg - $major * self::POUND_TO_KG) / self::POUND_TO_KG * 16, 2));
if ($pounds_only) {
$major += round($minor * 0.0625, 2);
$minor = 0;
}
return array($major, $minor);
}
/**
* Converts Pounds to KG
*
* @param float $pounds
* @param float $ounces
* @return float
* @access public
*/
public static function Pounds2Kg($pounds, $ounces = 0.00)
{
return round(($pounds + ($ounces / 16)) * self::POUND_TO_KG, 5);
}
/**
* Formats file/memory size in nice way
*
* @param int $bytes
* @return string
* @access public
*/
public static function formatSize($bytes)
{
if ($bytes >= 1099511627776) {
$return = round($bytes / 1024 / 1024 / 1024 / 1024, 2);
$suffix = "TB";
} elseif ($bytes >= 1073741824) {
$return = round($bytes / 1024 / 1024 / 1024, 2);
$suffix = "GB";
} elseif ($bytes >= 1048576) {
$return = round($bytes / 1024 / 1024, 2);
$suffix = "MB";
} elseif ($bytes >= 1024) {
$return = round($bytes / 1024, 2);
$suffix = "KB";
} else {
$return = $bytes;
$suffix = "Byte";
}
$return .= ' '.$suffix;
return $return;
}
/**
* Enter description here...
*
* @param resource $filePointer the file resource to write to
* @param Array $data the data to write out
* @param string $delimiter the field separator
* @param string $enclosure symbol to enclose field data to
* @param string $recordSeparator symbols to separate records with
* @access public
*/
public static function fputcsv($filePointer, $data, $delimiter = ',', $enclosure = '"', $recordSeparator = "\r\n")
{
foreach($data as $field_index => $field_value) {
// replaces an enclosure with two enclosures
$data[$field_index] = str_replace($enclosure, $enclosure.$enclosure, $field_value);
}
$line = $enclosure.implode($enclosure.$delimiter.$enclosure, $data).$enclosure.$recordSeparator;
$line = preg_replace('/'.preg_quote($enclosure, '/').'([0-9\.]+)'.preg_quote($enclosure, '/').'/', '$1', $line);
fwrite($filePointer, $line);
}
/**
* Enter description here...
*
* @param Array $data the data to write out
* @param string $delimiter the field separator
* @param string $enclosure symbol to enclose field data to
* @param string $recordSeparator symbols to separate records with
* @return string
* @access public
*/
public static function getcsvline($data, $delimiter = ',', $enclosure = '"', $recordSeparator = "\r\n")
{
foreach($data as $field_index => $field_value) {
// replaces an enclosure with two enclosures
$data[$field_index] = str_replace($enclosure, $enclosure.$enclosure, $field_value);
}
$line = $enclosure.implode($enclosure.$delimiter.$enclosure, $data).$enclosure.$recordSeparator;
$line = preg_replace('/'.preg_quote($enclosure, '/').'([0-9\.]+)'.preg_quote($enclosure, '/').'/', '$1', $line);
return $line;
}
/**
* Allows to replace #section# within any string with current section
*
* @param string $string
* @return string
* @access public
*/
public static function replaceModuleSection($string)
{
$application =& kApplication::Instance();
$module_section = $application->RecallVar('section');
if ($module_section) {
// substitute section instead of #section# parameter in title preset name
$module_section = explode(':', $module_section);
$section = preg_replace('/(configuration|configure)_(.*)/i', '\\2', $module_section[count($module_section) == 2 ? 1 : 0]);
$string = str_replace('#section#', mb_strtolower($section), $string);
}
return $string;
}
/**
* Checks, that user IP address is within allowed range
*
* @param string $ip_list semi-column (by default) separated ip address list
* @param string $separator ip address separator (default ";")
*
* @return bool
* @access public
*/
public static function ipMatch($ip_list, $separator = ';')
{
if ( !isset($_SERVER['REMOTE_ADDR']) ) {
// PHP CLI used -> never match
return false;
}
$ip_match = false;
$ip_addresses = $ip_list ? explode($separator, $ip_list) : Array ();
foreach ($ip_addresses as $ip_address) {
if (self::netMatch($ip_address, $_SERVER['REMOTE_ADDR'])) {
$ip_match = true;
break;
}
}
return $ip_match;
}
/**
* Checks, that given ip belongs to given subnet
*
* @param string $network
* @param string $ip
* @return bool
* @access public
*/
public static function netMatch($network, $ip)
{
$network = trim($network);
$ip = trim($ip);
if ( preg_replace('/[\d\.\/-]/', '', $network) != '' ) {
$network = gethostbyname($network);
}
if ($network == $ip) {
// comparing two ip addresses directly
return true;
}
$d = strpos($network, '-');
if ($d !== false) {
// ip address range specified
$from = ip2long(trim(substr($network, 0, $d)));
$to = ip2long(trim(substr($network, $d + 1)));
$ip = ip2long($ip);
return ($ip >= $from && $ip <= $to);
}
elseif (strpos($network, '/') !== false) {
// sigle subnet specified
$ip_arr = explode('/', $network);
if (!preg_match("@\d*\.\d*\.\d*\.\d*@", $ip_arr[0], $matches)) {
$ip_arr[0] .= '.0'; // Alternate form 194.1.4/24
}
$network_long = ip2long($ip_arr[0]);
$x = ip2long($ip_arr[1]);
$mask = long2ip($x) == $ip_arr[1] ? $x : (0xffffffff << (32 - $ip_arr[1]));
$ip_long = ip2long($ip);
return ($ip_long & $mask) == ($network_long & $mask);
}
return false;
}
/**
* Returns mime type corresponding to given file
* @param string $file
* @return string
* @access public
*/
public static function mimeContentType($file)
{
$ret = '';
if ( function_exists('finfo_open') && function_exists('finfo_file') ) {
$mime_magic_resource = finfo_open(FILEINFO_MIME_TYPE);
if ( $mime_magic_resource ) {
$ret = finfo_file($mime_magic_resource, $file);
finfo_close($mime_magic_resource);
}
}
elseif ( function_exists('mime_content_type') ) {
$ret = mime_content_type($file);
}
return $ret ? $ret : self::mimeContentTypeByExtension($file);
}
/**
* Detects mime type of the file purely based on it's extension
*
* @param string $file
* @return string
* @access public
*/
public static function mimeContentTypeByExtension($file)
{
$file_extension = mb_strtolower( pathinfo($file, PATHINFO_EXTENSION) );
$mapping = '(xls:application/excel)(hqx:application/macbinhex40)(doc,dot,wrd:application/msword)(pdf:application/pdf)
(pgp:application/pgp)(ps,eps,ai:application/postscript)(ppt:application/powerpoint)(rtf:application/rtf)
(tgz,gtar:application/x-gtar)(gz:application/x-gzip)(php,php3:application/x-httpd-php)(js:application/x-javascript)
(ppd,psd:application/x-photoshop)(swf,swc,rf:application/x-shockwave-flash)(tar:application/x-tar)(zip:application/zip)
(mid,midi,kar:audio/midi)(mp2,mp3,mpga:audio/mpeg)(ra:audio/x-realaudio)(wav:audio/wav)(bmp:image/bitmap)(bmp:image/bitmap)
(gif:image/gif)(iff:image/iff)(jb2:image/jb2)(jpg,jpe,jpeg:image/jpeg)(jpx:image/jpx)(png:image/png)(tif,tiff:image/tiff)
(wbmp:image/vnd.wap.wbmp)(xbm:image/xbm)(css:text/css)(txt:text/plain)(htm,html:text/html)(xml:text/xml)
(mpg,mpe,mpeg:video/mpeg)(qt,mov:video/quicktime)(avi:video/x-ms-video)(eml:message/rfc822)
(sxw:application/vnd.sun.xml.writer)(sxc:application/vnd.sun.xml.calc)(sxi:application/vnd.sun.xml.impress)
(sxd:application/vnd.sun.xml.draw)(sxm:application/vnd.sun.xml.math)
(odt:application/vnd.oasis.opendocument.text)(oth:application/vnd.oasis.opendocument.text-web)
(odm:application/vnd.oasis.opendocument.text-master)(odg:application/vnd.oasis.opendocument.graphics)
(odp:application/vnd.oasis.opendocument.presentation)(ods:application/vnd.oasis.opendocument.spreadsheet)
(odc:application/vnd.oasis.opendocument.chart)(odf:application/vnd.oasis.opendocument.formula)
(odi:application/vnd.oasis.opendocument.image)';
if ( preg_match('/[\(,]' . $file_extension . '[,]{0,1}.*?:(.*?)\)/s', $mapping, $regs) ) {
return $regs[1];
}
return 'application/octet-stream';
}
/**
* Return param value and removes it from params array
*
* @param string $name
* @param Array $params
* @param bool $default
* @return string
*/
public static function popParam($name, &$params, $default = false)
{
if ( isset($params[$name]) ) {
$value = $params[$name];
unset($params[$name]);
return $value;
}
return $default;
}
+
+ /**
+ * Generate subpath from hashed value
+ *
+ * @param string $name
+ * @param int $levels
+ * @return string
+ */
+ public static function getHashPathForLevel($name, $levels = 2)
+ {
+ if ( $levels == 0 ) {
+ return '';
+ }
+ else {
+ $path = '';
+ $hash = md5($name);
+
+ for ($i = 0; $i < $levels; $i++) {
+ $path .= substr($hash, $i, 1) . '/';
+ }
+
+ return $path;
+ }
+ }
}
/**
* Returns array value if key exists
* Accepts infinite number of parameters
*
* @param Array $array searchable array
* @param int $key array key
* @return string
*/
function getArrayValue(&$array, $key)
{
$ret = isset($array[$key]) ? $array[$key] : false;
if ($ret && func_num_args() > 2) {
for ($i = 2; $i < func_num_args(); $i++) {
$cur_key = func_get_arg($i);
$ret = getArrayValue( $ret, $cur_key );
if ($ret === false) {
break;
}
}
}
return $ret;
}
if ( !function_exists('parse_ini_string') ) {
/**
* Equivalent for "parse_ini_string" function available since PHP 5.3.0
*
* @param string $ini
* @param bool $process_sections
* @param int $scanner_mode
* @return Array
*/
function parse_ini_string($ini, $process_sections = false, $scanner_mode = null)
{
# Generate a temporary file.
$tempname = tempnam('/tmp', 'ini');
$fp = fopen($tempname, 'w');
fwrite($fp, $ini);
$ini = parse_ini_file($tempname, !empty($process_sections));
fclose($fp);
@unlink($tempname);
return $ini;
}
}
if ( !function_exists('memory_get_usage') ) {
// PHP 4.x and compiled without --enable-memory-limit option
function memory_get_usage() { return -1; }
}
if ( !function_exists('imagecreatefrombmp') ) {
// just in case if GD will add this function in future
function imagecreatefrombmp($filename)
{
//Ouverture du fichier en mode binaire
if (! $f1 = fopen($filename,"rb")) return FALSE;
//1 : Chargement des ent�tes FICHIER
$FILE = unpack("vfile_type/Vfile_size/Vreserved/Vbitmap_offset", fread($f1,14));
if ($FILE['file_type'] != 19778) return FALSE;
//2 : Chargement des ent�tes BMP
$BMP = unpack('Vheader_size/Vwidth/Vheight/vplanes/vbits_per_pixel'.
'/Vcompression/Vsize_bitmap/Vhoriz_resolution'.
'/Vvert_resolution/Vcolors_used/Vcolors_important', fread($f1,40));
$BMP['colors'] = pow(2,$BMP['bits_per_pixel']);
if ($BMP['size_bitmap'] == 0) $BMP['size_bitmap'] = $FILE['file_size'] - $FILE['bitmap_offset'];
$BMP['bytes_per_pixel'] = $BMP['bits_per_pixel']/8;
$BMP['bytes_per_pixel2'] = ceil($BMP['bytes_per_pixel']);
$BMP['decal'] = ($BMP['width']*$BMP['bytes_per_pixel']/4);
$BMP['decal'] -= floor($BMP['width']*$BMP['bytes_per_pixel']/4);
$BMP['decal'] = 4-(4*$BMP['decal']);
if ($BMP['decal'] == 4) $BMP['decal'] = 0;
//3 : Chargement des couleurs de la palette
$PALETTE = array();
if ($BMP['colors'] < 16777216)
{
$PALETTE = unpack('V'.$BMP['colors'], fread($f1,$BMP['colors']*4));
}
//4 : Cr�ation de l'image
$IMG = fread($f1,$BMP['size_bitmap']);
$VIDE = chr(0);
$res = imagecreatetruecolor($BMP['width'],$BMP['height']);
$P = 0;
$Y = $BMP['height']-1;
while ($Y >= 0)
{
$X=0;
while ($X < $BMP['width'])
{
if ($BMP['bits_per_pixel'] == 24)
$COLOR = unpack("V",substr($IMG,$P,3).$VIDE);
elseif ($BMP['bits_per_pixel'] == 16)
{
$COLOR = unpack("n",substr($IMG,$P,2));
$COLOR[1] = $PALETTE[$COLOR[1]+1];
}
elseif ($BMP['bits_per_pixel'] == 8)
{
$COLOR = unpack("n",$VIDE.substr($IMG,$P,1));
$COLOR[1] = $PALETTE[$COLOR[1]+1];
}
elseif ($BMP['bits_per_pixel'] == 4)
{
$COLOR = unpack("n",$VIDE.substr($IMG,floor($P),1));
if (($P*2)%2 == 0) $COLOR[1] = ($COLOR[1] >> 4) ; else $COLOR[1] = ($COLOR[1] & 0x0F);
$COLOR[1] = $PALETTE[$COLOR[1]+1];
}
elseif ($BMP['bits_per_pixel'] == 1)
{
$COLOR = unpack("n",$VIDE.substr($IMG,floor($P),1));
if (($P*8)%8 == 0) $COLOR[1] = $COLOR[1] >>7;
elseif (($P*8)%8 == 1) $COLOR[1] = ($COLOR[1] & 0x40)>>6;
elseif (($P*8)%8 == 2) $COLOR[1] = ($COLOR[1] & 0x20)>>5;
elseif (($P*8)%8 == 3) $COLOR[1] = ($COLOR[1] & 0x10)>>4;
elseif (($P*8)%8 == 4) $COLOR[1] = ($COLOR[1] & 0x8)>>3;
elseif (($P*8)%8 == 5) $COLOR[1] = ($COLOR[1] & 0x4)>>2;
elseif (($P*8)%8 == 6) $COLOR[1] = ($COLOR[1] & 0x2)>>1;
elseif (($P*8)%8 == 7) $COLOR[1] = ($COLOR[1] & 0x1);
$COLOR[1] = $PALETTE[$COLOR[1]+1];
}
else
return FALSE;
imagesetpixel($res,$X,$Y,$COLOR[1]);
$X++;
$P += $BMP['bytes_per_pixel'];
}
$Y--;
$P+=$BMP['decal'];
}
//Fermeture du fichier
fclose($f1);
return $res;
}
}
\ No newline at end of file
Index: branches/5.2.x/core/units/helpers/file_helper.php
===================================================================
--- branches/5.2.x/core/units/helpers/file_helper.php (revision 14867)
+++ branches/5.2.x/core/units/helpers/file_helper.php (revision 14868)
@@ -1,442 +1,456 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
class FileHelper extends kHelper {
/**
* Puts existing item images (from sub-item) to virtual fields (in main item)
*
* @param kCatDBItem $object
* @return void
* @access public
*/
public function LoadItemFiles(&$object)
{
$max_file_count = $this->Application->ConfigValue($object->Prefix.'_MaxImageCount'); // file count equals to image count (temporary measure)
$sql = 'SELECT *
FROM '.TABLE_PREFIX.'ItemFiles
WHERE ResourceId = '.$object->GetDBField('ResourceId').'
ORDER BY FileId ASC
LIMIT 0, '.(int)$max_file_count;
$item_files = $this->Conn->Query($sql);
$file_counter = 1;
foreach ($item_files as $item_file) {
$file_path = $item_file['FilePath'];
$object->SetDBField('File'.$file_counter, $file_path);
$object->SetOriginalField('File'.$file_counter, $file_path);
$object->SetFieldOption('File'.$file_counter, 'original_field', $item_file['FileName']);
$file_counter++;
}
}
/**
* Saves newly uploaded images to external image table
*
* @param kCatDBItem $object
* @return void
* @access public
*/
public function SaveItemFiles(&$object)
{
$table_name = $this->Application->getUnitOption('#file', 'TableName');
$max_file_count = $this->Application->getUnitOption($object->Prefix, 'FileCount'); // $this->Application->ConfigValue($object->Prefix.'_MaxImageCount');
$this->CheckFolder(FULL_PATH . ITEM_FILES_PATH);
$i = 0;
while ($i < $max_file_count) {
$field = 'File'.($i + 1);
$field_options = $object->GetFieldOptions($field);
$file_path = $object->GetDBField($field);
if ($file_path) {
if (isset($field_options['original_field'])) {
$key_clause = 'FileName = '.$this->Conn->qstr($field_options['original_field']).' AND ResourceId = '.$object->GetDBField('ResourceId');
if ($object->GetDBField('Delete'.$field)) {
// if item was cloned, then new filename is in db (not in $image_src)
$sql = 'SELECT FilePath
FROM '.$table_name.'
WHERE '.$key_clause;
$file_path = $this->Conn->GetOne($sql);
if (@unlink(FULL_PATH.ITEM_FILES_PATH.$file_path)) {
$sql = 'DELETE FROM '.$table_name.'
WHERE '.$key_clause;
$this->Conn->Query($sql);
}
}
else {
// image record found -> update
$fields_hash = Array (
'FilePath' => $file_path,
);
$this->Conn->doUpdate($fields_hash, $table_name, $key_clause);
}
}
else {
// record not found -> create
$fields_hash = Array (
'ResourceId' => $object->GetDBField('ResourceId'),
'FileName' => $field,
'Status' => STATUS_ACTIVE,
'FilePath' => $file_path,
);
$this->Conn->doInsert($fields_hash, $table_name);
$field_options['original_field'] = $field;
$object->SetFieldOptions($field, $field_options);
}
}
$i++;
}
}
/**
* Preserves cloned item images/files to be rewritten with original item images/files
*
* @param Array $field_values
* @return void
* @access public
*/
public function PreserveItemFiles(&$field_values)
{
foreach ($field_values as $field_name => $field_value) {
- if (!is_array($field_value)) continue;
+ if ( !is_array($field_value) ) {
+ continue;
+ }
- if (isset($field_value['upload']) && ($field_value['error'] == UPLOAD_ERR_NO_FILE)) {
+ if ( isset($field_value['upload']) && ($field_value['error'] == UPLOAD_ERR_NO_FILE) ) {
// this is upload field, but nothing was uploaded this time
unset($field_values[$field_name]);
}
}
}
/**
* Determines what image/file fields should be created (from post or just dummy fields for 1st upload)
*
* @param string $prefix
* @param bool $is_image
* @return void
* @access public
*/
public function createItemFiles($prefix, $is_image = false)
{
$items_info = $this->Application->GetVar($prefix);
if ($items_info) {
list (, $fields_values) = each($items_info);
$this->createUploadFields($prefix, $fields_values, $is_image);
}
else {
$this->createUploadFields($prefix, Array(), $is_image);
}
}
/**
* Dynamically creates virtual fields for item for each image/file field in submit
*
* @param string $prefix
* @param Array $fields_values
* @param bool $is_image
* @return void
* @access public
*/
public function createUploadFields($prefix, $fields_values, $is_image = false)
{
$field_options = Array (
'type' => 'string',
'max_len' => 240,
'default' => '',
);
if ($is_image) {
$field_options['formatter'] = 'kPictureFormatter';
$field_options['include_path'] = 1;
$field_options['allowed_types'] = Array ('image/jpeg', 'image/pjpeg', 'image/png', 'image/x-png', 'image/gif', 'image/bmp');
$field_prefix = 'Image';
}
else {
$field_options['formatter'] = 'kUploadFormatter';
$field_options['upload_dir'] = ITEM_FILES_PATH;
$field_options['allowed_types'] = Array ('application/pdf', 'application/msexcel', 'application/msword', 'application/mspowerpoint');
$field_prefix = 'File';
}
$fields = $this->Application->getUnitOption($prefix, 'Fields');
$virtual_fields = $this->Application->getUnitOption($prefix, 'VirtualFields');
$image_count = 0;
foreach ($fields_values as $field_name => $field_value) {
if (preg_match('/^('.$field_prefix.'[\d]+|Primary'.$field_prefix.')$/', $field_name)) {
$fields[$field_name] = $field_options;
$virtual_fields[$field_name] = $field_options;
$this->_createCustomFields($prefix, $field_name, $virtual_fields, $is_image);
$image_count++;
}
}
if (!$image_count) {
// no images found in POST -> create default image fields
$image_count = $this->Application->ConfigValue($prefix.'_MaxImageCount');
if ($is_image) {
$created_count = 1;
$image_names = Array ('Primary' . $field_prefix => '');
while ($created_count < $image_count) {
$image_names[$field_prefix . $created_count] = '';
$created_count++;
}
}
else {
$created_count = 0;
$image_names = Array ();
while ($created_count < $image_count) {
$image_names[$field_prefix . ($created_count + 1)] = '';
$created_count++;
}
}
if ($created_count) {
$this->createUploadFields($prefix, $image_names, $is_image);
}
return ;
}
$this->Application->setUnitOption($prefix, $field_prefix.'Count', $image_count);
$this->Application->setUnitOption($prefix, 'Fields', $fields);
$this->Application->setUnitOption($prefix, 'VirtualFields', $virtual_fields);
}
/**
* Adds ability to create more virtual fields associated with main image/file
*
* @param string $prefix
* @param string $field_name
* @param Array $virtual_fields
* @param bool $is_image
* @return void
* @access protected
*/
protected function _createCustomFields($prefix, $field_name, &$virtual_fields, $is_image = false)
{
$virtual_fields['Delete' . $field_name] = Array ('type' => 'int', 'default' => 0);
if ( $is_image ) {
$virtual_fields[$field_name . 'Alt'] = Array ('type' => 'string', 'default' => '');
}
}
/**
* Downloads file to user
*
* @param string $filename
* @return void
* @access public
*/
public function DownloadFile($filename)
{
header('Content-type: ' . kUtil::mimeContentType($filename));
header('Content-Disposition: attachment; filename="' . basename($filename) . '"');
header('Content-Length: ' . filesize($filename));
readfile($filename);
flush();
}
/**
* Creates folder with given $path
*
* @param string $path
* @return bool
* @access public
*/
public function CheckFolder($path)
{
$result = true;
if (!file_exists($path) || !is_dir($path)) {
$parent_path = preg_replace('#(/|\\\)[^/\\\]+(/|\\\)?$#', '', $path);
$result = $this->CheckFolder($parent_path);
if ($result) {
$result = mkdir($path);
if ($result) {
chmod($path, 0777);
// don't commit any files from created folder
if (file_exists(FULL_PATH . '/CVS')) {
$cvsignore = fopen($path . '/.cvsignore', 'w');
fwrite($cvsignore, '*.*');
fclose($cvsignore);
chmod($path . '/.cvsignore', 0777);
}
}
else {
trigger_error('Cannot create directory "<strong>' . $path . '</strong>"', E_USER_WARNING);
return false;
}
}
}
return $result;
}
/**
* Copies all files and directories from $source to $destination directory. Create destination directory, when missing.
*
* @param string $source
* @param string $destination
* @return bool
* @access public
*/
public function copyFolderRecursive($source, $destination)
{
if ( substr($source, -1) == DIRECTORY_SEPARATOR ) {
$source = substr($source, 0, -1);
$destination .= DIRECTORY_SEPARATOR . basename($source);
}
$iterator = new DirectoryIterator($source);
/* @var $file_info DirectoryIterator */
$result = $this->CheckFolder($destination);
foreach ($iterator as $file_info) {
if ( $file_info->isDot() ) {
continue;
}
$file = $file_info->getFilename();
if ( $file_info->isDir() ) {
$result = $this->copyFolderRecursive($file_info->getPathname(), $destination . DIRECTORY_SEPARATOR . $file);
}
else {
$result = copy($file_info->getPathname(), $destination . DIRECTORY_SEPARATOR . $file);
}
if (!$result) {
trigger_error('Cannot create file/directory "<strong>' . $destination . DIRECTORY_SEPARATOR . $file . '</strong>"', E_USER_WARNING);
break;
}
}
return $result;
}
/**
* Copies all files from $source to $destination directory. Create destination directory, when missing.
*
* @param string $source
* @param string $destination
* @return bool
* @access public
*/
public function copyFolder($source, $destination)
{
if ( substr($source, -1) == DIRECTORY_SEPARATOR ) {
$source = substr($source, 0, -1);
$destination .= DIRECTORY_SEPARATOR . basename($source);
}
$iterator = new DirectoryIterator($source);
/* @var $file_info DirectoryIterator */
$result = $this->CheckFolder($destination);
foreach ($iterator as $file_info) {
if ( $file_info->isDot() || !$file_info->isFile() ) {
continue;
}
$file = $file_info->getFilename();
$result = copy($file_info->getPathname(), $destination . DIRECTORY_SEPARATOR . $file);
if ( !$result ) {
trigger_error('Cannot create file "<strong>' . $destination . DIRECTORY_SEPARATOR . $file . '</strong>"', E_USER_WARNING);
break;
}
}
return $result;
}
/**
* Transforms given path to file into it's url, where each each component is encoded (excluding domain and protocol)
*
* @param string $url
* @return string
* @access public
*/
public function pathToUrl($url)
{
$url = str_replace(DIRECTORY_SEPARATOR, '/', preg_replace('/^' . preg_quote(FULL_PATH, '/') . '(.*)/', '\\1', $url, 1));
$url = implode('/', array_map('rawurlencode', explode('/', $url)));
return rtrim($this->Application->BaseURL(), '/') . $url;
}
/**
* Transforms given url to path to it
*
* @param string $url
* @return string
* @access public
*/
public function urlToPath($url)
{
$base_url = rtrim($this->Application->BaseURL(), '/');
// escape replacement patterns, like "\<number>"
$full_path = preg_replace('/(\\\[\d]+)/', '\\\\\1', FULL_PATH);
$path = preg_replace('/^' . preg_quote($base_url, '/') . '(.*)/', $full_path . '\\1', $url, 1);
return str_replace('/', DIRECTORY_SEPARATOR, rawurldecode($path));
}
/**
* Ensures, that new file will not overwrite any of previously created files with same name
*
* @param string $path
* @param string $name
* @param Array $forbidden_names
* @return string
*/
public function ensureUniqueFilename($path, $name, $forbidden_names = Array())
{
$parts = pathinfo($name);
$ext = '.' . $parts['extension'];
- $filename = mb_substr($parts['basename'], 0, -mb_strlen($ext));
+ $filename = $parts['filename'];
$new_name = $filename . $ext;
+ if ( $parts['dirname'] != '.' ) {
+ $path = rtrim($path, '/') . '/' . ltrim($parts['dirname'], '/');
+ }
+
+ // make sure target folder always exists, especially for cases,
+ // when storage engine folder is supplied as a part of $name
+ $this->CheckFolder($path);
+
while ( file_exists($path . '/' . $new_name) || in_array(rtrim($path, '/') . '/' . $new_name, $forbidden_names) ) {
if ( preg_match('/(' . preg_quote($filename, '/') . '_)([0-9]*)(' . preg_quote($ext, '/') . ')/', $new_name, $regs) ) {
$new_name = $regs[1] . ($regs[2] + 1) . $regs[3];
}
else {
$new_name = $filename . '_1' . $ext;
}
}
+ if ( $parts['dirname'] != '.' ) {
+ $new_name = $parts['dirname'] . '/' . $new_name;
+ }
+
return $new_name;
}
}
\ No newline at end of file
Index: branches/5.2.x/core/units/images/image_event_handler.php
===================================================================
--- branches/5.2.x/core/units/images/image_event_handler.php (revision 14867)
+++ branches/5.2.x/core/units/images/image_event_handler.php (revision 14868)
@@ -1,480 +1,482 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
class ImageEventHandler extends kDBEventHandler {
function mapPermissions()
{
parent::mapPermissions();
$permissions = Array (
'OnCleanImages' => Array ('subitem' => true),
'OnCleanResizedImages' => Array ('subitem' => true),
);
$this->permMapping = array_merge($this->permMapping, $permissions);
}
function mapEvents()
{
parent::mapEvents(); // ensure auto-adding of approve/decine and so on events
$image_events = Array(
'OnAfterCopyToTemp'=>'ImageAction',
'OnBeforeDeleteFromLive'=>'ImageAction',
'OnBeforeCopyToLive'=>'ImageAction',
'OnBeforeItemDelete'=>'ImageAction',
'OnAfterClone'=>'ImageAction',
);
$this->eventMethods = array_merge($this->eventMethods, $image_events);
}
/**
* Get's special of main item for linking with subitem
*
* @param kEvent $event
* @return string
*/
function getMainSpecial(&$event)
{
if ($event->Special == 'list' && !$this->Application->isAdmin) {
// ListImages aggregated tag uses this special
return '';
}
return parent::getMainSpecial($event);
}
/**
* Don't allow to delete primary category item image, when there are no more images
*
* @param kEvent $event
* @param string $type
* @return void
* @access protected
*/
protected function customProcessing(&$event, $type)
{
$object =& $event->getObject();
/* @var $object kDBItem */
if ( $event->Name == 'OnMassDelete' && $type == 'before' ) {
$ids = $event->getEventParam('ids');
$parent_info = $object->getLinkedInfo($event->Special);
$sql = 'SELECT ImageId
FROM ' . $object->TableName . '
WHERE DefaultImg = 1 AND ' . $parent_info['ForeignKey'] . ' = ' . $parent_info['ParentId'];
$primary_file_id = $this->Conn->GetOne($sql);
if ( $primary_file_id ) {
$file_id_index = array_search($primary_file_id, $ids);
if ( $file_id_index ) {
// allow deleting of primary product file, when there is another file to make primary
$sql = 'SELECT COUNT(*)
FROM ' . $object->TableName . '
WHERE DefaultImg = 0 AND ' . $parent_info['ForeignKey'] . ' = ' . $parent_info['ParentId'];
$non_primary_file_count = $this->Conn->GetOne($sql);
if ( $non_primary_file_count ) {
unset($ids[$file_id_index]);
}
}
}
$event->setEventParam('ids', $ids);
}
switch ( $type ) {
case 'before' :
// empty unused fields
$object->SetDBField($object->GetDBField('LocalImage') ? 'Url' : 'LocalPath', '');
$object->SetDBField($object->GetDBField('LocalThumb') ? 'ThumbUrl' : 'ThumbPath', '');
if ( $object->GetDBField('SameImages') ) {
$object->SetDBField('LocalImage', 1);
$object->SetDBField('LocalPath', '');
$object->SetDBField('Url', '');
}
break;
case 'after':
// make sure, that there is only one primary image for the item
if ( $object->GetDBField('DefaultImg') ) {
$sql = 'UPDATE ' . $object->TableName . '
SET DefaultImg = 0
WHERE ResourceId = ' . $object->GetDBField('ResourceId') . ' AND ImageId <> ' . $object->GetID();
$this->Conn->Query($sql);
}
break;
}
}
/**
* Performs temp-table related action on current image record
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function ImageAction(&$event)
{
$id = $event->getEventParam('id');
- $object =& $this->Application->recallObject($event->Prefix.'.-item', $event->Prefix, Array ('skip_autoload' => true));
+ $object =& $this->Application->recallObject($event->Prefix . '.-item', $event->Prefix, Array ('skip_autoload' => true));
/* @var $object kDBItem */
- if (in_array($event->Name, Array('OnBeforeDeleteFromLive','OnAfterClone')) ) {
+ if ( in_array($event->Name, Array ('OnBeforeDeleteFromLive', 'OnAfterClone')) ) {
$object->SwitchToLive();
}
- elseif ($event->Name == 'OnBeforeItemDelete') {
+ elseif ( $event->Name == 'OnBeforeItemDelete' ) {
// keep current table
}
else {
$object->SwitchToTemp();
}
$object->Load($id);
- $fields = Array('LocalPath' => 'LocalImage', 'ThumbPath' => 'LocalThumb');
+ $file_helper =& $this->Application->recallObject('FileHelper');
+ /* @var $file_helper FileHelper */
+
+ $fields = Array ('LocalPath' => 'LocalImage', 'ThumbPath' => 'LocalThumb');
+
foreach ($fields as $a_field => $mode_field) {
- $file = $object->GetField($a_field);
- if (!$file) continue;
- $source_file = FULL_PATH.$file;
+ $file = $object->GetDBField($a_field);
+
+ if ( !$file ) {
+ continue;
+ }
+
+ $source_file = FULL_PATH . $file;
switch ($event->Name) {
// Copy image files to pending dir and update corresponding fields in temp record
- // Checking for existing files and renaming if nessessary - two users may upload same pending files at the same time!
+ // Checking for existing files and renaming if necessary - two users may upload same pending files at the same time!
case 'OnAfterCopyToTemp':
- $new_file = IMAGES_PENDING_PATH . $this->ValidateFileName(FULL_PATH.IMAGES_PENDING_PATH, basename($file));
- $dest_file = FULL_PATH.$new_file;
- copy($source_file, $dest_file);
+ $file = preg_replace('/^' . preg_quote(IMAGES_PATH, '/') . '/', IMAGES_PENDING_PATH, $file, 1);
+ $new_file = $file_helper->ensureUniqueFilename(FULL_PATH, $file);
+
+ $dst_file = FULL_PATH . $new_file;
+ copy($source_file, $dst_file);
+
$object->SetFieldOption($a_field, 'skip_empty', false);
$object->SetDBField($a_field, $new_file);
break;
- // Copy image files to live dir (checking if fileexists and renameing if nessessary)
+ // Copy image files to live dir (checking if file exists and renaming if necessary)
// and update corresponding fields in temp record (which gets copied to live automatically)
case 'OnBeforeCopyToLive':
- if ( $object->GetDBField($mode_field) ) { // if image is local
- // rename file if it exists in live folder
- $new_file = IMAGES_PATH . $this->ValidateFileName(FULL_PATH.IMAGES_PATH, basename($file));
- $dest_file = FULL_PATH.$new_file;
- rename($source_file, $dest_file);
+ if ( $object->GetDBField($mode_field) ) {
+ // if image is local -> rename file if it exists in live folder
+ $file = preg_replace('/^' . preg_quote(IMAGES_PENDING_PATH, '/') . '/', IMAGES_PATH, $file, 1);
+ $new_file = $file_helper->ensureUniqueFilename(FULL_PATH, $file);
+
+ $dst_file = FULL_PATH . $new_file;
+ rename($source_file, $dst_file);
}
- else { // if image is remote url - remove local file (if any), update local file field with empty value
- if (file_exists($source_file)) @unlink($source_file);
+ else {
+ // if image is remote url - remove local file (if any), update local file field with empty value
+ if ( file_exists($source_file) ) {
+ @unlink($source_file);
+ }
+
$new_file = '';
}
+
$object->SetFieldOption($a_field, 'skip_empty', false);
$object->SetDBField($a_field, $new_file);
break;
case 'OnBeforeDeleteFromLive': // Delete image files from live folder before copying over from temp
- case 'OnBeforeItemDelete': // Delete image files when deleteing Image object
- @unlink(FULL_PATH.$file);
+ case 'OnBeforeItemDelete': // Delete image files when deleting Image object
+ @unlink(FULL_PATH . $file);
break;
- case 'OnAfterClone': // Copy files when cloning objects, renaming it on the fly
- $path_info = pathinfo($file);
- $new_file = $path_info['dirname'].'/'.$this->ValidateFileName(FULL_PATH.$path_info['dirname'], $path_info['basename']);
- $dest_file = FULL_PATH . $new_file;
- copy($source_file, $dest_file);
+ case 'OnAfterClone':
+ // Copy files when cloning objects, renaming it on the fly
+ $new_file = $file_helper->ensureUniqueFilename(FULL_PATH, $file);
+ $dst_file = FULL_PATH . $new_file;
+ copy($source_file, $dst_file);
+
$object->SetFieldOption($a_field, 'skip_empty', false);
$object->SetDBField($a_field, $new_file);
break;
}
}
- if ( in_array($event->Name, Array('OnAfterClone', 'OnBeforeCopyToLive', 'OnAfterCopyToTemp')) ) {
- $object->Update(null, true);
- }
- }
- function ValidateFileName($path, $name)
- {
- $parts = pathinfo($name);
- $ext = '.'.$parts['extension'];
- $filename = mb_substr($parts['basename'], 0, -mb_strlen($ext));
- $new_name = $filename.$ext;
- while ( file_exists($path.'/'.$new_name) )
- {
- if ( preg_match('/('.preg_quote($filename, '/').'_)([0-9]*)('.preg_quote($ext, '/').')/', $new_name, $regs) ) {
- $new_name = $regs[1].($regs[2]+1).$regs[3];
- }
- else {
- $new_name = $filename.'_1'.$ext;
- }
+ if ( in_array($event->Name, Array ('OnAfterClone', 'OnBeforeCopyToLive', 'OnAfterCopyToTemp')) ) {
+ $object->Update(null, true);
}
- return $new_name;
}
/**
* Sets primary image of user/category/category item
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnSetPrimary(&$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
$object->SetDBField('DefaultImg', 1);
$object->Update();
}
/**
* Occurs before updating item
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnBeforeItemUpdate(&$event)
{
parent::OnBeforeItemUpdate($event);
$this->processImageStatus($event);
}
/**
* Occurs after creating item
*
* @param kEvent $event
* @return void
* @access protected
*/
protected function OnAfterItemCreate(&$event)
{
parent::OnAfterItemCreate($event);
$this->processImageStatus($event);
$object =& $event->getObject();
/* @var $object kDBItem */
$object->Update();
}
/**
* Occurs before item changed
*
* @param kEvent $event
*/
function processImageStatus(&$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
$id = $object->GetDBField('ResourceId');
$sql = 'SELECT ImageId
FROM ' . $object->TableName . '
WHERE ResourceId = ' . $id . ' AND DefaultImg = 1';
$primary_image_id = $this->Conn->GetOne($sql);
if ( !$primary_image_id ) {
$object->SetDBField('DefaultImg', 1);
}
if ( $object->GetDBField('DefaultImg') && $object->Validate() ) {
$sql = 'UPDATE ' . $object->TableName . '
SET DefaultImg = 0
WHERE ResourceId = ' . $id . ' AND ImageId <> ' . $object->GetDBField('ImageId');
$this->Conn->Query($sql);
$object->SetDBField('Enabled', 1);
}
}
/**
* Apply any custom changes to list's sql query
*
* @param kEvent $event
* @return void
* @access protected
* @see kDBEventHandler::OnListBuild()
*/
protected function SetCustomQuery(&$event)
{
parent::SetCustomQuery($event);
$object =& $event->getObject();
/* @var $object kDBList */
if (!$this->Application->isAdminUser) {
$object->addFilter('active', '%1$s.Enabled = 1');
}
$product_id = $event->getEventParam('product_id');
if ($product_id) {
$object->removeFilter('parent_filter');
$sql = 'SELECT ResourceId
FROM '.$this->Application->getUnitOption('p', 'TableName').'
WHERE ProductId = '.$product_id;
$resource_id = (int) $this->Conn->GetOne($sql);
$object->addFilter('product_images', '%1$s.ResourceId = '.$resource_id);
}
/********************************************/
$search_helper =& $this->Application->recallObject('SearchHelper');
/* @var $search_helper kSearchHelper */
$types = $event->getEventParam('types');
$except_types = $event->getEventParam('except');
$type_clauses = $this->getTypeClauses($event);
$search_helper->SetComplexFilter($event, $type_clauses, $types, $except_types);
}
/**
* Return type clauses for list bulding on front
*
* @param kEvent $event
* @return Array
*/
function getTypeClauses(&$event)
{
$type_clauses = Array ();
$type_clauses['additional']['include'] = '%1$s.DefaultImg != 1';
$type_clauses['additional']['except'] = '%1$s.DefaultImg = 1';
$type_clauses['additional']['having_filter'] = false;
return $type_clauses;
}
/**
* [AGENT] Remove unused images from "/system/images" and "/system/images/pending" folders
*
* @param kEvent $event
*/
function OnCleanImages(&$event)
{
// 1. get images, that are currently in use
$active_images = $this->_getActiveImages( $this->Application->getUnitOption('img', 'TableName') );
$active_images[] = 'noimage.gif';
// 2. get images on disk
$this->_deleteUnusedImages(FULL_PATH . IMAGES_PATH, $active_images);
// 3. get images in use from "images/pending" folder
$active_images = $this->_getPendingImages();
// 4. get image on disk
$this->_deleteUnusedImages(FULL_PATH . IMAGES_PENDING_PATH, $active_images);
}
/**
* Gets image filenames (no path) from given table
*
* @param string $image_table
* @return Array
*/
function _getActiveImages($image_table)
{
$sql = 'SELECT LocalPath, ThumbPath
FROM ' . $image_table . '
WHERE COALESCE(LocalPath, "") <> "" OR COALESCE(ThumbPath) <> ""';
$images = $this->Conn->Query($sql);
$active_images = Array ();
foreach ($images as $image) {
if ($image['LocalPath']) {
$active_images[] = basename($image['LocalPath']);
}
if ($image['ThumbPath']) {
$active_images[] = basename($image['ThumbPath']);
}
}
return $active_images;
}
/**
* Gets active images, that are currently beeing edited inside temporary tables
*
* @return Array
*/
function _getPendingImages()
{
$tables = $this->Conn->GetCol('SHOW TABLES');
$mask_edit_table = '/'.TABLE_PREFIX.'ses_(.*)_edit_' . TABLE_PREFIX . 'Images/';
$active_images = Array ();
foreach ($tables as $table) {
if (!preg_match($mask_edit_table, $table)) {
continue;
}
$active_images = array_unique( array_merge($active_images, $this->_getActiveImages($table)) );
}
return $active_images;
}
/**
* Deletes all files in given path, except of given $active_images
*
* @param string $path
* @param Array $active_images
*/
function _deleteUnusedImages($path, &$active_images)
{
$images = glob($path . '*.*');
if ($images) {
$images = array_map('basename', $images);
// delete images, that are on disk, but are not mentioned in Images table
$delete_images = array_diff($images, $active_images);
foreach ($delete_images as $delete_image) {
unlink($path . $delete_image);
}
}
}
/**
* [AGENT] Remove all images from "/system/images/resized" and "/system/images/pending/resized" folders
*
* @param kEvent $event
*/
function OnCleanResizedImages(&$event)
{
$images = glob(FULL_PATH . IMAGES_PATH . 'resized/*.*');
if ($images) {
foreach ($images as $image) {
unlink($image);
}
}
$images = glob(FULL_PATH . IMAGES_PENDING_PATH . 'resized/*.*');
if ($images) {
foreach ($images as $image) {
unlink($image);
}
}
}
}
\ No newline at end of file
Event Timeline
Log In to Comment