Page Menu
Home
In-Portal Phabricator
Search
Configure Global Search
Log In
Files
F1054749
file_helper.php
No One
Temporary
Actions
Download 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
Mon, Jul 7, 5:23 AM
Size
14 KB
Mime Type
text/x-php
Expires
Wed, Jul 9, 5:23 AM (16 h, 48 m)
Engine
blob
Format
Raw Data
Handle
680386
Attached To
rINP In-Portal
file_helper.php
View Options
<?php
/**
* @version $Id: file_helper.php 16692 2021-08-31 09:24:09Z alex $
* @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
.
'CatalogFiles
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
(
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
)
{
$fields_values
=
current
(
$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
)
{
$this
->
Application
->
setContentType
(
kUtil
::
mimeContentType
(
$filename
),
false
);
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
(
'#(/|
\\\)
[^/
\\\]
+(/|
\\\)
?$#'
,
''
,
rtrim
(
$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 DirectoryIterator $file_info */
$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 DirectoryIterator $file_info */
$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
));
// TODO: why?
$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
,
kUtil
::
unescape
(
$path
,
kUtil
::
ESCAPE_URL
));
}
/**
* Makes given paths DocumentRoot agnostic.
*
* @param array $paths List of file paths.
*
* @return array
*/
public
function
makeRelative
(
array
$paths
)
{
foreach
(
$paths
as
$index
=>
$path
)
{
$replaced_count
=
0
;
$relative_path
=
preg_replace
(
'/^'
.
preg_quote
(
FULL_PATH
,
'/'
)
.
'/'
,
''
,
$path
,
1
,
$replaced_count
);
if
(
$replaced_count
===
1
)
{
$paths
[
$index
]
=
$relative_path
;
}
}
return
$paths
;
}
/**
* 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
=
$parts
[
'filename'
];
$path
=
rtrim
(
$path
,
'/'
);
$original_checked
=
false
;
$new_name
=
$filename
.
$ext
;
if
(
$parts
[
'dirname'
]
!=
'.'
)
{
$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
(
$path
.
'/'
.
$new_name
,
$forbidden_names
))
{
if
(
preg_match
(
'/(.*)_([0-9]*)('
.
preg_quote
(
$ext
,
'/'
)
.
')/'
,
$new_name
,
$regs
)
)
{
$new_name
=
$regs
[
1
]
.
'_'
.
((
int
)
$regs
[
2
]
+
1
)
.
$regs
[
3
];
}
elseif
(
$original_checked
)
{
$new_name
=
$filename
.
'_1'
.
$ext
;
}
$original_checked
=
true
;
}
if
(
$parts
[
'dirname'
]
!=
'.'
)
{
$new_name
=
$parts
[
'dirname'
]
.
'/'
.
$new_name
;
}
return
$new_name
;
}
/**
* Checks, that given file name has on of provided file extensions
*
* @param string $filename Filename.
* @param string $file_types File types.
*
* @return boolean
*/
public
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
;
}
}
Event Timeline
Log In to Comment